2 Routines to add entries to the log files.
4 Copyright (C) 1991, 1992, 1993, 1994, 1995 Ian Lance Taylor
6 This file is part of the Taylor UUCP package.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 The author of the program may be contacted at ian@airs.com or
23 c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
29 const char log_rcsid[] = "$FreeBSD$";
49 /* Local functions. */
51 __inline__ static char *zstpcpy P((char *zto, const char *zfrom));
52 static const char *zldate_and_time P((void));
54 /* Program name. Set by main function. */
58 static const char *zLogfile;
60 /* The function to call when a LOG_FATAL error occurs. */
61 static void (*pfLfatal) P((void));
63 /* Whether to go to a file. */
64 static boolean fLfile;
69 /* The current user name. */
72 /* The current system name. */
73 static char *zLsystem;
75 /* The current device name. */
78 /* The open log file. */
81 /* Whether we have tried to open the log file. We need this because
82 we don't want to keep trying to open the log file if we failed the
83 first time. It can't be static because under HAVE_HDB_LOGGING we
84 may have to write to various different log files. */
85 static boolean fLlog_tried;
88 /* Debugging file name. */
89 static const char *zLdebugfile;
91 /* The open debugging file. */
94 /* Whether we've tried to open the debugging file. */
95 static boolean fLdebug_tried;
98 /* Statistics file name. */
99 static const char *zLstatsfile;
101 /* The open statistics file. */
102 static FILE *eLstats;
104 /* Whether we've tried to open the statistics file. */
105 static boolean fLstats_tried;
107 /* The array of signals. The elements are only set to TRUE by the
108 default signal handler. They are only set to FALSE if we don't
109 care whether we got the signal or not. */
110 volatile sig_atomic_t afSignal[INDEXSIG_COUNT];
112 /* The array of signals to log. The elements are only set to TRUE by
113 the default signal handler. They are set to FALSE when the signal
114 is logged in ulog. This means that if a signal comes in at just
115 the right time we won't log it (or, rather, we'll log it once
116 instead of twice), but that is not a catatrophe. */
117 volatile sig_atomic_t afLog_signal[INDEXSIG_COUNT];
119 /* Flag that indicates SIGHUP is worth logging. */
120 boolean fLog_sighup = TRUE;
122 /* Signal names to use when logging signals. */
123 static const char * const azSignal_names[INDEXSIG_COUNT] = INDEXSIG_NAMES;
125 /* If not NULL, ulog calls this function before outputting anything.
126 This is used to support cu. */
127 void (*pfLstart) P((void));
129 /* If not NULL, ulog calls this function after outputting everything.
130 This is used to support cu. */
131 void (*pfLend) P((void));
133 /* Set the function to call on a LOG_FATAL error. */
137 void (*pfn) P((void));
142 /* Decide whether to send log message to the file or not. */
145 ulog_to_file (puuconf, ffile)
151 iuuconf = uuconf_logfile (puuconf, &zLogfile);
152 if (iuuconf != UUCONF_SUCCESS)
153 ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
156 iuuconf = uuconf_debugfile (puuconf, &zLdebugfile);
157 if (iuuconf != UUCONF_SUCCESS)
158 ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
161 iuuconf = uuconf_statsfile (puuconf, &zLstatsfile);
162 if (iuuconf != UUCONF_SUCCESS)
163 ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
168 /* Set the ID number. This will be called by the usysdep_initialize
169 if there is something sensible to set it to. */
178 /* Set the user we are making log entries for. The arguments will be
179 copied into memory. */
186 zLuser = zbufcpy (zuser);
189 /* Set the system name we are making log entries for. The name is copied
193 ulog_system (zsystem)
198 || strcmp (zsystem, zLsystem) != 0)
201 zLsystem = zbufcpy (zsystem);
203 /* Under HDB logging we now must write to a different log file. */
205 #endif /* HAVE_HDB_LOGGING */
209 /* Set the device name. This is copied into memory. */
212 ulog_device (zdevice)
216 zLdevice = zbufcpy (zdevice);
219 /* A helper function for ulog. */
221 __inline__ static char *
226 while ((*zto++ = *zfrom++) != '\0')
231 /* Make a log entry. We make a token concession to non ANSI_C systems,
232 but it clearly won't always work. */
234 #if ! HAVE_PROTOTYPES || ! HAVE_STDARG_H
236 #define HAVE_VFPRINTF 0
242 ulog (enum tlog ttype, const char *zmsg, ...)
245 ulog (ttype, zmsg, a, b, c, d, f, g, h, i, j)
254 boolean fstart, fend;
261 /* Log any received signal. We do it this way to avoid calling ulog
262 from the signal handler. A few routines call ulog to get this
263 message out with zmsg == NULL. */
265 static boolean fdoing_sigs;
272 for (isig = 0; isig < INDEXSIG_COUNT; isig++)
274 if (afLog_signal[isig])
276 afLog_signal[isig] = FALSE;
278 /* Apparently SunOS sends SIGINT rather than SIGHUP
279 when hanging up, so we don't log either signal if
280 fLog_sighup is FALSE. */
281 if ((isig != INDEXSIG_SIGHUP && isig != INDEXSIG_SIGINT)
283 ulog (LOG_ERROR, "Got %s signal", azSignal_names[isig]);
291 /* If we've had a debugging file open in the past, then we want to
292 write all log file entries to the debugging file even if it's
299 fLdebug_tried = TRUE;
300 eLdebug = esysdep_fopen (zLdebugfile, FALSE, TRUE, TRUE);
302 #endif /* DEBUG > 1 */
307 else if ((int) ttype >= (int) LOG_DEBUG)
311 /* If we can't open the debugging file, don't output any
312 debugging messages. */
316 #endif /* DEBUG > 1 */
319 if (eLlog == NULL && ! fLlog_tried)
321 const char *zprint = NULL;
324 #if ! HAVE_HDB_LOGGING
325 eLlog = esysdep_fopen (zLogfile, TRUE, TRUE, TRUE);
327 #else /* HAVE_HDB_LOGGING */
334 /* We want to write to .Log/program/system, e.g.
335 .Log/uucico/uunet. The system name may not be set. */
336 if (zLsystem == NULL)
341 zbase = zsysdep_base_name (zProgram);
343 zbase = zbufcpy (zProgram);
345 /* On some systems the native uusched will invoke uucico
346 with an upper case argv[0]. We work around that by
347 forcing the filename to lower case here. */
348 for (zlower = zbase; *zlower != '\0'; zlower++)
349 if (isupper (*zlower))
350 *zlower = tolower (*zlower);
352 zfile = zbufalc (strlen (zLogfile)
356 sprintf (zfile, zLogfile, zbase, zsys);
358 eLlog = esysdep_fopen (zfile, TRUE, TRUE, TRUE);
364 #endif /* HAVE_HDB_LOGGING */
368 /* We can't open the log file. We report the problem to
369 stderr. This is not ideal, since if this is uucico
370 running on an inbound call stderr is actually
371 connected to a remote system, but is better than
373 fprintf (stderr, "%s: %s: can not open log file: %s\n",
374 zProgram, zprint, strerror (errno));
375 if (pfLfatal != NULL)
377 usysdep_exit (FALSE);
383 /* eLlog might be NULL here because we might try to open the log
384 file recursively via esysdep_fopen. */
392 if (pfLstart != NULL)
397 if ((int) ttype < (int) LOG_DEBUG)
419 case LOG_DEBUG_START:
423 case LOG_DEBUG_CONTINUE:
439 zprefix = zbufcpy ("");
444 zprefix = zbufalc (strlen (zProgram) + 3);
445 sprintf (zprefix, "%s: ", zProgram);
449 zprefix = zbufalc (strlen (zProgram)
450 + (zLsystem == NULL ? 1 : strlen (zLsystem))
451 + (zLuser == NULL ? 4 : strlen (zLuser))
452 + sizeof "1991-12-31 12:00:00.00"
456 #if HAVE_TAYLOR_LOGGING
460 zbase = zsysdep_base_name (zProgram);
462 zbase = zbufcpy (zProgram);
463 zset = zstpcpy (zset, zbase);
467 #else /* ! HAVE_TAYLOR_LOGGING */
468 zset = zstpcpy (zset, zLuser == NULL ? "uucp" : zLuser);
470 #endif /* HAVE_TAYLOR_LOGGING */
472 zset = zstpcpy (zset, zLsystem == NULL ? "-" : zLsystem);
475 #if HAVE_TAYLOR_LOGGING
476 zset = zstpcpy (zset, zLuser == NULL ? "-" : zLuser);
478 #endif /* HAVE_TAYLOR_LOGGING */
481 zset = zstpcpy (zset, zldate_and_time ());
485 #if ! HAVE_HDB_LOGGING
486 #if HAVE_TAYLOR_LOGGING
487 sprintf (zset, " %d", iLid);
488 #else /* ! HAVE_TAYLOR_LOGGING */
489 sprintf (zset, "-%d", iLid);
490 #endif /* ! HAVE_TAYLOR_LOGGING */
491 #else /* HAVE_HDB_LOGGING */
492 /* I assume that the second number here is meant to be
493 some sort of file sequence number, and that it should
494 correspond to the sequence number in the statistics
495 file. I don't have any really convenient way to do
496 this, so I won't unless somebody thinks it's very
498 sprintf (zset, ",%d,%d", iLid, 0);
499 #endif /* HAVE_HDB_LOGGING */
501 zset += strlen (zset);
505 sprintf (zset, " %ld", (long) getnid ());
506 zset += strlen (zset);
516 zformat = zbufalc (2 * strlen (zprefix) + strlen (zmsg) + 2);
520 while (*zfrom != '\0')
529 zset = zstpcpy (zset, zmsg);
538 va_start (parg, zmsg);
539 vfprintf (e, zformat, parg);
543 va_start (parg, zmsg);
544 vfprintf (edebug, zformat, parg);
547 #else /* ! HAVE_VFPRINTF */
548 fprintf (e, zformat, a, b, c, d, f, g, h, i, j);
550 fprintf (edebug, zformat, a, b, c, d, f, g, h, i, j);
551 #endif /* ! HAVE_VFPRINTF */
557 (void) fflush (edebug);
562 if (ttype == LOG_FATAL)
564 if (pfLfatal != NULL)
566 usysdep_exit (FALSE);
574 /* Log a uuconf error. */
577 ulog_uuconf (ttype, puuconf, iuuconf)
584 (void) uuconf_error_string (puuconf, iuuconf, ab, sizeof ab);
585 ulog (ttype, "%s", ab);
588 /* Close the log file. There's nothing useful we can do with errors,
589 so we don't check for them. */
594 /* Make sure we logged any signal we received. */
595 ulog (LOG_ERROR, (const char *) NULL);
599 (void) fclose (eLlog);
607 (void) fclose (eLdebug);
609 fLdebug_tried = FALSE;
614 /* Add an entry to the statistics file. We may eventually want to put
615 failed file transfers in here, but we currently do not. */
619 ustats (fsucceeded, zuser, zsystem, fsent, cbytes, csecs, cmicros, fcaller)
631 /* The seconds and microseconds are now counted independently, so
632 they may be out of synch. */
635 csecs -= ((- cmicros) / 1000000L) + 1;
636 cmicros = 1000000L - ((- cmicros) % 1000000L);
638 if (cmicros >= 1000000L)
640 csecs += cmicros / 10000000L;
641 cmicros = cmicros % 1000000L;
644 /* On a system which can determine microseconds we might very well
645 have both csecs == 0 and cmicros == 0. */
646 if (csecs == 0 && cmicros < 1000)
650 long cmillis, cdiv, crem;
652 /* Compute ((csecs * 1000) / cmillis) using integer division.
653 Where DIV is integer division, we know
654 a = (a DIV b) * b + a % b
656 a / b = (a DIV b) + (a % b) / b
657 We compute the latter with a as csecs and b as cmillis,
658 mixing the multiplication by 1000. */
659 cmillis = csecs * 1000 + cmicros / 1000;
660 cdiv = (cbytes / cmillis) * 1000;
661 crem = (cbytes % cmillis) * 1000;
662 cbps = cdiv + (crem / cmillis);
663 if (cmillis < 0 || cdiv < 0 || crem < 0 || cbps < 0)
665 /* We overflowed using milliseconds, so use seconds. */
666 cbps = cbytes / (csecs + ((cmicros > 500000L) ? 1 : 0));
674 fLstats_tried = TRUE;
675 eLstats = esysdep_fopen (zLstatsfile, TRUE, TRUE, TRUE);
680 #if HAVE_TAYLOR_LOGGING
682 "%s %s (%s) %s%s %ld bytes in %ld.%03ld seconds (%ld bytes/sec) on port %s\n",
683 zuser, zsystem, zldate_and_time (),
684 fsucceeded ? "" : "failed after ",
685 fsent ? "sent" : "received",
686 cbytes, csecs, cmicros / 1000, cbps,
687 zLdevice == NULL ? "unknown" : zLdevice);
688 #endif /* HAVE_TAYLOR_LOGGING */
691 "%s %s (%s) (%ld) %s %s %ld bytes %ld seconds\n",
692 zuser, zsystem, zldate_and_time (),
693 (long) time ((time_t *) NULL),
694 fsent ? "sent" : "received",
695 fsucceeded ? "data" : "failed after",
696 cbytes, csecs + cmicros / 500000);
697 #endif /* HAVE_V2_LOGGING */
702 /* I don't know what the 'C' means. The sequence number should
703 probably correspond to the sequence number in the log file, but
704 that is currently always 0; using this fake sequence number
705 will still at least reveal which transfers are from different
709 "%s!%s %c (%s) (C,%d,%d) [%s] %s %ld / %ld.%03ld secs, %ld%s%s\n",
710 zsystem, zuser, fcaller ? 'M' : 'S', zldate_and_time (),
711 iLid, iseq, zLdevice == NULL ? "unknown" : zLdevice,
713 cbytes, csecs, cmicros / 1000, cbps,
715 fsucceeded ? "" : " [PARTIAL FILE]");
717 #endif /* HAVE_HDB_LOGGING */
719 (void) fflush (eLstats);
726 /* Close the statistics file. */
733 if (fclose (eLstats) != 0)
734 ulog (LOG_ERROR, "fclose: %s", strerror (errno));
736 fLstats_tried = FALSE;
740 /* Return the date and time in a form used for a log entry. */
747 #if HAVE_TAYLOR_LOGGING
748 static char ab[sizeof "1991-12-31 12:00:00.00"];
751 static char ab[sizeof "12/31-12:00"];
754 static char ab[sizeof "12/31-12:00:00"];
757 isecs = ixsysdep_time (&imicros);
758 usysdep_localtime (isecs, &s);
760 #if HAVE_TAYLOR_LOGGING
761 sprintf (ab, "%04d-%02d-%02d %02d:%02d:%02d.%02d",
762 s.tm_year + 1900, s.tm_mon + 1, s.tm_mday, s.tm_hour,
763 s.tm_min, s.tm_sec, (int) (imicros / 10000));
766 sprintf (ab, "%d/%d-%02d:%02d", s.tm_mon + 1, s.tm_mday,
767 s.tm_hour, s.tm_min);
770 sprintf (ab, "%d/%d-%d:%02d:%02d", s.tm_mon + 1, s.tm_mday,
771 s.tm_hour, s.tm_min, s.tm_sec);