1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * error/logging/cleanup functions for ttymon. 32 */ 33 34 #include <unistd.h> 35 #include <stdlib.h> 36 #include <stdio.h> 37 #include <fcntl.h> 38 #include <string.h> 39 #include <errno.h> 40 #include <stdarg.h> 41 #include <time.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <sys/param.h> 45 #include <signal.h> 46 #include <syslog.h> 47 #include "ttymon.h" 48 #include "tmstruct.h" 49 #include "tmextern.h" 50 51 const char *appname = "ttymon"; 52 53 void 54 openttymonlog(void) 55 { 56 int fd, ret; 57 char logfile[MAXPATHLEN]; 58 59 /* the log file resides in /var/saf/pmtag/ */ 60 (void) snprintf(logfile, sizeof (logfile), "%s%s/%s", LOGDIR, Tag, 61 LOGFILE); 62 63 Logfp = NULL; 64 (void) close(0); 65 if ((fd = open(logfile, O_WRONLY | O_CREAT | O_APPEND, 0444)) != -1) 66 if ((ret = fcntl(fd, F_DUPFD, 3)) == 3) { 67 /* set close-on-exec flag */ 68 if (fcntl(ret, F_SETFD, FD_CLOEXEC) == 0) { 69 Logfp = fdopen(ret, "a+"); 70 } 71 } 72 if (!Logfp) { 73 cons_printf("ttymon cannot create log file \"%s\": %s\n", 74 logfile, strerror(errno)); 75 exit(1); 76 } 77 log(" "); 78 log("********** ttymon starting **********"); 79 80 #ifdef DEBUG 81 log("fd(log)\t = %d", fileno(Logfp)); 82 #endif 83 } 84 85 static void 86 roll_log(void) 87 { 88 char logf[MAXPATHLEN]; 89 char ologf[MAXPATHLEN]; 90 char tlogf[MAXPATHLEN]; 91 FILE *nlogfp; 92 struct stat buf; 93 94 (void) fprintf(Logfp, "Restarting log file\n"); 95 (void) snprintf(logf, sizeof (logf), "%s%s/%s", LOGDIR, Tag, LOGFILE); 96 97 (void) snprintf(ologf, sizeof (ologf), "%s%s/%s", LOGDIR, Tag, 98 OLOGFILE); 99 100 (void) snprintf(tlogf, sizeof (tlogf), "%s%s/%s", LOGDIR, Tag, 101 TLOGFILE); 102 103 if (!stat(ologf, &buf) && rename(ologf, tlogf)) { 104 (void) fprintf(Logfp, "rename old to tmp file failed\n"); 105 } else if (!stat(logf, &buf) && rename(logf, ologf)) { 106 (void) fprintf(Logfp, "rename log to old file failed\n"); 107 /* Restore old log file */ 108 if (!stat(tlogf, &buf) && rename(tlogf, ologf)) 109 (void) fprintf(Logfp, 110 "rename tmp to old file failed\n"); 111 } else if ((nlogfp = fopen(logf, "w")) != NULL) { 112 (void) fclose(Logfp); 113 Logfp = nlogfp; 114 /* reset close-on-exec */ 115 (void) fcntl(fileno(Logfp), F_SETFD, 1); 116 } else { 117 (void) fprintf(Logfp, "log file open failed\n"); 118 /* Restore current and old log file */ 119 if (!stat(ologf, &buf) && rename(ologf, logf)) 120 (void) fprintf(Logfp, 121 "rename old to log file failed\n"); 122 else if (!stat(tlogf, &buf) && rename(tlogf, ologf)) 123 (void) fprintf(Logfp, 124 "rename tmp to old file failed\n"); 125 } 126 127 (void) unlink(tlogf); /* remove any stale tmp logfile */ 128 } 129 130 131 /* 132 * vlog(msg) - common message routine. 133 * - if Logfp is NULL, write message to stderr or CONSOLE 134 */ 135 static void 136 vlog(const char *fmt, va_list ap) 137 { 138 char *timestamp; /* current time in readable form */ 139 time_t clock; /* current time in seconds */ 140 int fd; 141 struct stat buf; 142 143 if (Logfp) { 144 if ((fstat(fileno(Logfp), &buf) != -1) && 145 (buf.st_size >= Logmaxsz) && !Splflag) { 146 Splflag = 1; 147 roll_log(); 148 Splflag = 0; 149 } 150 151 (void) time(&clock); 152 timestamp = ctime(&clock); 153 *(strchr(timestamp, '\n')) = '\0'; 154 (void) fprintf(Logfp, "%s; %ld; ", timestamp, getpid()); 155 (void) vfprintf(Logfp, fmt, ap); 156 if (fmt[strlen(fmt) - 1] != '\n') 157 (void) fputc('\n', Logfp); 158 (void) fflush(Logfp); 159 } else if (isatty(STDERR_FILENO)) { 160 (void) fprintf(stderr, "%s: ", appname); 161 (void) vfprintf(stderr, fmt, ap); 162 if (fmt[strlen(fmt) - 1] != '\n') 163 (void) fputc('\n', stderr); 164 (void) fflush(stderr); 165 } else if ((fd = open(CONSOLE, O_WRONLY|O_NOCTTY)) != -1) { 166 FILE *f = fdopen(fd, "w"); 167 168 (void) fprintf(f, "%s: ", appname); 169 (void) vfprintf(f, fmt, ap); 170 if (fmt[strlen(fmt) - 1] != '\n') 171 (void) fputc('\n', f); 172 (void) fclose(f); 173 } else { 174 vsyslog(LOG_CRIT, fmt, ap); 175 } 176 } 177 178 /* 179 * log(fmt, ...) - put a message into the log file 180 * - if Logfp is NULL, write message to stderr or CONSOLE 181 */ 182 /*PRINTFLIKE1*/ 183 void 184 log(const char *fmt, ...) 185 { 186 va_list ap; 187 va_start(ap, fmt); 188 vlog(fmt, ap); 189 va_end(ap); 190 } 191 192 193 /* 194 * fatal(fmt, ...) - put a message into the log file, then exit. 195 */ 196 /*PRINTFLIKE1*/ 197 void 198 fatal(const char *fmt, ...) 199 { 200 if (fmt) { 201 va_list ap; 202 va_start(ap, fmt); 203 vlog(fmt, ap); 204 va_end(ap); 205 } 206 log("********** ttymon exiting ***********"); 207 exit(1); 208 } 209 210 #ifdef DEBUG 211 212 /* 213 * opendebug - open debugging file, sets global file pointer Debugfp 214 * arg: getty - if TRUE, ttymon is in getty_mode and use a different 215 * debug file 216 */ 217 218 void 219 opendebug(int getty_mode) 220 { 221 int fd, ret; 222 char debugfile[BUFSIZ]; 223 224 if (!getty_mode) { 225 (void) strcpy(debugfile, LOGDIR); 226 (void) strcat(debugfile, Tag); 227 (void) strcat(debugfile, "/"); 228 (void) strcat(debugfile, DBGFILE); 229 if ((Debugfp = fopen(debugfile, "a+")) == NULL) 230 fatal("open debug file failed"); 231 } else { 232 if ((fd = open(EX_DBG, O_WRONLY|O_APPEND|O_CREAT)) < 0) 233 fatal("open %s failed: %s", EX_DBG, errno); 234 235 if (fd >= 3) { 236 ret = fd; 237 } else { 238 if ((ret = fcntl(fd, F_DUPFD, 3)) < 0) 239 fatal("F_DUPFD fcntl failed: %s", 240 strerror(errno)); 241 242 } 243 if ((Debugfp = fdopen(ret, "a+")) == NULL) 244 fatal("fdopen failed: %s", strerror(errno)); 245 246 if (ret != fd) 247 (void) close(fd); 248 } 249 /* set close-on-exec flag */ 250 if (fcntl(fileno(Debugfp), F_SETFD, 1) == -1) 251 fatal("F_SETFD fcntl failed: %s", strerror(errno)); 252 } 253 254 /* 255 * debug(msg) - put a message into debug file 256 */ 257 258 void 259 debug(const char *fmt, ...) 260 { 261 va_list ap; 262 char *timestamp; /* current time in readable form */ 263 time_t clock; /* current time in seconds */ 264 265 (void) time(&clock); 266 timestamp = ctime(&clock); 267 *(strchr(timestamp, '\n')) = '\0'; 268 269 (void) fprintf(Debugfp, "%s; %ld; ", timestamp, getpid()); 270 271 va_start(ap, fmt); 272 (void) vfprintf(Debugfp, fmt, ap); 273 va_end(ap); 274 275 (void) fprintf(Debugfp, "\n"); 276 (void) fflush(Debugfp); 277 } 278 #endif 279