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: debug.c,v 1.17.4.3.4.3.2.9 2003/01/04 17:46:09 martinea Exp $
30 * debug log subroutines
39 # define AMANDA_DBGDIR AMANDA_TMPDIR
48 static int db_fd = 2; /* default is stderr */
49 static FILE *db_file = NULL; /* stderr may not be a constant */
50 static char *db_filename = NULL;
52 static pid_t debug_prefix_pid = 0;
55 * Format and write a debug message to the process debug file.
57 printf_arglist_function(void debug_printf, char *, format)
63 * It is common in the code to call dbprintf to write out
64 * syserrno(errno) and then turn around and try to do something else
65 * with errno (e.g. printf() or log()), so we make sure errno goes
66 * back out with the same value it came in with.
70 if(db_file == NULL && db_fd == 2) {
74 arglist_start(argp, format);
75 vfprintf(db_file, format, argp);
84 * Generate a debug file name. The name is based on the program name,
85 * followed by a timestamp, an optional sequence number, and ".debug".
92 char number[NUM_STR_SIZE];
96 if(n < 0 || n > 1000) {
99 ts = construct_timestamp(&t);
103 ap_snprintf(number, sizeof(number), "%03d", n - 1);
105 result = vstralloc(get_pname(), ".", ts, number, ".debug", NULL);
117 char *dbfilename = NULL;
119 struct dirent *entry;
123 char *test_name = NULL;
124 size_t test_name_len;
128 int fd_close[MIN_DB_FD+1];
129 struct passwd *pwent;
133 pname_len = strlen(pname);
135 if(client_uid == (uid_t) -1 && (pwent = getpwnam(CLIENT_LOGIN)) != NULL) {
136 client_uid = pwent->pw_uid;
137 client_gid = pwent->pw_gid;
142 * Create the debug directory if it does not yet exist.
144 dbgdir = stralloc2(AMANDA_DBGDIR, "/");
145 if(mkpdir(dbgdir, 02700, client_uid, client_gid) == -1) {
146 error("create debug directory \"%s\": %s",
147 AMANDA_DBGDIR, strerror(errno));
151 * Clean out old debug files. We also rename files with old style
152 * names (XXX.debug or XXX.$PID.debug) into the new name format.
153 * We assume no system has 17 digit PID-s :-) and that there will
154 * not be a conflict between an old and new name.
156 if((d = opendir(AMANDA_DBGDIR)) == NULL) {
157 error("open debug directory \"%s\": %s",
158 AMANDA_DBGDIR, strerror(errno));
161 test_name = get_debug_name(curtime - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
162 test_name_len = strlen(test_name);
163 while((entry = readdir(d)) != NULL) {
164 if(is_dot_or_dotdot(entry->d_name)) {
167 d_name_len = strlen(entry->d_name);
168 if(strncmp(entry->d_name, pname, pname_len) != 0
169 || entry->d_name[pname_len] != '.'
171 || strcmp(entry->d_name + d_name_len - 6, ".debug") != 0) {
172 continue; /* not one of our debug files */
174 e = newvstralloc(e, dbgdir, entry->d_name, NULL);
175 if(d_name_len < test_name_len) {
177 * Create a "pretend" name based on the last modification
178 * time. This name will be used to decide if the real name
179 * should be removed. If not, it will be used to rename the
182 if(stat(e, &sbuf) != 0) {
183 continue; /* ignore errors */
186 dbfilename = get_debug_name((time_t)sbuf.st_mtime, 0);
189 dbfilename = newstralloc(dbfilename, entry->d_name);
192 if(strcmp(dbfilename, test_name) < 0) {
193 (void) unlink(e); /* get rid of old file */
198 while(dbfilename != NULL
199 && (s = newvstralloc(s, dbgdir, dbfilename, NULL)) != NULL
200 && rename(e, s) != 0 && errno != ENOENT) {
202 dbfilename = get_debug_name((time_t)sbuf.st_mtime, ++i);
204 if(dbfilename == NULL) {
205 error("cannot rename old debug file \"%s\"", entry->d_name);
216 * Create the new file.
219 (dbfilename = get_debug_name(curtime, i)) != NULL
220 && (s = newvstralloc(s, dbgdir, dbfilename, NULL)) != NULL
221 && (fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0600)) < 0;
222 i++, free(dbfilename)) {}
223 if(dbfilename == NULL) {
224 error("cannot create %s debug file", get_pname());
230 (void) chown(db_filename, client_uid, client_gid);
234 * Move the file descriptor up high so it stays out of the way
235 * of other processing, e.g. sendbackup.
239 while((db_fd = dup(fd)) < MIN_DB_FD) {
240 fd_close[i++] = db_fd;
245 db_file = fdopen(db_fd, "a");
248 * Make the first debug log file entry.
250 saved_debug = debug; debug = 1;
251 debug_printf("%s: debug %d pid %ld ruid %ld euid %ld: start at %s",
252 pname, saved_debug, (long)getpid(),
253 (long)getuid(), (long)geteuid(),
267 save_pid = debug_prefix_pid;
268 debug_prefix_pid = 0;
269 debug_printf("%s: pid %ld finish time %s",
270 debug_prefix_time(NULL),
273 debug_prefix_pid = save_pid;
276 if(db_file && fclose(db_file) == EOF) {
277 int save_errno = errno;
279 db_file = NULL; /* prevent recursion */
280 error("close debug file: %s", strerror(save_errno));
303 * Routines for returning a common debug file line prefix. Always starts
304 * with the current program name, possibly with an optional suffix.
305 * May then be followed by a PID. May then be followed by an elapsed
309 void set_debug_prefix_pid(p)
312 debug_prefix_pid = p;
315 char *debug_prefix(suffix)
318 static char *s = NULL;
319 char debug_pid[NUM_STR_SIZE];
321 s = newvstralloc(s, get_pname(), suffix, NULL);
322 if (debug_prefix_pid != (pid_t) 0) {
323 ap_snprintf(debug_pid, sizeof(debug_pid),
325 (long) debug_prefix_pid);
326 s = newvstralloc(s, s, "[", debug_pid, "]", NULL);
331 char *debug_prefix_time(suffix)
334 static char *s = NULL;
338 if (clock_is_running()) {
340 t2 = walltime_str(curclock());
345 s = newvstralloc(s, debug_prefix(suffix), t1, t2, NULL);