home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / tools / checkque.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  19.0 KB  |  800 lines

  1. /*
  2.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  3.  *
  4.  *
  5.  *     Copyright (C) 1979,1980,1981  University of Delaware
  6.  *
  7.  *     Department of Electrical Engineering
  8.  *     University of Delaware
  9.  *     Newark, Delaware  19711
  10.  *
  11.  *     Phone:  (302) 738-1163
  12.  *
  13.  *
  14.  *     This program module was developed as part of the University
  15.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  16.  *
  17.  *     Acquisition, use, and distribution of this module and its listings
  18.  *     are subject restricted to the terms of a license agreement.
  19.  *     Documents describing systems using this module must cite its source.
  20.  *
  21.  *     The above statements must be retained with all copies of this
  22.  *     program and may not be removed without the consent of the
  23.  *     University of Delaware.
  24.  *     
  25.  *
  26.  *     version  -1    David H. Crocker    March   1979
  27.  *     version   0    David H. Crocker    April   1980
  28.  *     version  v7    David H. Crocker    May     1981
  29.  *     version   1    David H. Crocker    October 1981
  30.  *
  31.  */
  32. /*  CHECKQUE:  Peruse status of mail queue
  33.  *
  34.  *  Oct 81  D. Crocker          Initial coding
  35.  *  Nov 81  D. Crocker          message name must begin "msg."
  36.  *                              show hours since last contact
  37.  *                              show size of aquedir directory
  38.  *  Apr 82  D. Crocker          show last pickup in elapsed hours, also
  39.  *  Jun 82  S. Manion           added flags s,p,z,f, and t.
  40.  *                              rearanged output format.
  41.  *  Jul 82  D. Crocker          convert to mq_ package
  42.  *  Mar 83  Doug Kingston       changed to use format independent directory
  43.  *                              access routines a la 4.2BSD.  (libndir.a)
  44.  *  Sep 84  D. Rockwell        -c only looks at relevant queues
  45.  *  Oct 86  S. Kille            -h gives list of hosts
  46.  *  Oct 88  E. Bennett        converted to use getopt(3)
  47.  */
  48.  
  49. #include "util.h"
  50. #include "mmdf.h"
  51. #include <sys/stat.h>
  52. #include <utmp.h>
  53. #include "ch.h"
  54. #include "msg.h"
  55. #include "adr_queue.h"
  56. #include "phs.h"
  57. #ifdef SYS5
  58. #include <string.h>
  59. #else
  60. #include <strings.h>
  61. #endif
  62.  
  63. #define WARNTIME    (60L * 60L * 24) /* 1 day */
  64.  
  65. extern time_t time();
  66.  
  67. time_t    curtime;        /* Current time secconds        */
  68. time_t    toolate;        /* Time to wait before panicing        */
  69.  
  70. extern    char    *quedfldir,    /* home directory for mmdf        */
  71.         *mquedir,    /* subordinate message directory    */
  72.         *squepref,    /* subordinate queue prefix        */
  73.         *aquedir;    /* subordinate address directory    */
  74. extern    char    *strdup();
  75.  
  76. extern    Chan    **ch_tbsrch;    /* full list of channels        */
  77.  
  78. extern    int    ch_numchans;    /* number of channels which are known    */
  79. extern    int    errno;        /* system error number            */
  80.  
  81. LOCFUN mn_dirinit();
  82.  
  83. struct ch_hostat
  84. {
  85.     char            *hname;
  86.     time_t            h_oldest;
  87.     int            hcount;
  88.     struct    ch_hostat    *next;
  89. };
  90.  
  91.  
  92. struct ch_chstat
  93. {
  94.     int    ch_nummsgs;
  95.     long    ch_bytes;
  96.     time_t    dstrt,
  97.         dmsg,
  98.         ddone,
  99.         pstrt,
  100.         pmsg,
  101.         pdone,
  102.         oldest,            /* oldest message in queue */
  103.         llog;
  104.     char    oldmsg[15];        /* name of oldest msg */
  105.     struct    ch_hostat    *hlist; /* detailed host info */
  106. } ch_stat[NUMCHANS];
  107.  
  108. long    msglen,            /* length of the current message    */
  109.     totblks;        /* number of blocks (1K) of msg data    */
  110.  
  111. DIR    *ovr_dirp;        /* handle on the queue directory    */
  112.  
  113. int    msg_total;        /* total in the queue            */
  114. long    msg_dirsiz;        /* total spaces in aquedir        */
  115.  
  116. char    msg_sender[ADDRSIZE + 1]; /* return address of current message    */
  117. char    bufout[BUFSIZ];
  118. char    *program;
  119.  
  120. int    ssflag,            /* print site summary lines only    */
  121.     nzflag,            /* print only non-zero sites        */
  122.     pcflag,            /* print only problem channels        */
  123.     fflag,            /* print name of first queued msg    */
  124.     chflag,            /* print only specified channels    */
  125.     hoflag;            /* give detailed host info        */
  126.  
  127. int    nchan;
  128. Chan    *chcodes[NUMCHANS];
  129.  
  130. /* ****  (mn_)  MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN  ***** */
  131.  
  132. main(argc, argv)
  133. int argc;
  134. char *argv[];
  135. {
  136.     extern    char    *dupfpath();
  137.  
  138.     program = argv[0];
  139.  
  140.     mmdf_init(argv[0]);
  141.     setbuf(stdout, bufout);
  142.     if (ch_numchans > NUMCHANS)
  143.     {
  144.         printf("%s: Struct ch_stat[NUMCHANS] not large enough - recompile\n",
  145.             argv[0]);
  146.         exit(-1);
  147.     }
  148.  
  149.     siginit();        /* standard interrupt initialization    */
  150.                 /* distinguish different delivers    */
  151.     flaginit(argc, argv);    /* initialize the flags            */
  152.  
  153.     mn_dirinit();        /* get right working directory        */
  154.  
  155.     ovr_queue();        /* do the entire mail queue        */
  156.  
  157.     ch_callstat();
  158.     ch_report();
  159.  
  160.     exit(RP_OK);
  161. }
  162.  
  163. flaginit(argc, argv)        /* initialize flags */
  164. int argc;
  165. char **argv;
  166. {
  167.     register    char    *p;
  168.     register    int    ch;
  169.     extern        char    *optarg;
  170.     extern        int    optind;
  171.  
  172.     chflag = fflag = ssflag = pcflag = nzflag = hoflag = 0;
  173.     nchan = 0;
  174.     /*NOSTRICT*/
  175.     toolate = WARNTIME;
  176.     while ((ch = getopt(argc, argv, "c:fhpst:z")) != EOF) {
  177.         switch (ch) {
  178.         case 'c':    /*  channel flag  */
  179.             chflag++;
  180.             while ((p = index(optarg, ',')) != (char *)NULL) {
  181.                 *p = '\0';
  182.                 add_chan(optarg);
  183.                 optarg = ++p;
  184.             }
  185.             add_chan(optarg);
  186.             break;
  187.  
  188.         case 'f':    /*  print name of first queued msg  */
  189.             fflag++;
  190.             break;
  191.  
  192.         case 'h':    /* print detailed host info */
  193.             hoflag++;
  194.             break;
  195.  
  196.         case 'p':    /*  problem channel flag  */
  197.             pcflag++;
  198.             break;
  199.  
  200.         case 's':    /*  site summary flag  */
  201.             ssflag++;
  202.             break;
  203.  
  204.         case 't':    /*  set time on problem channels  */
  205.             pcflag++;    /* implied p option */
  206.  
  207.             /*
  208.              * We want toolate to be in seconds. We start off
  209.              * assuming that the given argument was in minutes.
  210.              */
  211.             toolate = atoi(optarg) * 60L;
  212.             /* check for a trailing M to indicate minutes */
  213.             while (isdigit(*optarg))
  214.                 optarg++;
  215.             if (*optarg != 'm' && *optarg != 'M')
  216.                 /* must be in hours */
  217.                 toolate *= 60L;
  218.             break;
  219.  
  220.         case 'z':    /*  non-zero flag  */
  221.             nzflag++;
  222.             break;
  223.  
  224.         default:    /*  abzorb unrecognized flags  */
  225.             Usage();
  226.             exit(-1);
  227.             break;
  228.         }
  229.     }
  230.  
  231.     (void) fflush(stdout);
  232.     return(0);
  233. }
  234.  
  235. add_chan(channel)
  236. char *channel;
  237. {
  238.     /* Is there room for the channel name? */
  239.     if (nchan == NUMCHANS) {
  240.         printf("%s: can only specify %d channels.\n",
  241.             program, NUMCHANS);
  242.         return;
  243.     }
  244.  
  245.     /* Convert from the ch_spec form to structure pointer */
  246.     if ((chcodes[nchan++] = ch_nm2struct(channel)) == (Chan *)NOTOK) {
  247.         printf("%s: unknown channel: %s\n",
  248.             program, channel);
  249.         (void) fflush(stdout);
  250.     }
  251. }
  252.  
  253. LOCFUN
  254. mn_dirinit()        /* get to the working directory        */
  255. {
  256.     if (chdir(quedfldir) < OK)
  257.     {
  258.         printf("%s: can't chdir to %s\n", program, quedfldir);
  259.         exit(-1);
  260.     }
  261. }
  262.  
  263. /* ***********  (ovr_)  OVERALL SEQUENCING MANAGEMENT  *************** */
  264.  
  265. LOCFUN
  266. ovr_ismsg(entry)    /* a processable message?        */
  267. register struct dirtype *entry;
  268. {
  269.     return((
  270. #ifdef BSDDIRECT
  271.     entry->d_namlen < MSGNSIZE
  272. #else
  273.     (strlen(entry->d_name) < MSGNSIZE)
  274. #endif
  275.         && equal(entry->d_name, "msg.", 4)) ? TRUE : FALSE );
  276. }
  277.  
  278. ovr_queue()            /* Process entire message queue        */
  279. {
  280.     register    int    index;
  281.             char    qname[128];
  282.  
  283.     time(&curtime);        /* Get current time (in hours)        */
  284.  
  285.     if (chflag != 0)
  286.     {
  287.         for (index = 0; index < nchan; index++)
  288.         {
  289.             (void) strcpy(qname, squepref);
  290.             strcat(qname, chcodes[index]->ch_queue);
  291.             ovr_aqueue(qname);
  292.         }
  293.     } else
  294.         ovr_aqueue(aquedir);
  295. }
  296.  
  297. ovr_aqueue(ch)            /* Process a single message queue    */
  298. register char *ch;        /* queue directory name            */
  299. {
  300.     register    struct    dirtype    *dp;
  301.             struct    stat    statbuf;
  302.  
  303.     stat(ch, &statbuf);
  304.     msg_dirsiz += st_gsize(&statbuf);
  305.  
  306.     if ((ovr_dirp = opendir (ch)) == NULL)
  307.     {
  308.         printf("%s: can't open queue %s\n", program, ch);
  309.         return;
  310.     }
  311.  
  312.     while ((dp = readdir (ovr_dirp)) != NULL)
  313.     {            /* straight linear processing        */
  314.         if (ovr_ismsg (dp))
  315.             msg_proc (dp -> d_name);
  316.     }
  317.     closedir(ovr_dirp);
  318. }
  319. /* ***************  (msg_)  HANDLE A SINGLE MESSAGE  ***************** */
  320.  
  321. msg_proc(thename)        /* get, process & release a msg        */
  322. char thename[];
  323. {
  324.     Msg        curmsg;
  325.     struct    stat    statbuf;
  326.     char        msgpath[28];
  327.  
  328.     (void) sprintf(msgpath, "%s%s", mquedir, thename);
  329.     if (stat(msgpath, &statbuf) < 0) {
  330.         printf("\n*** %s: Couldn't stat;  error %d.\n", thename, errno);
  331.         (void) fflush(stdout);
  332.         msglen = 0;
  333.     } else {
  334.         msglen = st_gsize(&statbuf);
  335.         if (msglen == 0)
  336.         {
  337.             printf("\n*** %s: msg length of zero.\n", thename);
  338.             (void) fflush(stdout);
  339.         } else {
  340.             totblks += ((msglen+1023L)/1024L);
  341.             msg_total++;
  342.         }
  343.     }
  344.  
  345.     /*
  346.      *  Check for real anomalies!
  347.      */
  348.     (void) strcpy(curmsg.mg_mname, thename);
  349.  
  350.     if (mq_rinit((Chan *)0, &curmsg, msg_sender) == OK)
  351.     {
  352.         if (adr_each(&curmsg) == 0)
  353.         {
  354.             printf("\n*** %s: msg exists (%d chars), but goes nowhere.\n",
  355.                 thename, msglen);
  356.             (void) fflush(stdout);
  357.         }
  358.         mq_rkill(OK);
  359.     }
  360. }
  361.  
  362. /* ***********  (adr_)  INDIVIDUAL ADDR DELIVERY ATTEMPT  ************ */
  363.  
  364. adr_each(themsg)        /* do each address            */
  365. Msg *themsg;
  366. {
  367.     register    int            naddrs, curind;
  368.             Chan            *curch, *newch;
  369.             struct    adr_struct    newadr;
  370.             char            curhost[LINESIZE];
  371.             char            oldque[LINESIZE];
  372.  
  373.     curhost[0] = '\0';
  374.     oldque[0] = '\0';
  375.     for (naddrs = 0, curch = (Chan *)0, mq_setpos(0L);;)
  376.         switch(mq_radr(&newadr))
  377.         {
  378.         default:        /* should not get this        */
  379.             printf ("\n*** %s: bad return from mq_radr\n", themsg -> mg_mname);
  380.             exit(NOTOK);
  381.  
  382.         case NOTOK:        /* rest of list must be skipped    */
  383.         case DONE:        /* end of list            */
  384.             return(naddrs);
  385.  
  386.         case OK:        /* normal addr acquisition    */
  387.             naddrs++;
  388.             if (strcmp(newadr.adr_que, oldque) != 0 &&
  389.                 (newch = ch_qu2struct(newadr.adr_que)) == (Chan *)NOTOK)
  390.             {
  391.                 printf("\n*** Unknown channel queue ('%s') in message '%s'\n",
  392.                     newadr.adr_que, themsg->mg_mname);
  393.                 (void) fflush(stdout);
  394.             }
  395.             else
  396.             {
  397.                 (void) strcpy(oldque, newadr.adr_que);
  398.                 if (newadr.adr_delv != ADR_DONE)
  399.                 {
  400.                     if (curch != newch)
  401.                     {
  402.                         curch = newch;
  403.                         curind = ch_find(curch);
  404.                         ch_newmsg(curind, themsg);
  405.                         if (hoflag)
  406.                         {
  407.                             if (curch->ch_host == (char *)0)
  408.                             {
  409.                                 /* code folded from here */
  410.                                 (void) strcpy(curhost, newadr.adr_host);
  411.                                 ch_newhost(curind, curhost, themsg->mg_time);
  412.                                 /* unfolding */
  413.                             }
  414. #ifdef notdef
  415.                             else
  416.                                 /* code folded from here */
  417.                                 ch_newhost(curind, curch->ch_host, themsg->mg_time);
  418. #endif notdef
  419.                                 /* unfolding */
  420.                         }
  421.                     }
  422.                     else
  423.                     {
  424.                         if (hoflag
  425.                             && curch->ch_host == (char *)0
  426.                             && !lexequ(curhost, newadr.adr_host))
  427.                         {
  428.                             (void) strcpy(curhost, newadr.adr_host);
  429.                             ch_newhost(curind, curhost, themsg->mg_time);
  430.                         }
  431.                     }
  432.                 }
  433.             }
  434.         }
  435. }
  436. /* */
  437. ch_find(thech)
  438. Chan *thech;
  439. {
  440.     register    int    chind;
  441.  
  442.     for (chind = 0; chind < ch_numchans; chind++)
  443.         if (ch_tbsrch[chind] == thech)
  444.             return(chind);
  445.  
  446.     printf ("\n*** Could not locate channel ('%s') in channel list\n",
  447.         thech->ch_name);
  448.     (void) fflush(stdout);
  449.  
  450.     return(-1);
  451. }
  452.  
  453. ch_newmsg(theind, themsg)
  454. int theind;
  455. Msg  *themsg;
  456. {
  457.     if (theind < 0)
  458.         return;
  459.     ch_stat[theind].ch_nummsgs++;
  460.     ch_stat[theind].ch_bytes += msglen;
  461.     if (themsg -> mg_time < ch_stat[theind].oldest ||
  462.         ch_stat[theind].oldest == 0)
  463.     {
  464.         ch_stat[theind].oldest = themsg->mg_time;
  465.         (void) strcpy(ch_stat[theind].oldmsg, themsg->mg_mname);
  466.     }
  467.     return;
  468.  
  469. }
  470. /* */
  471.  
  472. ch_newhost(theind, thehost, age)
  473. int theind;
  474. char *thehost;
  475. time_t age;
  476. {
  477.     struct    ch_hostat    *hptr;
  478.     char            *ctime();
  479.  
  480.     if (theind < 0)
  481.         return;
  482.  
  483.     if (ch_stat[theind].hlist == (struct ch_hostat *)0)
  484.     {
  485.         hptr = (struct ch_hostat *)malloc(sizeof(struct ch_hostat));
  486.         ch_stat[theind].hlist = hptr;
  487.         hptr->hname = strdup(thehost);
  488.         hptr->h_oldest = age;
  489.         hptr->hcount = 1;
  490.         hptr->next = (struct ch_hostat *)0;
  491.         return;
  492.     }
  493.     for (hptr = ch_stat[theind].hlist;; hptr = hptr -> next)
  494.     {
  495.         if (lexequ(thehost, hptr->hname))
  496.         {
  497.             hptr->hcount++;
  498.             if (age < hptr->h_oldest)
  499.                 hptr->h_oldest = age;
  500.             return;
  501.         }
  502.         if (hptr->next == (struct ch_hostat *)0)
  503.             break;
  504.     }
  505.     hptr->next = (struct ch_hostat *)malloc(sizeof(struct ch_hostat));
  506.     hptr = hptr->next;
  507.     hptr->hname = strdup(thehost);
  508.     hptr->h_oldest = age;
  509.     hptr->hcount = 1;
  510.     hptr->next = (struct ch_hostat *)0;
  511.     return;
  512. }
  513. /* */
  514.  
  515. ch_callstat()
  516. {
  517.     register    int        chind;
  518.     extern        struct    utmp    *getllnam();
  519.             struct    utmp    *llogptr;
  520.  
  521.     for (chind = 0; chind < ch_numchans; chind++)
  522.     {
  523.         if (ch_tbsrch[chind]->ch_login != NOLOGIN)
  524.         {
  525.             setllog();    /* setup for checking last logins */
  526.             if ((llogptr = getllnam(ch_tbsrch[chind]->ch_login)) != NULL)
  527.                 /*NOSTRICT*/
  528.                 ch_stat[chind].llog = llogptr->ut_time;
  529.         }
  530.  
  531.         ch_stat[chind].dstrt = phs_get(ch_tbsrch[chind], PHS_WRSTRT);
  532.         ch_stat[chind].dmsg  = phs_get(ch_tbsrch[chind], PHS_WRMSG);
  533.         ch_stat[chind].ddone = phs_get(ch_tbsrch[chind], PHS_WREND);
  534.         ch_stat[chind].pstrt = phs_get(ch_tbsrch[chind], PHS_RESTRT);
  535.         ch_stat[chind].pmsg  = phs_get(ch_tbsrch[chind], PHS_REMSG);
  536.         ch_stat[chind].pdone = phs_get(ch_tbsrch[chind], PHS_REEND);
  537.     }
  538.  
  539.     endllog();
  540. }
  541. /* */
  542.  
  543. ch_report()
  544. {
  545.     register    int    chind;
  546.     register    int    index;
  547.     register    Chan    *chptr;
  548.             time_t    age, timestamp[7], overstamp[7];
  549.             char    *tptr;
  550.             char    *ctime();
  551.             char    tmp[LINESIZE], *textout[7];
  552.             int    prtpos,    prtflag;
  553.  
  554.     tptr = ctime(&curtime);
  555.     tptr[16] = '\0';
  556.     printf("\n%s:  %d queued msgs / %ld byte queue directory\n",
  557.         tptr, msg_total, msg_dirsiz);
  558.     printf("\t\t   %ld Kbytes in msg dir\n\n", totblks);
  559.  
  560.     prtflag = 0;
  561.     for (chind = 0; chind < ch_numchans; chind++)
  562.     {
  563.         /*  If the non-zero flag is set, then make sure the number
  564.          *  of messages on this channel is non-zero.
  565.          */
  566.         if (nzflag != 0)
  567.             if (ch_stat[chind].ch_nummsgs == 0)
  568.                 continue;
  569.  
  570.         /*  An often used variable  */
  571.         chptr = ch_tbsrch[chind];
  572.  
  573.         /*  If specific channels were requested, make sure this is
  574.          *  one of them.
  575.          */
  576.         if (chflag != 0)
  577.         {
  578.             for (index = 0;  index < nchan;  index++)
  579.                 if (chptr == chcodes[index])
  580.                     break;
  581.             if (index >= nchan)
  582.                 continue;
  583.         }
  584.  
  585.         /*  find time information  */
  586.  
  587.         for (index = 0; index <= 6; index++)
  588.             overstamp[index] = (time_t)0;
  589.  
  590.         if (chptr->ch_login == NOLOGIN) {
  591.             textout[1] = "deliver start";
  592.             textout[2] = "deliver message";
  593.             textout[3] = "deliver end";
  594.             textout[4] = "pickup start";
  595.             textout[5] = "pickup message";
  596.             textout[6] = "pickup end";
  597.             timestamp[0] = (time_t) 0;
  598.             timestamp[1] = ch_stat[chind].dstrt;
  599.             timestamp[2] = ch_stat[chind].dmsg;
  600.             timestamp[3] = ch_stat[chind].ddone;
  601.             timestamp[4] = ch_stat[chind].pstrt;
  602.             timestamp[5] = ch_stat[chind].pmsg;
  603.             timestamp[6] = ch_stat[chind].pdone;
  604.             if (ch_stat[chind].ch_nummsgs > 0 && timestamp[3] != (time_t) 0)
  605.                 overstamp[3] = curtime - timestamp[3];
  606.             if (timestamp[6] != (time_t) 0)
  607.                 overstamp[6] = (curtime - timestamp[6])/2;
  608.         } else {
  609.             sprintf(tmp, "%-8s login", chptr->ch_login);
  610.             textout[0] = tmp;
  611.             timestamp[0] = ch_stat[chind].llog;
  612.             if (timestamp[0] != (time_t) 0)
  613.                 overstamp[0] = curtime - timestamp[0];
  614.             textout[1] = "pickup start";
  615.             textout[2] = "pickup message";
  616.             textout[3] = "pickup end";
  617.             textout[4] = "deliver start";
  618.             textout[5] = "deliver message";
  619.             textout[6] = "deliver end";
  620.             timestamp[1] = ch_stat[chind].pstrt;
  621.             timestamp[2] = ch_stat[chind].pmsg;
  622.             timestamp[3] = ch_stat[chind].pdone;
  623.             timestamp[4] = ch_stat[chind].dstrt;
  624.             timestamp[5] = ch_stat[chind].dmsg;
  625.             timestamp[6] = ch_stat[chind].ddone;
  626.             if (ch_stat[chind].ch_nummsgs > 0 && timestamp[6] != (time_t) 0)
  627.                 overstamp[6] = curtime - timestamp[6];
  628.             if (timestamp[3] != (time_t) 0)
  629.                 overstamp[3] = (curtime - timestamp[3])/2;
  630.         }
  631.  
  632.         /*  how long ago was the completion?  */
  633.         prtpos = -1;
  634.         for (index=0; index <= 6; index++)
  635.             if (timestamp[index] != (time_t)0)
  636.                 prtpos = index;
  637.         if (prtpos >= 0)
  638.             age = curtime - timestamp[prtpos];
  639.         else
  640.             age = (time_t)0;
  641.  
  642.         /*  if problem channel flag is set, check age  */
  643.         if (pcflag != 0)
  644.         {
  645.             if (age < toolate)
  646.                 continue;
  647.             else
  648.                 prtflag++;
  649.         }
  650.  
  651.         prtinfo(chind, timestamp, overstamp, textout, age, prtpos);
  652.     }
  653.     if ((pcflag != 0 ) && (prtflag == 0))
  654.         printf("No problems with any channels.\n");
  655. }
  656.  
  657. prtinfo(chind, timestamp, overstamp, textout, age, prtpos)
  658. int chind, prtpos;
  659. time_t timestamp[], overstamp[];
  660. char *textout[];
  661. time_t age;
  662. {
  663.     register    Chan            *chptr;
  664.             struct    ch_hostat    *hptr;
  665.             time_t            ageh;
  666.             char            *tptr, *ctime();
  667.             int            temp, line, toploop;
  668.  
  669.     chptr = ch_tbsrch[chind];
  670.  
  671.     /*  print the site summary line  */
  672.     if(ssflag == 0)
  673.         putchar('\n');
  674.     else
  675.     {
  676.         /*  print a star to indicate overdue channels  */
  677.         if ((age != (time_t)0) && (age > toolate))
  678.             printf("* ");
  679.         else
  680.             printf("  ");
  681.     }
  682.     /*NOSTRICT*/
  683.     temp = (ch_stat[chind].ch_bytes + 500) / 1000;
  684.     if ((ch_stat[chind].ch_bytes != 0) && (temp == 0))
  685.         temp++;
  686.     /*NOSTRICT*/
  687.     ageh = age / (60L * 60L);
  688.     printf ("%3d msg%s %4d Kb ",
  689.         ch_stat[chind].ch_nummsgs,
  690.         ((ch_stat[chind].ch_nummsgs == 1) ? " " : "s"),
  691.         temp);
  692.     if (ssflag != 0)
  693.     {
  694.         if ((age != (time_t)0))
  695.             printf("%5ld hour%s ", ageh, ((ageh == 1)  ?  " " : "s"));
  696.         else
  697.             if (chptr->ch_login == NOLOGIN)
  698.                 printf("   inactive ");
  699.             else
  700.                 printf("   no login ");
  701.     }
  702.  
  703.     printf("(%-8s) %-15s :  %s\n",
  704.         chptr->ch_queue, chptr->ch_name, chptr->ch_show);
  705.  
  706.     /*  If only a summary was requested, then go on  */
  707.     if (ssflag != 0)
  708.     {
  709.         /*  print oldest file if specifically requested  */
  710.         if(fflag != 0)
  711.             printf("    oldest msg:  %s\n", ch_stat[chind].oldmsg);
  712.         return;
  713.     }
  714.  
  715.     toploop = ((chptr->ch_login==NOLOGIN) &&
  716.         ((chptr->ch_access&CH_PICK)!=CH_PICK) &&
  717.         (timestamp[4] == (time_t)0) &&
  718.         (timestamp[5] == (time_t)0) &&
  719.         (timestamp[6] == (time_t)0)) ? 3 : 6;
  720.     for (line = (chptr->ch_login != NOLOGIN ? 0 : 1); line <= toploop; line++)
  721.     {
  722.         overdue(overstamp[line]);
  723.  
  724.         if (timestamp[line] == (time_t)0)
  725.             printf("No %-23s", textout[line]);
  726.         else
  727.         {
  728.             tptr = ctime(×tamp[line]);
  729.             tptr[16] = '\0';
  730.             printf("%-26s:  %s", textout[line], tptr);
  731.         }
  732.  
  733.         if (line == prtpos)
  734.             printf(" / %ld hour%s\n",  ageh, ((ageh == 1)  ?  "" : "s"));
  735.         else
  736.             putchar('\n');
  737.     }
  738.  
  739.     if (((timestamp[1] > (time_t)0) && (timestamp[3] > (time_t)0) &&
  740.         (timestamp[1] > timestamp[3])) || 
  741.         ((timestamp[4] > (time_t)0) && (timestamp[6] > (time_t)0) &&
  742.         (timestamp[4] > timestamp[6])))
  743.         printf("  *** INCOMPLETE **\n");
  744.  
  745.     /*  print oldest file in queue if requested  */
  746.     if ((fflag != 0) && (ch_stat[chind].oldest != (time_t)0))
  747.         printf("\t\t  oldest msg                :  %s\n", ch_stat[chind].oldmsg);
  748.  
  749.     if (ch_stat[chind].ch_nummsgs != 0 &&
  750.         ch_stat[chind].oldest < (curtime - toolate))
  751.     {
  752.         tptr = ctime (&(ch_stat[chind].oldest));
  753.         tptr[16] = '\0';
  754.  
  755.         printf("  *** WAITING **  First message             :  %s\n", tptr);
  756.     }
  757.  
  758.     if ((hoflag != 0) && (chptr->ch_host == (char *)0))
  759.     {
  760.         for (hptr = ch_stat[chind].hlist; hptr != (struct ch_hostat *)0;
  761.             hptr = hptr->next)
  762.         {
  763.             tptr = ctime(&(hptr->h_oldest));
  764.             tptr[16] = '\0';
  765.             printf("    %-32s (%3d)  :  %s", hptr->hname,
  766.                 hptr->hcount, tptr);
  767.             if ((curtime - hptr->h_oldest) > toolate)
  768.                 printf("  ** BLOCKING **\n");
  769.             else
  770.                 printf("\n");
  771.         }
  772.     }
  773. }
  774.  
  775. overdue(age)
  776. time_t age;
  777. {
  778.     if (age == (time_t)0 || age <= toolate) {
  779.         printf("\t\t  ");
  780.         return(0);
  781.     }
  782.  
  783.     printf("  *** OVERDUE **  ");
  784.     return;
  785. }
  786.  
  787. Usage()
  788. {
  789.     printf("Usage: %s [-z] [-s] [-p] [-f] [-h] [-t<age>[m]] [-c <channel name(s)>]\n", program);
  790.     printf("\t-c <channel names>\n");
  791.     printf("\t\tspecifies the channel names to look at\n");
  792.     printf("\t-f  ->  print name of oldest queued msg\n");
  793.     printf("\t-h  ->  print list of overdue hosts\n");
  794.     printf("\t-p  ->  print only the problem channels\n");
  795.     printf("\t-s  ->  summary lines only\n");
  796.     printf("\t-t<age>[m]\n");
  797.     printf("\t\tspecifies the age for problem channels in hours or minutes\n");
  798.     printf("\t-z  ->  non zero channels only\n");
  799. }
  800.