/* log a change in tracing */ void tracelevel_msg(const char *pat, int dump) /* -1=no dump, 0=default, 1=force */ { static const char *off_msgs[MAX_TRACELEVEL] = { "Tracing actions stopped", "Tracing packets stopped", "Tracing packet contents stopped", "Tracing kernel changes stopped", "Tracing routing socket messages stopped", }; static const char *on_msgs[MAX_TRACELEVEL] = { "Tracing actions started", "Tracing packets started", "Tracing packet contents started", "Tracing kernel changes started", "Tracing routing socket messages started", }; uint_t old_tracelevel = tracelevel; if (new_tracelevel < 0) new_tracelevel = 0; else if (new_tracelevel > MAX_TRACELEVEL) new_tracelevel = MAX_TRACELEVEL; if (new_tracelevel < tracelevel) { if (new_tracelevel <= 0) { trace_off(pat, off_msgs[0]); } else { do { tmsg(pat, off_msgs[tracelevel]); } while (--tracelevel != new_tracelevel); } } else if (new_tracelevel > tracelevel) { do { tmsg(pat, on_msgs[tracelevel++]); } while (tracelevel != new_tracelevel); } if (dump > 0 || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) trace_dump(); }
void set_tracefile(const char *filename, const char *pat, int dump) /* -1=no dump, 0=default, 1=force */ { struct stat stbuf; FILE *n_ftrace; const char *fn; /* Allow a null filename to increase the level if the trace file * is already open or if coming from a trusted source, such as * a signal or the command line. */ if (filename == NULL || filename[0] == '\0') { filename = NULL; if (ftrace == NULL) { if (inittracename[0] == '\0') { msglog("missing trace file name"); return; } fn = inittracename; } else { fn = NULL; } } else if (!strcmp(filename,"dump/../table")) { trace_dump(); return; } else { /* Allow the file specified with "-T file" to be reopened, * but require all other names specified over the net to * match the official path. The path can specify a directory * in which the file is to be created. */ if (strcmp(filename, inittracename) #ifdef _PATH_TRACE && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) || strstr(filename,"../") || 0 > stat(_PATH_TRACE, &stbuf)) #endif ) { msglog("wrong trace file \"%s\"", filename); return; } /* If the new tracefile exists, it must be a regular file. */ if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) { msglog("wrong type (%#x) of trace file \"%s\"", stbuf.st_mode, filename); return; } fn = filename; } if (fn != NULL) { n_ftrace = fopen(fn, "a"); if (n_ftrace == NULL) { msglog("failed to open trace file \"%s\" %s", fn, strerror(errno)); if (fn == inittracename) inittracename[0] = '\0'; return; } tmsg("switch to trace file %s", fn); trace_close(file_trace = 1); if (fn != savetracename) strncpy(savetracename, fn, sizeof(savetracename)-1); ftrace = n_ftrace; fflush(stdout); fflush(stderr); dup2(fileno(ftrace), STDOUT_FILENO); dup2(fileno(ftrace), STDERR_FILENO); } if (new_tracelevel == 0 || filename == NULL) new_tracelevel++; tracelevel_msg(pat, dump != 0 ? dump : (filename != NULL)); }
void set_tracefile(const char *filename, const char *pat, int dump) /* -1=no dump, 0=default, 1=force */ { struct stat stbuf; struct stat stbuf2; FILE *n_ftrace; const char *fn; int nfd; boolean_t allow_create; /* * main() calls this routine with "dump == -1". All others * call it with 0, so we take dump == -1 to mean "can create * the file." */ allow_create = (dump == -1); /* * Allow a null filename to increase the level if the trace file * is already open or if coming from a trusted source, such as * a signal or the command line. */ if (filename == NULL || filename[0] == '\0') { filename = NULL; if (ftrace == NULL) { if (inittracename[0] == '\0') { msglog("missing trace file name"); return; } fn = inittracename; } else { goto set_tracelevel; } } else if (strcmp(filename, "dump/../table") == 0) { trace_dump(); return; } else { /* * Allow the file specified with "-T file" to be reopened, * but require all other names specified over the net to * match the official path. The path can specify a directory * in which the file is to be created. */ if (strcmp(filename, inittracename) != 0) { if (strncmp(filename, PATH_TRACE, sizeof (PATH_TRACE)-1) != 0 || (strstr(filename, "../") != NULL)) { msglog("wrong trace file \"%s\"", filename); return; } if (stat(PATH_TRACE, &stbuf) == -1) { fn = PATH_TRACE; goto missing_file; } if (filename[sizeof (PATH_TRACE) - 1] != '\0' && (filename[sizeof (PATH_TRACE) - 1] != '/' || !S_ISDIR(stbuf.st_mode))) { goto bad_file_type; } if (S_ISDIR(stbuf.st_mode)) allow_create = _B_TRUE; } fn = filename; } /* fn cannot be null here */ /* If the new tracefile exists, it must be a regular file. */ if (lstat(fn, &stbuf) == -1) { if (!allow_create) goto missing_file; nfd = open(fn, O_CREAT|O_EXCL|O_WRONLY, 0644); if (nfd != -1 && fstat(nfd, &stbuf) == -1) { (void) close(nfd); goto missing_file; } } else if (S_ISREG(stbuf.st_mode)) { nfd = open(fn, O_APPEND|O_WRONLY, 0644); } else { goto bad_file_type; } if (nfd == -1 || (n_ftrace = fdopen(nfd, "a")) == NULL) { msglog("failed to open trace file \"%s\" %s", fn, rip_strerror(errno)); if (fn == inittracename) inittracename[0] = '\0'; if (nfd != -1) (void) close(nfd); return; } if (fstat(nfd, &stbuf2) == -1 || !S_ISREG(stbuf2.st_mode) || stbuf2.st_dev != stbuf.st_dev || stbuf2.st_ino != stbuf.st_ino) { msglog("trace file \"%s\" moved", fn); (void) fclose(n_ftrace); return; } tmsg("switch to trace file %s", fn); trace_close(file_trace = _B_TRUE); (void) dup2(nfd, STDOUT_FILENO); (void) dup2(nfd, STDERR_FILENO); if (fn != savetracename) (void) strlcpy(savetracename, fn, sizeof (savetracename) - 1); ftrace = n_ftrace; set_tracelevel: if (new_tracelevel == 0 || filename == NULL) new_tracelevel++; tracelevel_msg(pat, dump != 0 ? dump : (filename != NULL)); return; missing_file: msglog("trace \"%s\" missing", fn); return; bad_file_type: msglog("wrong type (%#x) of trace file \"%s\"", stbuf.st_mode, fn); }