xref: /illumos-gate/usr/src/cmd/listen/lslog.c (revision 2a8bcb4e)
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 /*
24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
31 /*
32  * error/logging/cleanup functions for the network listener process.
33  */
34 
35 
36 /* system include files	*/
37 
38 #include <fcntl.h>
39 #include <signal.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <tiuser.h>
44 #include <sys/utsname.h>
45 #include <sys/param.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/ipc.h>
49 #include <values.h>
50 #include <ctype.h>
51 #include <time.h>
52 
53 /* listener include files */
54 
55 #include "lsparam.h"		/* listener parameters		*/
56 #include "listen.h"		/* listener */
57 #include "lsfiles.h"		/* listener files info		*/
58 #include "lserror.h"		/* listener error codes		*/
59 #include "lsdbf.h"
60 
61 extern char Lastmsg[];
62 extern int NLPS_proc;
63 extern char *Netspec;
64 extern FILE *Logfp;
65 extern FILE *Debugfp;
66 extern char Mytag[];
67 
68 static char *stamp(char *);
69 void logmessage(char *s);
70 void clean_up(int code, int flag, char *msg);
71 
72 /*
73  * error handling and debug routines
74  * most routines take two args: code and exit.
75  * code is a #define in lserror.h.
76  * if EXIT bit in exitflag is non-zero, the routine exits. (see clean_up() )
77  * define COREDUMP to do the obvious.
78  */
79 
80 
81 /*
82  * error: catastrophic error handler
83  */
84 
85 void
error(int code,int exitflag)86 error(int code, int exitflag)
87 {
88 	char scratch[BUFSIZ];
89 
90 	if (!(exitflag & NO_MSG)) {
91 		strcpy(scratch, err_list[code].err_msg);
92 		clean_up(code, exitflag, scratch);
93 	}
94 	clean_up(code, exitflag, NULL);
95 }
96 
97 /*
98  * tli_error:  Deal (appropriately) with an error in a TLI call
99  */
100 
101 static char *tlirange = "Unknown TLI error (t_errno > t_nerr)";
102 
103 void
tli_error(int code,int exitflag)104 tli_error(int code, int exitflag)
105 {
106 	void	t_error();
107 	char	scratch[256];
108 	const char *p;
109 	int	save_errno = errno;
110 
111 	p = (t_errno < t_nerr ? t_errlist[t_errno] : tlirange);
112 
113 	(void) snprintf(scratch, sizeof (scratch), "%s: %s",
114 	    err_list[code].err_msg, p);
115 	if (t_errno == TSYSERR)  {
116 		(void) strlcat(scratch, ": ", sizeof (scratch));
117 		(void) strlcat(scratch, strerror(save_errno), sizeof (scratch));
118 	}
119 	clean_up(code, exitflag, scratch);
120 }
121 
122 
123 /*
124  * sys_error: error in a system call
125  */
126 
127 void
sys_error(int code,int exitflag)128 sys_error(int code, int exitflag)
129 {
130 	char scratch[256];
131 
132 	(void) snprintf(scratch, sizeof (scratch), "%s: %s",
133 	    err_list[code].err_msg, strerror(errno));
134 	clean_up(code, exitflag, scratch);
135 }
136 
137 
138 /*
139  * clean_up:	if 'flag', and main listener is exiting, clean things
140  *		up and exit.  Dumps core if !(flag & NOCORE).
141  *		Tries to send a message to someone if the listener
142  *		is exiting due to an error. (Inherrently machine dependent.)
143  */
144 
145 void
clean_up(int code,int flag,char * msg)146 clean_up(int code, int flag, char *msg)
147 {
148 	extern int Dbf_entries;
149 	extern void logexit();
150 	extern int NLPS_proc, Nflag;
151 	int i;
152 	extern dbf_t Dbfhead;
153 	dbf_t	*dbp = &Dbfhead;
154 
155 	if (!(flag & EXIT)) {
156 		logmessage(msg);
157 		return;
158 	}
159 
160 	if (!(NLPS_proc))  {
161 
162 		/*
163 		 * unbind anything that we bound.
164 		 * Needs more intelligence.
165 		 */
166 
167 
168 		for (i=0;i<Dbf_entries;i++) {
169 			t_unbind(dbp->dbf_fd);
170 			dbp++;
171 		}
172 	}
173 
174 #ifdef	COREDUMP
175 	if (!(flag & NOCORE))
176 		abort();
177 #endif	/* COREDUMP */
178 
179 	logexit(err_list[code].err_code, msg);
180 }
181 
182 
183 void
logexit(exitcode,msg)184 logexit(exitcode, msg)
185 int exitcode;
186 char *msg;
187 {
188 	if (msg) {
189 		logmessage(msg); /* put it in the log */
190 	}
191 	if (!NLPS_proc)
192 		logmessage("*** listener terminating!!! ***");
193 	exit(exitcode);
194 
195 }
196 
197 
198 #ifdef	DEBUGMODE
199 
200 /*VARARGS2*/
201 int
debug(int level,char * format,...)202 debug(int level, char *format, ...)
203 {
204 	char buf[256];
205 	va_list ap;
206 
207 	va_start(ap, format);
208 	(void) vsprintf(buf, format, ap);
209 	va_end(ap);
210 
211 	fprintf(Debugfp, stamp(buf));
212 	fflush(Debugfp);
213 }
214 
215 #endif
216 
217 
218 
219 /*
220  * log:		given a message number (code), write a message to the logfile
221  * logmessage:	given a string, write a message to the logfile
222  */
223 
224 void
log(int code)225 log(int code)
226 {
227 	logmessage(err_list[code].err_msg);
228 }
229 
230 
231 static int nlogs;		/* maintains size of logfile	*/
232 
233 void
logmessage(char * s)234 logmessage(char *s)
235 {
236 	char log[BUFSIZ];
237 	char olog[BUFSIZ];
238 	int err = 0;
239 	FILE *nlogfp;
240 	extern int Logmax;
241 	extern int Splflag;
242 
243 	/*
244 	 * The listener may be maintaining the size of it's logfile.
245 	 * Nothing in here should make the listener abort.
246 	 * If it can't save the file, it rewinds the existing log.
247 	 * Note that the algorithm is not exact, child listener's
248 	 * messages do not affect the parent's count.
249 	 */
250 
251 	if (!Logfp)
252 		return;
253 	if (!NLPS_proc && Logmax && ( nlogs >= Logmax ) && !Splflag)  {
254 		nlogs = 0;
255 		fprintf(Logfp, stamp("Restarting log file"));
256 		sprintf(log, "%s/%s/%s", ALTDIR, Mytag, LOGNAME);
257 		sprintf(olog, "%s/%s/%s", ALTDIR, Mytag, OLOGNAME);
258 		DEBUG((1, "Logfile exceeds Logmax (%d) lines", Logmax));
259 		unlink(olog); /* remove stale saved logfile */
260 		if (rename(log, olog))  {
261 			++err;
262 			rewind(Logfp);
263 			DEBUG((1,"errno %d renaming log to old logfile",errno));
264 		}
265 		else  if (nlogfp = fopen(log, "a+"))  {
266 			fclose(Logfp);
267 			Logfp = nlogfp;
268 			fcntl(fileno(Logfp), F_SETFD, 1); /* reset close-on-exec */
269 			DEBUG((1, "logmessage: logfile saved successfully"));
270 		}  else  {
271 			++err;
272 			rewind(Logfp);
273 			DEBUG((1, "Lost the logfile, errno %d", errno));
274 		}
275 		if (err)
276 			fprintf(Logfp, stamp("Trouble saving the logfile"));
277 	}
278 
279 	fprintf(Logfp, stamp(s));
280 	fflush(Logfp);
281 	++nlogs;
282 }
283 
284 extern pid_t Pid;
285 
286 static char *
stamp(char * msg)287 stamp(char *msg)
288 {
289 	time_t clock;
290 	struct tm *tm_p;
291 
292 	(void)time(&clock);
293 	tm_p = (struct tm *) localtime(&clock);
294 	tm_p->tm_mon++;	/* since months are 0-11 */
295 	sprintf(Lastmsg, "%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d; %ld; %s\n",
296 		tm_p->tm_mon, tm_p->tm_mday, (tm_p->tm_year % 100),
297 		tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec, Pid, msg);
298 	return(Lastmsg);
299 }
300