xref: /illumos-gate/usr/src/cmd/ttymon/tmlog.c (revision dd72704bd9e794056c558153663c739e2012d721)
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