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