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

传真(Fax)编程

开发平台:

C/C++

  1. #! @SCRIPT_SH@
  2. # $Id: xferfaxstats.sh.in,v 1.5 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. #
  27. # Print Statistics about Transmitted Facsimile.
  28. #
  29. SPOOL=@SPOOL@
  30. . $SPOOL/bin/common-functions
  31. test -f $SPOOL/etc/setup.cache || {
  32.     cat<<EOF
  33. FATAL ERROR: $SPOOL/etc/setup.cache is missing!
  34. The file $SPOOL/etc/setup.cache is not present.  This
  35. probably means the machine has not been setup using the faxsetup(@MANNUM1_8@)
  36. command.  Read the documentation on setting up HylaFAX before you
  37. startup a server system.
  38. EOF
  39.     hfExit 1
  40. }
  41. . $SPOOL/etc/setup.cache
  42. FILES=
  43. SORTKEY=-sender # default is to sort by sender
  44. MAPNAMES=no # default is to not map email addresses (NIS)
  45. TODAY="`date +'%D %H:%M'`"
  46. AGE="360" # report statistics for last year
  47. SINCEDT=
  48. ENDDT=
  49. while [ x"$1" != x"" ] ; do
  50.     case $1 in
  51.     -send*|-csi|-dest*|-speed|-rate|-format|-job*|-dev*)
  52.     SORTKEY=$1;;
  53.     -nomap) MAPNAMES=no;;
  54.     -map)   MAPNAMES=yes;;
  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] [-nomap] [files]"; hfExit 1;;
  59.     *)     FILES="$FILES $1";;
  60.     esac
  61.     shift
  62. done
  63. if [ -z "$FILES" ]; then
  64.     FILES=$SPOOL/etc/xferfaxlog
  65. fi
  66. #
  67. # Construct awk rules to collect information according
  68. # to the desired sort key.  There are multiple rules for
  69. # each; to deal with the different formats that have
  70. # existed over time.
  71. #
  72. case $SORTKEY in
  73. -send*)
  74.     AWKRULES='
  75. $2 == "SEND" && NF == 9  { acct($3, $4, $7, $8, $5, $6, $9); }
  76. $2 == "SEND" && NF == 11 { acct($4, $5, $9, $10, $7, $8, $11); }
  77. $2 == "SEND" && NF == 12 { acct($5, $6, $10, $11, $8, $9, $12); }
  78. $2 == "SEND" && NF == 13 { acct($7, $8, $11, $12, getBR($10), getDF($10), $13); }
  79. $2 == "SEND" && NF == 14 { acct($7, $8, $11, $13, getBR($10), getDF($10), $14); }
  80. $2 == "SEND" && NF == 16 { acct($7, $8, $11, $13, getBR($10), getDF($10), $14); }
  81. $2 == "SEND" && NF == 17 { acct($7 " (" $17 ")", $8, $11, $13, getBR($10), getDF($10), $14); }
  82. $2 == "SEND" && NF == 18 { acct($7 " (" $18 ")", $8, $11, $13, getBR($10), getDF($10), $14); }
  83. $2 == "SEND" && NF == 19 { acct($7 " (" $18 ")", $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  84. $2 == "SEND" && NF == 20 { acct($7 " (" $18 ")", $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  85. '
  86.     KEYTITLE="Sender"
  87.     ;;
  88. -csi)
  89.     AWKRULES='
  90. $2 == "SEND" && NF == 9  { acct($4, $4, $7, $8, $5, $6, $9); }
  91. $2 == "SEND" && NF == 11 { acct($6, $5, $9, $10, $7, $8, $11); }
  92. $2 == "SEND" && NF == 12 { acct($7, $6, $10, $11, $8, $9, $12); }
  93. $2 == "SEND" && NF == 13 { acct($9, $8, $11, $12, getBR($10), getDF($10), $13); }
  94. $2 == "SEND" && NF == 14 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
  95. $2 == "SEND" && NF == 16 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
  96. $2 == "SEND" && NF == 17 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
  97. $2 == "SEND" && NF == 18 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
  98. $2 == "SEND" && NF == 19 { acct($9, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  99. $2 == "SEND" && NF == 20 { acct($9, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  100. '
  101.     KEYTITLE="CSI"
  102.     MAPNAMES=no
  103.     ;;
  104. -dest*)
  105.     AWKRULES='
  106. $2 == "SEND" && NF == 9  { acct($4, $4, $7, $8, $5, $6, $9); }
  107. $2 == "SEND" && NF == 11 { acct($5, $5, $9, $10, $7, $8, $11); }
  108. $2 == "SEND" && NF == 12 { acct($6, $6, $10, $11, $8, $9, $12); }
  109. $2 == "SEND" && NF == 13 { acct($8, $8, $11, $12, getBR($10), getDF($10), $13); }
  110. $2 == "SEND" && NF == 14 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
  111. $2 == "SEND" && NF == 16 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
  112. $2 == "SEND" && NF == 17 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
  113. $2 == "SEND" && NF == 18 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
  114. $2 == "SEND" && NF == 19 { acct($8, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  115. $2 == "SEND" && NF == 20 { acct($8, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  116. '
  117.     KEYTITLE="Destination"
  118.     MAPNAMES=no
  119.     ;;
  120. -speed|-rate)
  121.     AWKRULES='
  122. $2 == "SEND" && NF == 9  { acct($5, $4, $7, $8, $5, $6, $9); }
  123. $2 == "SEND" && NF == 11 { acct($7, $5, $9, $10, $7, $8, $11); }
  124. $2 == "SEND" && NF == 12 { acct($8, $6, $10, $11, $8, $9, $12); }
  125. $2 == "SEND" && NF == 13 { acct(getBR($10), $8, $11, $12, getBR($10), getDF($10), $13); }
  126. $2 == "SEND" && NF == 14 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  127. $2 == "SEND" && NF == 16 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  128. $2 == "SEND" && NF == 17 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  129. $2 == "SEND" && NF == 18 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  130. $2 == "SEND" && NF == 19 { acct(getBR($10), $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  131. $2 == "SEND" && NF == 20 { acct(getBR($10), $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  132. '
  133.     KEYTITLE="Speed"
  134.     MAPNAMES=no
  135.     ;;
  136. -format)
  137.     AWKRULES='
  138. $2 == "SEND" && NF == 9  { acct($6, $4, $7, $8, $5, $6, $9); }
  139. $2 == "SEND" && NF == 11 { acct($8, $5, $9, $10, $7, $8, $11); }
  140. $2 == "SEND" && NF == 12 { acct($9, $6, $10, $11, $8, $9, $12); }
  141. $2 == "SEND" && NF == 13 { acct(getDF($10), $8, $11, $12, getBR($10), getDF($10), $13); }
  142. $2 == "SEND" && NF == 14 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  143. $2 == "SEND" && NF == 16 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  144. $2 == "SEND" && NF == 17 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  145. $2 == "SEND" && NF == 18 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
  146. $2 == "SEND" && NF == 19 { acct(getDF($10), $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  147. $2 == "SEND" && NF == 20 { acct(getDF($10), $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  148. '
  149.     KEYTITLE="Format"
  150.     MAPNAMES=no
  151.     ;;
  152. -job*)
  153.     AWKRULES='
  154. $2 == "SEND" && NF == 13 { acct($6, $8, $11, $12, getBR($10), getDF($10), $13); }
  155. $2 == "SEND" && NF == 14 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
  156. $2 == "SEND" && NF == 16 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
  157. $2 == "SEND" && NF == 17 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
  158. $2 == "SEND" && NF == 18 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
  159. $2 == "SEND" && NF == 19 { acct($6, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  160. $2 == "SEND" && NF == 20 { acct($6, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  161. '
  162.     KEYTITLE="JobTag"
  163.     MAPNAMES=no
  164.     ;;
  165. -dev*)
  166.     AWKRULES='
  167. $2 == "SEND" && NF == 13 { acct($4, $8, $11, $12, getBR($10), getDF($10), $13); }
  168. $2 == "SEND" && NF == 14 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
  169. $2 == "SEND" && NF == 16 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
  170. $2 == "SEND" && NF == 17 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
  171. $2 == "SEND" && NF == 18 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
  172. $2 == "SEND" && NF == 19 { acct($4, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  173. $2 == "SEND" && NF == 20 { acct($4, $8, $11, $13, getBR($10), getDFfromDCS($19), $14); }
  174. '
  175.     KEYTITLE="Device"
  176.     MAPNAMES=no
  177.     ;;
  178. esac
  179. #
  180. # Generate an awk program to process the statistics file.
  181. #
  182. SetupPrivateTmp
  183. tmpAwk=$TMPDIR/xferfax$$
  184. ($CAT<<'EOF'
  185. #
  186. # Setup date conversion data structures.
  187. #
  188. function setupDateTimeStuff()
  189. {
  190.     daysInMonth[ 0] = 31; daysInMonth[ 1] = 28; daysInMonth[ 2] = 31;
  191.     daysInMonth[ 3] = 30; daysInMonth[ 4] = 31; daysInMonth[ 5] = 30;
  192.     daysInMonth[ 6] = 31; daysInMonth[ 7] = 31; daysInMonth[ 8] = 30;
  193.     daysInMonth[ 9] = 31; daysInMonth[10] = 30; daysInMonth[11] = 31;
  194.     FULLDAY = 24 * 60 * 60;
  195. }
  196. #
  197. # Convert hh:mm:ss to seconds.
  198. #
  199. function cvtTime(s)
  200. {
  201.     t = i = 0;
  202.     for (n = split(s, a, ":"); i++ < n; )
  203. t = t*60 + a[i];
  204.     return t;
  205. }
  206. #
  207. # Convert MM/DD/YY hh:mm to seconds.
  208. # NB: this does not deal with leap years.
  209. #
  210. function cvtDateTime(s)
  211. {
  212.     yday = substr(s,7,2)
  213.     if (yday < 70)
  214.         yday += 30;
  215.     else
  216.         yday -= 70;
  217.     yday = yday*365 + substr(s,4,2) - 1;
  218.     mon = substr(s,1,2) - 1;
  219.     for (i = 0; i < mon; i++)
  220. yday += daysInMonth[i];
  221.     return yday*FULLDAY + cvtTime(substr(s,10) ":00");
  222. }
  223. function setupDigits()
  224. {
  225.   digits[0] = "0"; digits[1] = "1"; digits[2] = "2";
  226.   digits[3] = "3"; digits[4] = "4"; digits[5] = "5";
  227.   digits[6] = "6"; digits[7] = "7"; digits[8] = "8";
  228.   digits[9] = "9";
  229. }
  230. #
  231. # Format seconds as hh:mm:ss.
  232. #
  233. function fmtTime(t)
  234. {
  235.     v = int(t/3600);
  236.     result = "";
  237.     if (v > 0) {
  238. t -= v*3600;
  239.         result = v ":"
  240.     }
  241.     v = int(t/60);
  242.     if (v >= 10 || result != "")
  243. result = result digits[int(v/10)];
  244.     result = result digits[int(v%10)];
  245.     t -= v*60;
  246.     return (result ":" digits[int(t/10)] digits[int(t%10)]);
  247. }
  248. #
  249. # Setup map for histogram calculations
  250. # and indexed table for decoding params.
  251. #
  252. function setupMaps(s, map, names)
  253. {
  254.     n = split(s, a, ":");
  255.     for (i = 1; i <= n; i++) {
  256. map[a[i]] = i;
  257. names[i-1] = a[i];
  258.     }
  259. }
  260. #
  261. # Add pages to a histogram.
  262. #
  263. function addToMap(key, ix, pages, map)
  264. {
  265.     if (key == "") {
  266. for (i in map)
  267.     key = key ":";
  268.     }
  269.     n = split(key, a, ":");
  270.     a[map[ix]] += pages;
  271.     t = a[1];
  272.     for (i = 2; i <= n; i++)
  273.       t = t ":" a[i];
  274.     return t;
  275. }
  276. #
  277. # Merge two histogram maps.
  278. #
  279. function mergeMap(map2, map1)
  280. {
  281.     if (map2 == "")
  282. return map1;
  283.     else if (map1 == "")
  284. return map2;
  285.     # map1 & map2 are populated
  286.     n1 = split(map1, a1, ":");
  287.     n2 = split(map2, a2, ":");
  288.     for (i = 1; i <= n1; i++)
  289. a2[i] += a1[i];
  290.     t = a2[1];
  291.     for (i = 2; i <= n; i++)
  292.       t = t ":" a2[i];
  293.     return t;
  294. }
  295. #
  296. # Return the name of the item with the
  297. # largest number of accumulated pages.
  298. #
  299. function bestInMap(totals, map)
  300. {
  301.    n = split(totals, a, ":");
  302.    imax = 1; max = -1;
  303.    for (j = 1; j <= n; j++)
  304.        if (a[j] > max) {
  305.    max = a[j];
  306.    imax = j;
  307.        }
  308.    split(map, a, ":");
  309.    return a[imax];
  310. }
  311. #
  312. # Sort array a[l..r]
  313. #
  314. function qsort(a, l, r) {
  315.     i = l;
  316.     k = r+1;
  317.     item = a[l];
  318.     for (;;) {
  319. while (i < r) {
  320.             i++;
  321.     if (a[i] >= item)
  322. break;
  323.         }
  324. while (k > l) {
  325.             k--;
  326.     if (a[k] <= item)
  327. break;
  328.         }
  329.         if (i >= k)
  330.     break;
  331. t = a[i]; a[i] = a[k]; a[k] = t;
  332.     }
  333.     t = a[l]; a[l] = a[k]; a[k] = t;
  334.     if (k != 0 && l < k-1)
  335. qsort(a, l, k-1);
  336.     if (k+1 < r)
  337. qsort(a, k+1, r);
  338. }
  339. function cleanup(s)
  340. # remove special characters from the string s and return the results
  341. # the first arg of gsub is a regex to be substituted (removed in this
  342. # case) from the string s
  343. #  remove double quotes, leading spaces at the beginning
  344. #  of the string any spaces followed at the end of the string
  345. {
  346.     gsub(""", "", s);
  347.     gsub("^ +", "", s);
  348.     gsub(" +$", "", s);
  349.     return s;
  350. }
  351. function setupToLower()
  352. {
  353.     upperRE = "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]";
  354.     upper["A"] = "a"; upper["B"] = "b"; upper["C"] = "c";
  355.     upper["D"] = "d"; upper["E"] = "e"; upper["F"] = "f";
  356.     upper["G"] = "g"; upper["H"] = "h"; upper["I"] = "i";
  357.     upper["J"] = "j"; upper["K"] = "k"; upper["L"] = "l";
  358.     upper["M"] = "m"; upper["N"] = "n"; upper["O"] = "o";
  359.     upper["P"] = "p"; upper["Q"] = "q"; upper["R"] = "r";
  360.     upper["S"] = "s"; upper["T"] = "t"; upper["U"] = "u";
  361.     upper["V"] = "v"; upper["W"] = "w"; upper["X"] = "x";
  362.     upper["Y"] = "y"; upper["Z"] = "z";
  363. }
  364. function toLower(s)
  365. {
  366.     if (match(s, upperRE) != 0) {
  367. do {
  368.     c = substr(s, RSTART, 1);
  369.     gsub(c, upper[c], s);
  370. } while (match(s, upperRE));
  371.     }
  372.     return s;
  373. }
  374. function getBR(params)
  375. {
  376.     if ((int(int(params) / 2097152) % 2) == 1) {
  377.         return brNames[int(int(params) / 8) % 16];
  378.     } else {
  379.         return brNames[int(int(params) / 2) % 8];
  380.     }
  381. }
  382. function getDF(params)
  383. {
  384.     if ((int(int(params) / 2097152) % 2) == 1) {
  385.         return dfNames[int(int(params) / 16384) % 4];
  386.     } else {
  387.         return dfNames[int(int(params) / 512) % 4];
  388.     }
  389. }
  390. function hex(n) {
  391.     # GNU Awk 3.1.3 has a type conversion error from hex strings,
  392.     # so we have to do it the hard way
  393.     val = 0;
  394.     for (position = 1; position <= length(n); position++) {
  395. val = val * 16;
  396. char = tolower(substr(n, position, 1));
  397. if (char == "a") val = val + 10;
  398. else if (char == "b") val = val + 11;
  399. else if (char == "c") val = val + 12;
  400. else if (char == "d") val = val + 13;
  401. else if (char == "e") val = val + 14;
  402. else if (char == "f") val = val + 15;
  403. else val = val + int(char);
  404.     }
  405.     return val;
  406. }
  407. function isBitSet(bit, dcs) {
  408.     byte = int((bit - 1) / 8);  
  409.     pos = 7 - ((bit - 1) % 8);
  410.     dcsbyte = hex(substr(dcs, (byte*3+1), 2));
  411.     return int(int(dcsbyte / (2 ^ pos)) % 2);
  412. }
  413.         
  414. function getDFfromDCS(dcs)
  415. {
  416.     if (substr(dcs, 1, 1) == """)
  417. dcs = substr(dcs, 2);
  418.     if (substr(dcs, length(dcs), 1) == """)
  419. dcs = substr(dcs, 1, length(dcs)-1);
  420.     if (isBitSet(68, dcs)) {
  421. if (isBitSet(69, dcs))  
  422.     return dfNames[6]; 
  423. return dfNames[5];
  424.     }
  425.     if (isBitSet(78, dcs) || isBitSet(79, dcs))
  426. return dfNames[4];
  427.     if (isBitSet(31, dcs))  
  428. return dfNames[3];
  429.     if (isBitSet(26, dcs))
  430. return dfNames[2];
  431.     if (isBitSet(16, dcs))
  432. return dfNames[1];
  433.     return dfNames[0];
  434. }
  435. #
  436. # Accumulate a statistics record.
  437. #
  438. function acct(key, dest, pages, time, br, df, status)
  439. {
  440.     status = cleanup(status);
  441.     if (length(status) > 11) {
  442. msg = toLower(substr(status, 1, 11));
  443. if (callFailed[msg])
  444.     return;
  445.     }
  446.     if (cvtDateTime($1) < KEEPSINCE || cvtDateTime($1) > KEEPEND)
  447. return;
  448.     key = cleanup(key);
  449. EOF
  450. test "$MAPNAMES" = "yes" && $CAT<<'EOF'
  451.     #
  452.     # Try to merge unqualified names w/ fully qualified names
  453.     # by stripping the host part of the domain address and
  454.     # mapping unqualified names to a stripped qualified name.
  455.     #
  456.     n = split(key, parts, "@");
  457.     if (n == 2) { # user@addr
  458. user = parts[1];
  459. if (user != "root" && user != "guest") {
  460.     addr = parts[2];
  461.     #
  462.     # Strip hostname from multi-part domain name.
  463.     #
  464. EOF
  465. test "$MAPNAMES" = "yes" && echo 'p = split("'`hostname`'", hostname, ".");'
  466. test "$MAPNAMES" = "yes" && $CAT<<'EOF'
  467.     n = split(addr, domains, ".");
  468.     if (p > 1 && n > p) { # e.g. flake.asd.sgi.com
  469. l = length(domains[1])+1;
  470. addr = substr(addr, l+1, length(addr)-l);
  471. key = user "@" addr;
  472.     }
  473.     if (addrs[user] == "") { # record mapped name
  474. addrs[user] = addr;
  475.     } else if (addrs[user] != addr) {
  476. if (!warned[user "@" addr]) {
  477.     warned[user "@" addr] = 1;
  478.     printf "Warning, address clash, "%s" and "%s".n", 
  479.        user "@" addrs[user], user "@" addr
  480. }
  481.     }
  482. }
  483.     } else if (n != 1) {
  484. printf "Warning, weird user address/name "%s".n", key
  485.     }
  486. EOF
  487. $CAT<<'EOF'
  488.     dest = cleanup(dest);
  489.     sendpages[key] += pages;
  490. sendcalls[key] += 1;
  491.     time = cleanup(time);
  492.     if (pages == 0 && time > 60)
  493. time = 0;
  494.     sendtime[key] += cvtTime(time);
  495.     if (status != "")
  496. senderrs[key]++;
  497.     br = cleanup(br);
  498.     sendrate[key] = addToMap(sendrate[key], br, pages, rateMap);
  499.     df = cleanup(df);
  500.     senddata[key] = addToMap(senddata[key], df, pages, dataMap);
  501. }
  502. #
  503. # Print a rule between the stats and the totals line.
  504. #
  505. function printRule(n, s)
  506. {
  507.     r = "";
  508.     while (n-- >= 0)
  509. r = r s;
  510.     printf "%sn", r;
  511. }
  512. BEGIN { FS="t";
  513.   rates = "2400:4800:7200:9600:12000:14400:16800:19200:21600:24000:26400:28800:31200:33600";
  514.   setupMaps(rates, rateMap, brNames);
  515.   datas = "1-D MH:2-D MR:2-D Uncompressed Mode:2-D MMR:JBIG:JPEG Greyscale:JPEG Full-color";
  516.   setupMaps(datas, dataMap, dfNames);
  517.   callFailed["busy signal"] = 1;
  518.   callFailed["unknown pro"] = 1;
  519.   callFailed["no carrier "] = 1;
  520.   callFailed["no local di"] = 1;
  521.   callFailed["no answer f"] = 1;
  522.   callFailed["ringback de"] = 1;
  523.   callFailed["job aborted"] = 1;
  524.   setupToLower();
  525.   setupDateTimeStuff();
  526.   if (SINCEDT == "")
  527.       KEEPSINCE = cvtDateTime(TODAY) - AGE*FULLDAY;
  528.   else
  529.       KEEPSINCE = cvtDateTime(SINCEDT);
  530.   if (ENDDT == "")
  531.       KEEPEND = cvtDateTime(TODAY);
  532.   else
  533.       KEEPEND = cvtDateTime(ENDDT);
  534. EOF
  535. echo   "KeyTitle = "$KEYTITLE""
  536. $CAT<<'EOF'
  537. }
  538. END { OFS="t"; setupDigits();
  539.   maxlen = 15;
  540.   # merge unqualified and qualified names
  541.   for (key in sendpages) {
  542.       if (addrs[key] != "") {
  543.   fullkey = key "@" addrs[key];
  544.   sendpages[fullkey] += sendpages[key];
  545.   sendcalls[fullkey] += sendcalls[key];
  546.   sendtime[fullkey] += sendtime[key];
  547.   senderrs[fullkey] += senderrs[key];
  548.   sendrate[fullkey] = 
  549.       mergeMap(sendrate[fullkey], sendrate[key]);
  550.   senddata[fullkey] = 
  551.       mergeMap(senddata[fullkey], senddata[key]);
  552.       }
  553.   }
  554.   nsorted = 0;
  555.   for (key in sendpages) {
  556.       if (addrs[key] != "") # unqualified name
  557.   continue;
  558.       l = length(key);
  559.       if (l > maxlen)
  560. maxlen = l;
  561.       sorted[nsorted++] = key;
  562.   }
  563.   qsort(sorted, 0, nsorted-1);
  564.   fmt = "%-" maxlen "." maxlen "s"; # e.g. %-24.24s
  565.                   printf fmt " %6s %6s %9s %6s %5s %7s %7sn",
  566.       KeyTitle, "Pages", "Calls", "Time", "Pg/min",
  567.       "Errs", "TypRate", "TypData";
  568.   tpages = 0;
  569.   ttime = 0;
  570.   terrs = 0;
  571.   for (k = 0; k < nsorted; k++) {
  572.       i = sorted[k];
  573.       t = sendtime[i]/60; if (t == 0) t = 1;
  574.       n = sendpages[i]; if (n == 0) n = 1;
  575.       brate = best
  576.       printf fmt " %6d %6d %9s %6.1f %5d %7d %7.7sn",
  577.   i, sendpages[i], sendcalls[i], fmtTime(sendtime[i]),
  578.   sendpages[i] / t, senderrs[i],
  579.   bestInMap(sendrate[i], rates),
  580.   bestInMap(senddata[i], datas);
  581. tpages += sendpages[i];
  582. tcalls += sendcalls[i];
  583. ttime += sendtime[i];
  584. terrs += senderrs[i];
  585.   }
  586.   printRule(maxlen+1+6+1+6+1+9+6+1+5+1+7+1+7, "-");
  587.   t = ttime/60; if (t == 0) t = 1;
  588.   printf fmt " %6d %6d %9s %6.1f %5dn",
  589.       "Total", tpages, tcalls, fmtTime(ttime), tpages/t, terrs;
  590. }
  591. EOF
  592. echo "$AWKRULES"
  593. )>$tmpAwk
  594. $AWK -f $tmpAwk -v TODAY="$TODAY" -v AGE="$AGE" -v SINCEDT="$SINCEDT" -v ENDDT="$ENDDT" $FILES
  595. # cleanup
  596. hfExit 0