2 * Implementation of logging facilities.
4 * Europagate, 1994-1995.
7 * Revision 1.9 1995/04/19 12:12:06 adam
8 * Resource system uses only one log debug level.
10 * Revision 1.8 1995/04/17 09:36:16 adam
13 * Revision 1.7 1995/04/10 13:20:25 adam
14 * Use gettimeofday(2) instead of time(2) to get log time in milliseconds.
16 * Revision 1.6 1995/03/28 08:01:51 adam
17 * Bug fix: GW_LOG_ERRNO.
19 * Revision 1.5 1995/03/27 12:51:10 adam
20 * New log level in use: GW_LOG_ERRNO.
22 * Revision 1.4 1995/02/23 08:32:22 adam
25 * Revision 1.2 1995/02/17 17:06:56 adam
26 * Remove everything before '/' in app_name. Use compact date format.
28 * Revision 1.1.1.1 1995/02/09 17:27:12 adam
29 * Initial version of email gateway under CVS control.
31 * Initial: Dec 7, 94 (Adam Dickmeiss)
46 static char *app_name = NULL;
47 static unsigned level = GW_LOG_DEFAULT;
48 static int session = 0;
51 unsigned mask; /* level mask for this file entry */
52 int fd; /* file descriptor for this file */
53 char *fname; /* name of file ("" if stdout) */
54 struct file_mask *next; /* next file in chain */
57 struct file_mask *file_mask_list = NULL;
59 char *gw_strdup (const char *s)
61 char *n = malloc (strlen(s)+1);
67 void gw_log_init (const char *app_name_a)
69 struct file_mask *list, *list1;
72 if ((cp = strrchr (app_name_a, '/')))
73 app_name = gw_strdup (cp+1);
75 app_name = gw_strdup (app_name_a);
76 level = GW_LOG_DEFAULT;
79 /* clean up all output file masks... */
80 for (list = file_mask_list; list; list = list1)
82 if (list->fd > 2) /* avoid closing stdout/stderr */
88 file_mask_list = NULL;
91 void gw_log_level (unsigned level_a)
96 void gw_log_session (int session_a)
101 int gw_log_file (unsigned level_a, const char *fname_a)
103 struct file_mask **listp, *new_file_mask;
104 listp = &file_mask_list;
106 /* go through file mask list and close files already associated */
110 if (!((*listp)->mask &= ~level_a)) /* any levels left on this one? */
112 if ((*listp)->fd > 2) /* close if not stdout/stderr */
113 close ((*listp)->fd);
114 free ((*listp)->fname);
115 *listp = (*listp)->next;
117 listp = &(*listp)->next;
119 if (!fname_a) /* stderr? */
120 return 0; /* stderr doesn't appear on list */
121 new_file_mask = malloc (sizeof(*new_file_mask));
124 new_file_mask->mask = level_a;
125 new_file_mask->next = file_mask_list;
126 file_mask_list = new_file_mask;
127 if (!(file_mask_list->fname = gw_strdup (fname_a)))
129 if (*fname_a == '\0') /* stdout? */
130 new_file_mask->fd = 1;
131 else /* no, open as usual */
133 new_file_mask->fd = open (fname_a, O_WRONLY|O_CREAT|O_APPEND, 0666);
134 if (new_file_mask->fd == -1)
140 int gw_log (unsigned level_a, const char *event_type, const char *format, ...)
142 static char emit_str[2048];
143 struct file_mask *list;
147 unsigned e_level = level_a & level;
153 if (!e_level) /* any effective level(s)? */
156 va_start (ap, format);
157 gettimeofday (&tv, &tz);
159 memcpy (&tms, localtime (&tv.tv_sec), sizeof(tms));
160 sprintf (emit_str, "%s %d %02d%02d%02d%02d%02d%02d%03d %d %s ",
162 tms.tm_year, 1+tms.tm_mon, tms.tm_mday,
163 tms.tm_hour, tms.tm_min, tms.tm_sec,
164 (int) (tv.tv_usec/1000),
165 e_level, event_type);
166 if ((cp = strchr (emit_str, '\n'))) /* remove \n from ctime-str */
168 count = strlen (emit_str);
169 vsprintf (emit_str+count, format, ap);
170 if (level_a & GW_LOG_ERRNO)
172 strcat (emit_str, ": ");
173 strcat (emit_str, strerror (errno));
175 strcat (emit_str, "\n");
176 count = strlen (emit_str);
178 /* go through file mask list... */
179 for (list = file_mask_list; list; list = list->next)
180 if (list->mask & e_level) /* output this one? */
182 e_level &= ~list->mask; /* remove from effective level */
183 if (write (list->fd, emit_str, count) != count)
186 if (e_level) /* bits left on effective level? */
187 write (2, emit_str, count);