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 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * error/logging/cleanup functions for ttymon. 35 */ 36 37 #include <unistd.h> 38 #include <stdlib.h> 39 #include <stdio.h> 40 #include <fcntl.h> 41 #include <string.h> 42 #include <errno.h> 43 #include <stdarg.h> 44 #include <time.h> 45 #include <sys/types.h> 46 #include <sys/stat.h> 47 #include <sys/param.h> 48 #include <signal.h> 49 #include <syslog.h> 50 #include "ttymon.h" 51 #include "tmstruct.h" 52 #include "tmextern.h" 53 54 # ifdef DEBUG 55 extern FILE *Debugfp; 56 # endif 57 58 const char *appname = "ttymon"; 59 60 void 61 openttymonlog(void) 62 { 63 int fd, ret; 64 char logfile[MAXPATHLEN]; 65 extern char *Tag; 66 67 /* the log file resides in /var/saf/pmtag/ */ 68 (void) snprintf(logfile, sizeof (logfile), "%s%s/%s", LOGDIR, Tag, 69 LOGFILE); 70 71 Logfp = NULL; 72 (void)close(0); 73 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND,0444)) != -1) 74 if ((ret = fcntl(fd, F_DUPFD, 3)) == 3) { 75 /* set close-on-exec flag */ 76 if (fcntl(ret, F_SETFD, FD_CLOEXEC) == 0) { 77 Logfp = fdopen(ret, "a+"); 78 } 79 } 80 if (!Logfp) { 81 cons_printf("ttymon cannot create log file \"%s\": %s\n", 82 logfile, strerror(errno)); 83 exit(1); 84 } 85 log(" "); 86 log("********** ttymon starting **********"); 87 88 #ifdef DEBUG 89 log("fd(log)\t = %d", fileno(Logfp)); 90 #endif 91 } 92 93 static void 94 roll_log() 95 { 96 char logf[MAXPATHLEN]; 97 char ologf[MAXPATHLEN]; 98 char tlogf[MAXPATHLEN]; 99 FILE *nlogfp; 100 struct stat buf; 101 102 (void) fprintf(Logfp, "Restarting log file\n"); 103 (void) snprintf(logf, sizeof (logf), "%s%s/%s", LOGDIR, Tag, LOGFILE); 104 105 (void) snprintf(ologf, sizeof (ologf), "%s%s/%s", LOGDIR, Tag, 106 OLOGFILE); 107 108 (void) snprintf(tlogf, sizeof (tlogf), "%s%s/%s", LOGDIR, Tag, 109 TLOGFILE); 110 111 if (!stat(ologf, &buf) && rename(ologf, tlogf)) { 112 (void) fprintf(Logfp, "rename old to tmp file failed\n"); 113 } else if (!stat(logf, &buf) && rename(logf, ologf)) { 114 (void) fprintf(Logfp, "rename log to old file failed\n"); 115 /* Restore old log file */ 116 if (!stat(tlogf, &buf) && rename(tlogf, ologf)) 117 (void) fprintf(Logfp, 118 "rename tmp to old file failed\n"); 119 } else if (nlogfp = fopen(logf, "w")) { 120 (void) fclose(Logfp); 121 Logfp = nlogfp; 122 /* reset close-on-exec */ 123 (void) fcntl(fileno(Logfp), F_SETFD, 1); 124 } else { 125 (void) fprintf(Logfp, "log file open failed\n"); 126 /* Restore current and old log file */ 127 if (!stat(ologf, &buf) && rename(ologf, logf)) 128 (void) fprintf(Logfp, 129 "rename old to log file failed\n"); 130 else if (!stat(tlogf, &buf) && rename(tlogf, ologf)) 131 (void) fprintf(Logfp, 132 "rename tmp to old file failed\n"); 133 } 134 135 (void) unlink(tlogf); /* remove any stale tmp logfile */ 136 } 137 138 139 /* 140 * vlog(msg) - common message routine. 141 * - if Logfp is NULL, write message to stderr or CONSOLE 142 */ 143 static void 144 vlog(const char *fmt, va_list ap) 145 { 146 char *timestamp; /* current time in readable form */ 147 time_t clock; /* current time in seconds */ 148 int fd; 149 struct stat buf; 150 151 if (Logfp) { 152 if ((fstat(fileno(Logfp), &buf) != -1) && 153 (buf.st_size >= Logmaxsz) && !Splflag) { 154 Splflag = 1; 155 roll_log(); 156 Splflag = 0; 157 } 158 159 (void) time(&clock); 160 timestamp = ctime(&clock); 161 *(strchr(timestamp, '\n')) = '\0'; 162 (void) fprintf(Logfp, "%s; %ld; ", timestamp, getpid()); 163 (void) vfprintf(Logfp, fmt, ap); 164 if (fmt[strlen(fmt) - 1] != '\n') 165 (void) fputc('\n', Logfp); 166 (void) fflush(Logfp); 167 } else if (isatty(STDERR_FILENO)) { 168 (void) fprintf(stderr, "%s: ", appname); 169 (void) vfprintf(stderr, fmt, ap); 170 if (fmt[strlen(fmt) - 1] != '\n') 171 (void) fputc('\n', stderr); 172 (void) fflush(stderr); 173 } else if ((fd = open(CONSOLE, O_WRONLY|O_NOCTTY)) != -1) { 174 FILE *f = fdopen(fd, "w"); 175 176 (void) fprintf(f, "%s: ", appname); 177 (void) vfprintf(f, fmt, ap); 178 if (fmt[strlen(fmt) - 1] != '\n') 179 (void) fputc('\n', f); 180 (void) fclose(f); 181 } else { 182 vsyslog(LOG_CRIT, fmt, ap); 183 } 184 } 185 186 /* 187 * log(fmt, ...) - put a message into the log file 188 * - if Logfp is NULL, write message to stderr or CONSOLE 189 */ 190 /*PRINTFLIKE1*/ 191 void 192 log(const char *fmt, ...) 193 { 194 va_list ap; 195 va_start(ap, fmt); 196 vlog(fmt, ap); 197 va_end(ap); 198 } 199 200 201 /* 202 * fatal(fmt, ...) - put a message into the log file, then exit. 203 */ 204 /*PRINTFLIKE1*/ 205 void 206 fatal(const char *fmt, ...) 207 { 208 if (fmt) { 209 va_list ap; 210 va_start(ap, fmt); 211 vlog(fmt, ap); 212 va_end(ap); 213 } 214 log("********** ttymon exiting ***********"); 215 exit(1); 216 } 217 218 # ifdef DEBUG 219 220 /* 221 * opendebug - open debugging file, sets global file pointer Debugfp 222 * arg: getty - if TRUE, ttymon is in getty_mode and use a different 223 * debug file 224 */ 225 226 void 227 opendebug(int getty_mode) 228 { 229 int fd, ret; 230 char debugfile[BUFSIZ]; 231 extern char *Tag; 232 233 if (!getty_mode) { 234 (void)strcpy(debugfile, LOGDIR); 235 (void)strcat(debugfile, Tag); 236 (void)strcat(debugfile, "/"); 237 (void)strcat(debugfile, DBGFILE); 238 if ((Debugfp = fopen(debugfile, "a+")) == NULL) 239 fatal("open debug file failed"); 240 } 241 else { 242 if ((fd = open(EX_DBG, O_WRONLY|O_APPEND|O_CREAT)) < 0) 243 fatal("open %s failed: %s", EX_DBG, errno); 244 245 if (fd >= 3) 246 ret = fd; 247 else { 248 if ((ret = fcntl(fd, F_DUPFD, 3)) < 0) 249 fatal("F_DUPFD fcntl failed: %s", 250 strerror(errno)); 251 252 } 253 if ((Debugfp = fdopen(ret, "a+")) == NULL) 254 fatal("fdopen failed: %s", strerror(errno)); 255 256 if (ret != fd) 257 (void)close(fd); 258 } 259 /* set close-on-exec flag */ 260 if (fcntl(fileno(Debugfp), F_SETFD, 1) == -1) 261 fatal("F_SETFD fcntl failed: %s", strerror(errno)); 262 } 263 264 /* 265 * debug(msg) - put a message into debug file 266 */ 267 268 void 269 debug(const char *fmt, ...) 270 { 271 va_list ap; 272 char *timestamp; /* current time in readable form */ 273 time_t clock; /* current time in seconds */ 274 275 (void) time(&clock); 276 timestamp = ctime(&clock); 277 *(strchr(timestamp, '\n')) = '\0'; 278 279 (void) fprintf(Debugfp, "%s; %ld; ", timestamp, getpid()); 280 281 va_start(ap, fmt); 282 (void) vfprintf(Debugfp, fmt, ap); 283 va_end(ap); 284 285 (void) fprintf(Debugfp, "\n"); 286 (void) fflush(Debugfp); 287 } 288 #endif 289