recvstats.sh.in
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:14k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. #! @SCRIPT_SH@
  2. # $Id: recvstats.sh.in,v 1.3 2008/06/18 05:12:47 faxguy Exp $
  3. #
  4. # HylaFAX Facsimile Software
  5. #
  6. # Copyright (c) 1990-1996 Sam Leffler
  7. # Copyright (c) 1991-1996 Silicon Graphics, Inc.
  8. # HylaFAX is a trademark of Silicon Graphics
  9. # Permission to use, copy, modify, distribute, and sell this software and 
  10. # its documentation for any purpose is hereby granted without fee, provided
  11. # that (i) the above copyright notices and this permission notice appear in
  12. # all copies of the software and related documentation, and (ii) the names of
  13. # Sam Leffler and Silicon Graphics may not be used in any advertising or
  14. # publicity relating to the software without the specific, prior written
  15. # permission of Sam Leffler and Silicon Graphics.
  16. # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  17. # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  18. # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  19. # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20. # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21. # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22. # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23. # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24. # OF THIS SOFTWARE.
  25. #
  26. # security
  27. NOCLOBBER_ON=@NOCLOBBER_ON@
  28. NOCLOBBER_OFF=@NOCLOBBER_OFF@
  29. #
  30. # Print Statistics about Received Facsimile.
  31. #
  32. SPOOL=@SPOOL@
  33. . $SPOOL/bin/common-functions
  34. test -f $SPOOL/etc/setup.cache || {
  35.     cat<<EOF
  36. FATAL ERROR: $SPOOL/etc/setup.cache is missing!
  37. The file $SPOOL/etc/setup.cache is not present.  This
  38. probably means the machine has not been setup using the faxsetup(@MANNUM1_8@)
  39. command.  Read the documentation on setting up HylaFAX before you
  40. startup a server system.
  41. EOF
  42.     hfExit 1
  43. }
  44. . $SPOOL/etc/setup.cache
  45. FILES=
  46. SORTKEY=-sender # default is to sort by sender
  47. TODAY="`date +'%D %H:%M'`"
  48. AGE="360" # report statistics for last year
  49. SINCEDT=
  50. ENDDT=
  51. while [ x"$1" != x"" ] ; do
  52.     case $1 in
  53.     -send*|-csi|-dest*|-speed|-rate|-format|-cidname|-cidnumber)
  54.     SORTKEY=$1;;
  55.     -age)   shift; AGE=$1;;
  56.     -since) shift; SINCEDT=$1;;
  57.     -end) shift; ENDDT=$1;;
  58.     -*)     echo "Usage: $0 [-sortkey] [-age days] [-since date] [-end date] [files]"
  59.     hfExit 1
  60.     ;;
  61.     *)     FILES="$FILES $1";;
  62.     esac
  63.     shift
  64. done
  65. if [ -z "$FILES" ]; then
  66.     FILES=$SPOOL/etc/xferfaxlog
  67. fi
  68. #
  69. # Construct awk rules to collect information according
  70. # to the desired sort key.  There are multiple rules for
  71. # dealing with the different formats that have existed
  72. # over time.
  73. #
  74. case $SORTKEY in
  75. -send*|-csi)
  76.     AWKRULES='
  77. $2 == "RECV" && NF == 9  { acct($3, $7, $8, $5, $6, $9); }
  78. $2 == "RECV" && NF == 11 { acct($6, $9, $10, $7, $8, $11); }
  79. $2 == "RECV" && NF == 12 { acct($7, $10, $11, $8, $9, $12); }
  80. $2 == "RECV" && NF == 13 { acct($9, $11, $12, getBR($10), getDF($10), $13); }
  81. $2 == "RECV" && NF == 14 { acct($9, $11, $13, getBR($10), getDF($10), $14); }
  82. $2 == "RECV" && NF == 16 { acct($9, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  83. $2 == "RECV" && NF == 17 { acct($9, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  84. $2 == "RECV" && NF == 18 { acct($9, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  85. $2 == "RECV" && NF == 19 { acct($9, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  86. $2 == "RECV" && NF == 20 { acct($9, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  87. '
  88.     ;;
  89. -cidname)
  90.     AWKRULES='
  91. $2 == "RECV" && NF == 16 { acct($15, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  92. $2 == "RECV" && NF == 17 { acct($15, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  93. $2 == "RECV" && NF == 18 { acct($15, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  94. $2 == "RECV" && NF == 19 { acct($15, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  95. $2 == "RECV" && NF == 20 { acct($15, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  96. '
  97.     ;;
  98. -cidnumber)
  99.     AWKRULES='
  100. $2 == "RECV" && NF == 16 { acct($16, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  101. $2 == "RECV" && NF == 17 { acct($16, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  102. $2 == "RECV" && NF == 18 { acct($16, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  103. $2 == "RECV" && NF == 19 { acct($16, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  104. $2 == "RECV" && NF == 20 { acct($16, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  105. '
  106.     ;;
  107. -dest*)
  108.     AWKRULES='
  109. $2 == "RECV" && NF == 9  { acct($4, $7, $8, $5, $6, $9); }
  110. $2 == "RECV" && NF == 11 { acct($5, $9, $10, $7, $8, $11); }
  111. $2 == "RECV" && NF == 12 { acct($6, $10, $11, $8, $9, $12); }
  112. $2 == "RECV" && NF == 14 { acct($8, $11, $13, getBR($10), getDF($10), $14); }
  113. $2 == "RECV" && NF == 16 { acct($8, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  114. $2 == "RECV" && NF == 17 { acct($8, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  115. $2 == "RECV" && NF == 18 { acct($8, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  116. $2 == "RECV" && NF == 19 { acct($8, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  117. $2 == "RECV" && NF == 20 { acct($8, $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  118. '
  119.     ;;
  120. -speed|-rate)
  121.     AWKRULES='
  122. $2 == "RECV" && NF == 9  { acct($5, $7, $8, $5, $6, $9); }
  123. $2 == "RECV" && NF == 11 { acct($7, $9, $10, $7, $8, $11); }
  124. $2 == "RECV" && NF == 12 { acct($8, $10, $11, $8, $9, $12); }
  125. $2 == "RECV" && NF == 13 { acct(getBR($10), $11, $12, getBR($10), getDF($10), $13); }
  126. $2 == "RECV" && NF == 14 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14); }
  127. $2 == "RECV" && NF == 16 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  128. $2 == "RECV" && NF == 17 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  129. $2 == "RECV" && NF == 18 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  130. $2 == "RECV" && NF == 19 { acct(getBR($10), $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  131. $2 == "RECV" && NF == 20 { acct(getBR($10), $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  132. '
  133.     ;;
  134. -format)
  135.     AWKRULES='
  136. $2 == "RECV" && NF == 9  { acct($6, $7, $8, $5, $6, $9); }
  137. $2 == "RECV" && NF == 11 { acct($8, $9, $10, $7, $8, $11); }
  138. $2 == "RECV" && NF == 12 { acct($9, $10, $11, $8, $9, $12); }
  139. $2 == "RECV" && NF == 13 { acct(getDF($10), $11, $12, getBR($10), getDF($10), $13); }
  140. $2 == "RECV" && NF == 14 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14); }
  141. $2 == "RECV" && NF == 16 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  142. $2 == "RECV" && NF == 17 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  143. $2 == "RECV" && NF == 18 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
  144. $2 == "RECV" && NF == 19 { acct(getDF($10), $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  145. $2 == "RECV" && NF == 20 { acct(getDF($10), $11, $13, getBR($10), getDFfromDCS($19), $14, $15, $16); }
  146. '
  147.     ;;
  148. esac
  149. #
  150. # Generate an awk program to process the statistics file.
  151. #
  152. SetupPrivateTmp
  153. tmpAwk=$TMPDIR/xferfax$$
  154. ($CAT<<'EOF'
  155. #
  156. # Setup date conversion data structures.
  157. #
  158. function setupDateTimeStuff()
  159. {
  160.     daysInMonth[ 0] = 31; daysInMonth[ 1] = 28; daysInMonth[ 2] = 31;
  161.     daysInMonth[ 3] = 30; daysInMonth[ 4] = 31; daysInMonth[ 5] = 30;
  162.     daysInMonth[ 6] = 31; daysInMonth[ 7] = 31; daysInMonth[ 8] = 30;
  163.     daysInMonth[ 9] = 31; daysInMonth[10] = 30; daysInMonth[11] = 31;
  164.     FULLDAY = 24 * 60 * 60;
  165. }
  166. #
  167. # Convert hh:mm:ss to seconds.
  168. #
  169. function cvtTime(s)
  170. {
  171.     t = i = 0;
  172.     for (n = split(s, a, ":"); i++ < n; )
  173. t = t*60 + a[i];
  174.     return t;
  175. }
  176. #
  177. # Convert MM/DD/YY hh:mm to seconds.
  178. # NB: this does not deal with leap years.
  179. #
  180. function cvtDateTime(s)
  181. {
  182.     yday = substr(s,7,2);
  183.     if (yday < 70)
  184.         yday += 30;
  185.     else 
  186.         yday -= 70;
  187.     yday = yday*365 + substr(s,4,2) - 1;
  188.     mon = substr(s,1,2) - 1;
  189.     for (i = 0; i < mon; i++)
  190. yday += daysInMonth[i];
  191.     return yday*FULLDAY + cvtTime(substr(s,10) ":00");
  192. }
  193. function setupDigits()
  194. {
  195.   digits[0] = "0"; digits[1] = "1"; digits[2] = "2";
  196.   digits[3] = "3"; digits[4] = "4"; digits[5] = "5";
  197.   digits[6] = "6"; digits[7] = "7"; digits[8] = "8";
  198.   digits[9] = "9";
  199. }
  200. #
  201. # Format seconds as hh:mm:ss.
  202. #
  203. function fmtTime(t)
  204. {
  205.     v = int(t/3600);
  206.     result = "";
  207.     if (v > 0) {
  208. if (v >= 10)
  209.     result = digits[int(v/10)];
  210. result = result digits[int(v%10)] ":";
  211. t -= v*3600;
  212.     }
  213.     v = int(t/60);
  214.     if (v >= 10 || result != "")
  215. result = result digits[int(v/10)];
  216.     result = result digits[int(v%10)];
  217.     t -= v*60;
  218.     return (result ":" digits[int(t/10)] digits[int(t%10)]);
  219. }
  220. #
  221. # Setup map for histogram calculations
  222. # and indexed table for decoding params.
  223. #
  224. function setupMaps(s, map, names)
  225. {
  226.     n = split(s, a, ":");
  227.     for (i = 1; i <= n; i++) {
  228. map[a[i]] = i;
  229. names[i-1] = a[i];
  230.     }
  231. }
  232. #
  233. # Add pages to a histogram.
  234. #
  235. function addToMap(key, ix, pages, map)
  236. {
  237.     if (key == "") {
  238. for (i in map)
  239.     key = key ":";
  240.     }
  241.     n = split(key, a, ":");
  242.     a[map[ix]] += pages;
  243.     t = a[1];
  244.     for (i = 2; i <= n; i++)
  245.       t = t ":" a[i];
  246.     return t;
  247. }
  248. #
  249. # Return the name of the item with the
  250. # largest number of accumulated pages.
  251. #
  252. function bestInMap(totals, map)
  253. {
  254.    n = split(totals, a, ":");
  255.    imax = 1; max = -1;
  256.    for (j = 1; j <= n; j++)
  257.        if (a[j] > max) {
  258.    max = a[j];
  259.    imax = j;
  260.        }
  261.    split(map, a, ":");
  262.    return a[imax];
  263. }
  264. #
  265. # Sort array a[l..r]
  266. #
  267. function qsort(a, l, r) {
  268.     i = l;
  269.     k = r+1;
  270.     item = a[l];
  271.     for (;;) {
  272. while (i < r) {
  273.             i++;
  274.     if (a[i] >= item)
  275. break;
  276.         }
  277. while (k > l) {
  278.             k--;
  279.     if (a[k] <= item)
  280. break;
  281.         }
  282.         if (i >= k)
  283.     break;
  284. t = a[i]; a[i] = a[k]; a[k] = t;
  285.     }
  286.     t = a[l]; a[l] = a[k]; a[k] = t;
  287.     if (k != 0 && l < k-1)
  288. qsort(a, l, k-1);
  289.     if (k+1 < r)
  290. qsort(a, k+1, r);
  291. }
  292. function getBR(params)
  293. {
  294.     if ((int(int(params) / 2097152) % 2) == 1) {
  295. return brNames[int(int(params) / 8) % 16];
  296.     } else {
  297. return brNames[int(int(params) / 2) % 8];
  298.     }
  299. }
  300. function getDF(params)
  301. {
  302.     if ((int(int(params) / 2097152) % 2) == 1) {
  303. return dfNames[int(int(params) / 16384) % 4];
  304.     } else {
  305. return dfNames[int(int(params) / 512) % 4];
  306.     }
  307. }
  308. function hex(n) {
  309.     # GNU Awk 3.1.3 has a type conversion error from hex strings,
  310.     # so we have to do it the hard way
  311.     val = 0;
  312.     for (position = 1; position <= length(n); position++) {
  313. val = val * 16;
  314. char = tolower(substr(n, position, 1));
  315. if (char == "a") val = val + 10;
  316. else if (char == "b") val = val + 11;
  317. else if (char == "c") val = val + 12;
  318. else if (char == "d") val = val + 13;
  319. else if (char == "e") val = val + 14;
  320. else if (char == "f") val = val + 15;
  321. else val = val + int(char);
  322.     }
  323.     return val;
  324. }
  325. function isBitSet(bit, dcs) {
  326.     byte = int((bit - 1) / 8);
  327.     pos = 7 - ((bit - 1) % 8);
  328.     dcsbyte = hex(substr(dcs, (byte*3+1), 2));
  329.     return int(int(dcsbyte / (2 ^ pos)) % 2);
  330. }
  331. function getDFfromDCS(dcs)
  332. {
  333.     if (substr(dcs, 1, 1) == """)
  334. dcs = substr(dcs, 2);
  335.     if (substr(dcs, length(dcs), 1) == """)
  336. dcs = substr(dcs, 1, length(dcs)-1);
  337.     if (isBitSet(68, dcs)) {
  338. if (isBitSet(69, dcs))
  339.     return dfNames[6];
  340. return dfNames[5];
  341.     }
  342.     if (isBitSet(78, dcs) || isBitSet(79, dcs))
  343. return dfNames[4];
  344.     if (isBitSet(31, dcs))
  345. return dfNames[3];
  346.     if (isBitSet(26, dcs))
  347. return dfNames[2];
  348.     if (isBitSet(16, dcs))
  349. return dfNames[1];
  350.     return dfNames[0];
  351. }
  352. #
  353. # Accumulate a statistics record.
  354. #
  355. function acct(key, pages, time, br, df, status, cidname, cidnumber)
  356. {
  357.     if (cvtDateTime($1) < KEEPSINCE || cvtDateTime($1) > KEEPEND)
  358. return;
  359.     gsub(""", "", key);
  360.     gsub("^ +", "", key);
  361.     gsub(" +$", "", key);
  362.     recvpages[key] += pages;
  363.     if (pages == 0 && time > 60)
  364. time = 0;
  365.     recvtime[key] += cvtTime(time);
  366.     gsub(""", "", status);
  367.     if (status != "")
  368. recverrs[key]++;
  369.     gsub(""", "", br);
  370.     recvrate[key] = addToMap(recvrate[key], br, pages, rateMap);
  371.     gsub(""", "", df);
  372.     recvdata[key] = addToMap(recvdata[key], df, pages, dataMap);
  373.     gsub(""", "", cidname);
  374.     gsub(""", "", cidnumber);
  375.     lastcidname[key] = cidname;
  376.     lastcidnumber[key] = cidnumber;
  377. }
  378. #
  379. # Print a rule between the stats and the totals line.
  380. #
  381. function printRule(n, s)
  382. {
  383.     r = "";
  384.     while (n-- >= 0)
  385. r = r s;
  386.     printf "%sn", r;
  387. }
  388. BEGIN { FS="t";
  389.   rates = "2400:4800:7200:9600:12000:14400:16800:19200:21600:24000:26400:28800:31200:33600";
  390.   setupMaps(rates, rateMap, brNames);
  391.   datas = "1-D MH:2-D MR:2-D Uncompressed Mode:2-D MMR:JBIG:JPEG Greyscale:JPEG Full-color";
  392.   setupMaps(datas, dataMap, dfNames);
  393.   setupDateTimeStuff();
  394.   if (SINCEDT == "")
  395.       KEEPSINCE = cvtDateTime(TODAY) - AGE*FULLDAY;
  396.   else
  397.       KEEPSINCE = cvtDateTime(SINCEDT);
  398.   if (ENDDT == "")
  399.       KEEPEND = cvtDateTime(TODAY);
  400.   else
  401.       KEEPEND = cvtDateTime(ENDDT);
  402. }
  403. END { OFS="t"; setupDigits();
  404.   maxlen = 15;
  405.   nsorted = 0;
  406.   for (i in recvpages) {
  407.       l = length(i);
  408.       if (l > maxlen)
  409. maxlen = l;
  410.       sorted[nsorted++] = i;
  411.   }
  412.   qsort(sorted, 0, nsorted-1);
  413.   fmt = "%-" maxlen "." maxlen "s" " %-" maxlen "." maxlen "s" " %-" maxlen "." maxlen "s"; # e.g. %-24.24s
  414.   printf fmt " %5s %8s %6s %4s %7s %7sn",
  415.       "Sender", "CIDName", "CIDNumber", "Pages", "Time", "Pg/min",
  416.       "Errs", "TypRate", "TypData";
  417.   tpages = 0;
  418.   ttime = 0;
  419.   terrs = 0;
  420.   for (k = 0; k < nsorted; k++) {
  421.       i = sorted[k];
  422.       t = recvtime[i]/60; if (t == 0) t = 1;
  423.       n = recvpages[i]; if (n == 0) n = 1;
  424.       brate = best
  425.       printf fmt " %5d %8s %6.1f %4d %7d %7sn",
  426.   i, lastcidname[i], lastcidnumber[i], recvpages[i], fmtTime(recvtime[i]),
  427.   recvpages[i] / t, recverrs[i],
  428.   bestInMap(recvrate[i], rates),
  429.   bestInMap(recvdata[i], datas);
  430. tpages += recvpages[i];
  431. ttime += recvtime[i];
  432. terrs += recverrs[i];
  433.   }
  434.   printRule(maxlen+1+maxlen+1+maxlen+1+5+1+8+6+1+4+1+7+1+7, "-");
  435.   t = ttime/60; if (t == 0) t = 1;
  436.   printf fmt " %5d %8s %6.1f %4dn",
  437.       "Total", "", "", tpages, fmtTime(ttime), tpages/t, terrs;
  438. }
  439. EOF
  440. echo "$AWKRULES"
  441. )>$tmpAwk
  442. $AWK -f $tmpAwk -v TODAY="$TODAY" -v AGE="$AGE" -v SINCEDT="$SINCEDT" -v ENDDT="$ENDDT" $FILES
  443. # cleanup
  444. hfExit 0