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 63 extern char Lastmsg[]; 64 extern int NLPS_proc; 65 extern char *Netspec; 66 extern FILE *Logfp; 67 extern FILE *Debugfp; 68 extern char Mytag[]; 69 70 static char *stamp(char *); 71 void logmessage(char *s); 72 void 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 87 void 88 error(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 103 static char *tlirange = "Unknown TLI error (t_errno > t_nerr)"; 104 105 void 106 tli_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 129 void 130 sys_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 147 void 148 clean_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 185 void 186 logexit(exitcode, msg) 187 int exitcode; 188 char *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*/ 203 int 204 debug(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 226 void 227 log(int code) 228 { 229 logmessage(err_list[code].err_msg); 230 } 231 232 233 static int nlogs; /* maintains size of logfile */ 234 235 void 236 logmessage(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 286 extern pid_t Pid; 287 288 static char * 289 stamp(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