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

  1. #include "util.h"
  2. #include "conf.h"
  3. #include <sys/stat.h>
  4. #include "ll_log.h"
  5.  
  6. /*  Package for logging entries into files                              */
  7.  
  8. /*      David H. Crocker, Dept. of Electrical Engineering               */
  9. /*      University of Delaware; October 1979                            */
  10.  
  11. /*  Failure to open a log file, other than due to its being busy,
  12.  *  causes the fd associated with ll_struct to be set to -1.
  13.  *  Later calls then result in a no-op, except for openllog & closellog
  14.  */
  15.  
  16. /*
  17.  *  Modified to use 4.2BSD's O_APPEND mode unless the file is in cycle mode
  18.  *  Peter Collinson UKC March 1987
  19.  *  Probably would be better to totally rewrite this, but that seems
  20.  *  a little dangerous and is probably not good engineering practice
  21.  */
  22. #ifdef    V4_2BSD
  23. #include <sys/file.h>
  24. #endif
  25.  
  26. #define _LLRETRY  5               /* number of retries if log locked    */
  27. #define _LLSLEEP  5               /* time between tries                 */
  28.  
  29.  
  30. #define SHORTIM   0          /* Short time format                  */
  31. #define LONGTIM   1          /* Long time format                   */
  32. #define _LLDIDC 0200          /* Already did cycle, this opening    */
  33.  
  34. extern char *strdup ();
  35. extern time_t time();
  36. extern int errno;
  37.  
  38. LOCFUN ll_tmout(), ll_cycle(), ll_size(), ll_time();
  39.  
  40. LOCVAR int errno_save;
  41.  
  42. LOCVAR char
  43.         _cycling[] = "\n\n***  CYCLING  ***\n",
  44.         _cycled[] = "***  CYCLED  ***\n";
  45.  
  46. /*  *******************  LOG OPENING AND CLOSING  ******************** */
  47.  
  48. ll_open (loginfo)                /* physically open the file           */
  49. register struct ll_struct *loginfo;
  50. {
  51.     short     retries;
  52.     int          opnflg;
  53.     
  54.     if (loginfo -> ll_file == 0 || *(loginfo -> ll_file) == '\0')
  55.     return (loginfo -> ll_fd = NOTOK);
  56.                   /* no pathname => no place to log       */
  57.  
  58. #ifdef V4_2BSD
  59.     opnflg = (loginfo -> ll_stat & LLOGCYC) ? O_WRONLY : (O_WRONLY|O_APPEND);
  60. #else
  61.     opnflg = 1;
  62. #endif
  63.     if (loginfo -> ll_fd <= 0)   /* now closed; ALWAYS try               */
  64.     for (retries = _LLRETRY;
  65.         (loginfo -> ll_fd = open (loginfo -> ll_file, opnflg)) <= 0;
  66.         sleep (_LLSLEEP))
  67.     {                         /* exclusive & write access             */
  68.         if (errno != 26 ||    /* not simply busy                    */
  69.             !(loginfo -> ll_stat & LLOGWAT) ||
  70.             retries-- <= 0)
  71.         return (loginfo -> ll_fd = NOTOK);
  72.     }
  73.  
  74.     if (loginfo -> ll_timmax <= 0)
  75.     loginfo -> ll_timmax = LLTIMEOUT;
  76.     loginfo -> ll_timer = time((time_t *)0);
  77.     loginfo -> ll_fp = fdopen(loginfo -> ll_fd, "w");
  78.     return (ll_init (loginfo));
  79. }
  80.  
  81.  
  82. ll_close (loginfo)
  83. register struct ll_struct *loginfo;
  84. {                                 /* maybe close file; always clear fd  */
  85.     register int    fd;
  86.  
  87.     fd = loginfo -> ll_fd;
  88.     loginfo -> ll_fd = 0;        /* clear the fd: erase -1 or handle   */
  89.  
  90.     if (loginfo -> ll_stat & _LLDIDC)
  91.     {                             /* cycled during this open            */
  92.     if (fd > 0)               /* flag end, from rest of log         */
  93.         fwrite (&_cycled[5], sizeof(char), (sizeof _cycled) - 6,
  94.             loginfo -> ll_fp);
  95.     loginfo -> ll_stat &= ~_LLDIDC;
  96.     }                             /* clear cycled flag                  */
  97.  
  98.     return ((fd > 0) ? fclose (loginfo -> ll_fp) : NULL);
  99.                   /* -1 or 0 => nothing was open        */
  100. }
  101. /*  *********************  LOG INITIALIZATION  *********************** */
  102.  
  103. ll_hdinit (loginfo, pref)              /* make header field unique           */
  104. register struct ll_struct *loginfo;
  105. register char *pref;
  106. {
  107.     char *curhdr;
  108.     char tmpstr[16];
  109.     static int pid;
  110.  
  111.     if (pid == 0)
  112.         pid = getpid();
  113.     
  114.     if ((curhdr = pref) == (char *) 0)
  115.     if ((curhdr = loginfo -> ll_hdr) == (char *) 0)
  116.         curhdr = "XXXXXX";
  117.  
  118.     (void) sprintf (tmpstr, "%-6.6s%04d", curhdr, pid % 10000);
  119.                 /* use last 4 digits of procid          */
  120.  
  121.     loginfo -> ll_hdr = strdup (tmpstr);
  122.     ll_close (loginfo);          /* start with a clean pointer        */
  123. }
  124.  
  125. ll_init (loginfo)                /* position log [print header]        */
  126. register struct ll_struct *loginfo;
  127. {
  128.     if (loginfo -> ll_fd < 0)
  129.     return (NOTOK);
  130.  
  131. #ifdef V4_2BSD
  132.     if ((loginfo -> ll_stat & LLOGCYC) == 0) /*..... don't fseek */
  133. #endif
  134.     fseek (loginfo -> ll_fp, 0L, 2);
  135.  
  136.  
  137.     if ((loginfo->ll_stat & LLOGCYC) && (ll_cycle (loginfo) < OK))
  138.     return (NOTOK);          /* too big and can't cycle            */
  139.  
  140.     if ((loginfo -> ll_stat & (LLOGCLS | LLOGTIMED)))
  141.     return (OK);              /* don't do header for opening        */
  142.  
  143.     if (loginfo -> ll_hdr == (char *) 0) /* give it a place-holder      */
  144.     loginfo -> ll_hdr = "";
  145.  
  146.     ll_time (loginfo, LONGTIM);
  147.     errno_save = errno;
  148.     fprintf (loginfo -> ll_fp, "---  OPEN  ---(%d)\n", loginfo -> ll_fd);
  149.     errno = errno_save;
  150.  
  151.     return (OK);
  152. }
  153.  
  154. /*  *********************  DO THE LOGGING  *************************** */
  155.  
  156. /* VARARGS3 */
  157. ll_log (loginfo, verblev, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a0)
  158. register struct ll_struct *loginfo;
  159. int     verblev;
  160. char   *format,
  161.        *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a0;
  162. {
  163.     if (verblev > loginfo -> ll_level)
  164.     return (OK);              /* too verbose for this setting       */
  165.  
  166.     switch (loginfo -> ll_fd)
  167.     {
  168.     case NOTOK:           /* error in its past                  */
  169.         return (OK);
  170.  
  171.     case 0:
  172.         if (ll_open (loginfo) < OK)
  173.         return (NOTOK);   /* couldn't open it properly          */
  174.         break;
  175.  
  176.     default:           
  177.         if (loginfo -> ll_stat & LLOGTIMED)
  178.         {
  179.             if (ll_tmout(loginfo) < OK)
  180.             return (NOTOK);
  181.         }
  182.         else if (ll_cycle (loginfo) < OK)  /* check file size    */
  183.         return (NOTOK);
  184.     }
  185.  
  186.     ll_time (loginfo, 
  187.          (loginfo -> ll_stat & (LLOGCLS | LLOGTIMED)) ? LONGTIM : SHORTIM);
  188.     errno_save = errno;
  189.     fprintf(loginfo->ll_fp,
  190.         format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a0);
  191.     (void) putc('\n', loginfo->ll_fp);
  192.     errno = errno_save;
  193.  
  194.     fflush(loginfo->ll_fp);
  195.  
  196.     if (loginfo -> ll_stat & LLOGCLS)
  197.     {
  198.     if (ll_close (loginfo) == EOF)
  199.         return (loginfo -> ll_fd = NOTOK);
  200.     }
  201.                   /* error or close after each entry    */
  202.     return (OK);
  203. }
  204.  
  205. /*  *********************  INTERNAL ROUTINES  ************************ */
  206.  
  207. LOCFUN
  208.     ll_tmout(loginfo)
  209. register struct ll_struct *loginfo;
  210. {
  211.     int temp;
  212.     time_t now;
  213.  
  214.     now = time((time_t *)0);
  215.  
  216.     if ((now - (loginfo->ll_timer)) > (loginfo -> ll_timmax))
  217.     {
  218.  
  219.     if ((temp = ll_close(loginfo)) < OK)
  220.         return(temp);
  221.  
  222.     return (ll_open(loginfo));
  223.     }
  224.  
  225.     return (ll_init(loginfo));
  226. }
  227.  
  228.  
  229. LOCFUN
  230.     ll_cycle (loginfo)        /* file not within limits => cycle     */
  231. register struct ll_struct *loginfo;
  232. {
  233.     int stats;
  234.     register int    numblocks,
  235.             maxblocks;
  236.  
  237.     if ((maxblocks = loginfo -> ll_msize) <= 0)
  238.     return (OK);
  239.  
  240.     maxblocks *= 25;              /* units of 25 blocks                   */
  241.     numblocks = ll_size (loginfo);
  242.  
  243.     if ((stats = loginfo -> ll_stat) & _LLDIDC)
  244.     {                             /* different test if already cycled     */
  245.     if (numblocks > maxblocks + 1)
  246.         goto endit;           /* the sucker REwrote length of file    */
  247.     }
  248.     else
  249.     if (numblocks >= maxblocks)
  250.     {                         /* normal uncycled check                */
  251.         if ((stats & LLOGCLS) || !(stats & LLOGCYC))
  252.         {                     /* give up if one-liner or no cycling   */
  253. endit:
  254.         ll_close (loginfo);
  255.         return (loginfo -> ll_fd = NOTOK);
  256.         }
  257.                   /* record status of llog file           */
  258.         loginfo -> ll_msize = numblocks / 25;
  259.         loginfo -> ll_stat |= _LLDIDC;
  260.                   /* make notes in it & goto beginning    */
  261.  
  262.         fseek (loginfo->ll_fp, -20L, 1);
  263.         fwrite(_cycling, sizeof(char), sizeof _cycling - 1,
  264.             loginfo->ll_fp);
  265.         fseek (loginfo->ll_fp, 0L, 0);
  266.         fwrite(_cycled, sizeof(char), sizeof _cycled - 1,
  267.             loginfo->ll_fp);
  268.     }
  269.     return (OK);
  270. }
  271. /* */
  272.  
  273. LOCFUN
  274.     ll_size (loginfo)       /* how big is log file?               */
  275. register struct ll_struct *loginfo;
  276. {
  277.     struct stat llstat;
  278.  
  279.     if(fflush(loginfo->ll_fp) == EOF)  /* must show what is buffered too */
  280.     return (0);
  281.     if (fstat(loginfo -> ll_fd, &llstat) < 0)
  282.     return (0);
  283.  
  284.     /*NOSTRICT*/
  285.     return ((st_gsize (&llstat) + 1023L)/1024L);
  286. }
  287. /* */
  288.  
  289. LOCFUN
  290.     ll_time (loginfo, timtype)
  291. register struct ll_struct *loginfo;
  292. int     timtype;
  293. {                  /* record real date/time              */
  294.     extern struct tm   *localtime ();
  295.     time_t clock;
  296.     register struct tm *tpt;
  297.  
  298.     time (&clock);
  299.     tpt = localtime (&clock);
  300.  
  301.     errno_save = errno;
  302.     switch (timtype)
  303.     {
  304.     case LONGTIM:           /* mm/dd hh:mm:ss                       */
  305.         fprintf (loginfo->ll_fp, "%2d/%2d %2d:%02d:%02d %s:  ",
  306.             tpt->tm_mon + 1, tpt->tm_mday, tpt->tm_hour,
  307.             tpt->tm_min, tpt->tm_sec, loginfo -> ll_hdr);
  308.         break;
  309.  
  310.     case SHORTIM:           /* mm:ss                                */
  311.         fprintf (loginfo->ll_fp, "%2d:%02d ", tpt->tm_min, tpt->tm_sec);
  312.     }
  313.     errno = errno_save;
  314. }
  315.