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
openttymonlog(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
roll_log()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
vlog(const char * fmt,va_list ap)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
log(const char * fmt,...)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
fatal(const char * fmt,...)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
opendebug(int getty_mode)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
debug(const char * fmt,...)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