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