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