2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: James da Silva, Systems Design and Analysis Group
24 * Computer Science Department
25 * University of Maryland at College Park
28 * $Id: logfile.c,v 1.17.4.1.4.2.2.3 2003/01/01 23:28:56 martinea Exp $
30 * common log file writing routine
38 char *logtype_str[] = {
40 "FATAL", /* program died for some reason, used by error() */
41 "ERROR", "WARNING", "INFO", "SUMMARY", /* information messages */
42 "START", "FINISH", /* start/end of a run */
44 "SUCCESS", "FAIL", "STRANGE", /* the end of a dump */
45 "STATS", /* statistics */
46 "MARKER", /* marker for reporter */
47 "CONT" /* continuation line; special */
50 char *program_str[] = {
51 "UNKNOWN", "planner", "driver", "amreport", "dumper", "taper", "amflush"
61 static int logfd = -1;
64 * Note that technically we could use two locks, a read lock
65 * from 0-EOF and a write-lock from EOF-EOF, thus leaving the
66 * beginning of the file open for read-only access. Doing so
67 * would open us up to some race conditions unless we're pretty
68 * careful, and on top of that the functions here are so far
69 * the only accesses to the logfile, so keep things simple.
73 static void open_log P((void));
74 static void close_log P((void));
79 log_add(L_FATAL, "%s", msg);
82 printf_arglist_function1(void log_add, logtype_t, typ, char *, format)
87 char linebuf[STR_SIZE];
91 /* format error message */
93 if((int)typ <= (int)L_BOGUS || (int)typ > (int)L_MARKER) typ = L_BOGUS;
96 leader = stralloc(" "); /* continuation line */
98 leader = vstralloc(logtype_str[(int)typ], " ", get_pname(), " ", NULL);
101 arglist_start(argp, format);
102 ap_vsnprintf(linebuf, sizeof(linebuf)-1, format, argp);
103 /* -1 to allow for '\n' */
106 /* avoid recursive call from error() */
108 saved_errout = erroutput_type;
109 erroutput_type &= ~ERR_AMANDALOG;
111 /* append message to the log file */
113 if(multiline == -1) open_log();
115 for(l = 0, n = strlen(leader); l < n; l += s) {
116 if((s = write(logfd, leader + l, n - l)) < 0) {
117 error("log file write error: %s", strerror(errno));
124 if(n == 0 || linebuf[n-1] != '\n') linebuf[n++] = '\n';
127 for(l = 0; l < n; l += s) {
128 if((s = write(logfd, linebuf + l, n - l)) < 0) {
129 error("log file write error: %s", strerror(errno));
133 if(multiline != -1) multiline++;
136 erroutput_type = saved_errout;
139 void log_start_multiline()
141 assert(multiline == -1);
148 void log_end_multiline()
150 assert(multiline != -1);
156 void log_rename(datestamp)
162 char seq_str[NUM_STR_SIZE];
166 if(datestamp == NULL) datestamp = "error";
168 conf_logdir = getconf_str(CNF_LOGDIR);
169 if (*conf_logdir == '/') {
170 conf_logdir = stralloc(conf_logdir);
172 conf_logdir = stralloc2(config_dir, conf_logdir);
174 logfile = vstralloc(conf_logdir, "/log", NULL);
176 for(seq = 0; 1; seq++) { /* if you've got MAXINT files in your dir... */
177 ap_snprintf(seq_str, sizeof(seq_str), "%d", seq);
178 fname = newvstralloc(fname,
183 if(stat(fname, &statbuf) == -1 && errno == ENOENT) break;
186 if(rename(logfile, fname) != 0) {
187 error("could not rename \"%s\" to \"%s\": %s",
188 logfile, fname, strerror(errno));
197 static void open_log()
201 conf_logdir = getconf_str(CNF_LOGDIR);
202 if (*conf_logdir == '/') {
203 conf_logdir = stralloc(conf_logdir);
205 conf_logdir = stralloc2(config_dir, conf_logdir);
207 logfile = vstralloc(conf_logdir, "/log", NULL);
210 logfd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600);
213 error("could not open log file %s: %s", logfile, strerror(errno));
216 if(amflock(logfd, "log") == -1)
217 error("could not lock log file %s: %s", logfile, strerror(errno));
221 static void close_log()
223 if(amfunlock(logfd, "log") == -1)
224 error("could not unlock log file %s: %s", logfile, strerror(errno));
226 if(close(logfd) == -1)
227 error("close log file: %s", strerror(errno));
234 int get_logline(logf)
237 static char *logline = NULL;
238 char *logstr, *progstr;
243 if((logline = agets(logf)) == NULL) return 0;
248 /* continuation lines are special */
250 if(logline[0] == ' ' && logline[1] == ' ') {
252 /* curprog stays the same */
253 skip_whitespace(s, ch);
258 /* isolate logtype field */
260 skip_whitespace(s, ch);
262 skip_non_whitespace(s, ch);
265 /* isolate program name field */
267 skip_whitespace(s, ch);
269 skip_non_whitespace(s, ch);
272 /* rest of line is logtype dependent string */
274 skip_whitespace(s, ch);
279 for(curlog = L_MARKER; curlog != L_BOGUS; curlog--)
280 if(strcmp(logtype_str[curlog], logstr) == 0) break;
282 for(curprog = P_LAST; curprog != P_UNKNOWN; curprog--)
283 if(strcmp(program_str[curprog], progstr) == 0) break;