17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5657b1f3dSraf * Common Development and Distribution License (the "License"). 6657b1f3dSraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21657b1f3dSraf 227c478bd9Sstevel@tonic-gate /* 237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 327c478bd9Sstevel@tonic-gate * The Regents of the University of California 337c478bd9Sstevel@tonic-gate * All Rights Reserved 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 367c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 377c478bd9Sstevel@tonic-gate * contributors. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * SYSLOG -- print message on log file 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * This routine looks a lot like printf, except that it 457c478bd9Sstevel@tonic-gate * outputs to the log file instead of the standard output. 467c478bd9Sstevel@tonic-gate * Also: 477c478bd9Sstevel@tonic-gate * adds a timestamp, 487c478bd9Sstevel@tonic-gate * prints the module name in front of the message, 497c478bd9Sstevel@tonic-gate * has some other formatting types (or will sometime), 507c478bd9Sstevel@tonic-gate * adds a newline on the end of the message. 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * The output of this routine is intended to be read by /etc/syslogd. 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate 557257d1b4Sraf #pragma weak _syslog = syslog 567c478bd9Sstevel@tonic-gate 577257d1b4Sraf #include "lint.h" 587c478bd9Sstevel@tonic-gate #include <sys/types.h> 597c478bd9Sstevel@tonic-gate #include <sys/types32.h> 607c478bd9Sstevel@tonic-gate #include <sys/mman.h> 617c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 627c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 637c478bd9Sstevel@tonic-gate #include <sys/log.h> /* for LOG_MAXPS */ 647c478bd9Sstevel@tonic-gate #include <stdlib.h> 657c478bd9Sstevel@tonic-gate #include <procfs.h> 667c478bd9Sstevel@tonic-gate #include <syslog.h> 677c478bd9Sstevel@tonic-gate #include <signal.h> 687c478bd9Sstevel@tonic-gate #include <fcntl.h> 697c478bd9Sstevel@tonic-gate #include <string.h> 707c478bd9Sstevel@tonic-gate #include <stdarg.h> 717c478bd9Sstevel@tonic-gate #include <unistd.h> 727c478bd9Sstevel@tonic-gate #include <wait.h> 737c478bd9Sstevel@tonic-gate #include <stdio.h> 747c478bd9Sstevel@tonic-gate #include <string.h> 757c478bd9Sstevel@tonic-gate #include <errno.h> 767c478bd9Sstevel@tonic-gate #include <thread.h> 777c478bd9Sstevel@tonic-gate #include <synch.h> 787c478bd9Sstevel@tonic-gate #include <sys/door.h> 797c478bd9Sstevel@tonic-gate #include <sys/stat.h> 807c478bd9Sstevel@tonic-gate #include <stropts.h> 81657b1f3dSraf #include <sys/fork.h> 827c478bd9Sstevel@tonic-gate #include <sys/wait.h> 837c478bd9Sstevel@tonic-gate #include "libc.h" 847c478bd9Sstevel@tonic-gate 85*d1a17b3dSArne Jansen #define MAXLINE 8192 /* max message size (but see below) */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #define PRIMASK(p) (1 << ((p) & LOG_PRIMASK)) 887c478bd9Sstevel@tonic-gate #define PRIFAC(p) (((p) & LOG_FACMASK) >> 3) 897c478bd9Sstevel@tonic-gate #define IMPORTANT LOG_ERR 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #ifndef FALSE 927c478bd9Sstevel@tonic-gate #define FALSE 0 937c478bd9Sstevel@tonic-gate #endif 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #ifndef TRUE 967c478bd9Sstevel@tonic-gate #define TRUE 1 977c478bd9Sstevel@tonic-gate #endif 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate #define logname "/dev/conslog" 1007c478bd9Sstevel@tonic-gate #define ctty "/dev/syscon" 1017c478bd9Sstevel@tonic-gate #define sysmsg "/dev/sysmsg" 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate #define DOORFILE "/var/run/syslog_door" 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static struct __syslog { 1067c478bd9Sstevel@tonic-gate int _LogFile; 1077c478bd9Sstevel@tonic-gate int _LogStat; 1087c478bd9Sstevel@tonic-gate const char *_LogTag; 1097c478bd9Sstevel@tonic-gate int _LogMask; 1107c478bd9Sstevel@tonic-gate char *_SyslogHost; 1117c478bd9Sstevel@tonic-gate int _LogFacility; 1127c478bd9Sstevel@tonic-gate int _LogFileInvalid; 1137c478bd9Sstevel@tonic-gate int _OpenLogCalled; 1147c478bd9Sstevel@tonic-gate dev_t _LogDev; 1157c478bd9Sstevel@tonic-gate char _ProcName[PRFNSZ + 1]; 1167c478bd9Sstevel@tonic-gate } __syslog = { 1177c478bd9Sstevel@tonic-gate -1, /* fd for log */ 1187c478bd9Sstevel@tonic-gate 0, /* status bits, set by openlog() */ 1197c478bd9Sstevel@tonic-gate "syslog", /* string to tag the entry with */ 1207c478bd9Sstevel@tonic-gate 0xff, /* mask of priorities to be logged */ 1217c478bd9Sstevel@tonic-gate NULL, 1227c478bd9Sstevel@tonic-gate LOG_USER, /* default facility code */ 1237c478bd9Sstevel@tonic-gate FALSE, /* check for validity of fd for log */ 1247c478bd9Sstevel@tonic-gate 0, /* openlog has not yet been called */ 1257c478bd9Sstevel@tonic-gate }; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate #define LogFile (__syslog._LogFile) 1287c478bd9Sstevel@tonic-gate #define LogStat (__syslog._LogStat) 1297c478bd9Sstevel@tonic-gate #define LogTag (__syslog._LogTag) 1307c478bd9Sstevel@tonic-gate #define LogMask (__syslog._LogMask) 1317c478bd9Sstevel@tonic-gate #define SyslogHost (__syslog._SyslogHost) 1327c478bd9Sstevel@tonic-gate #define LogFacility (__syslog._LogFacility) 1337c478bd9Sstevel@tonic-gate #define LogFileInvalid (__syslog._LogFileInvalid) 1347c478bd9Sstevel@tonic-gate #define OpenLogCalled (__syslog._OpenLogCalled) 1357c478bd9Sstevel@tonic-gate #define LogDev (__syslog._LogDev) 1367c478bd9Sstevel@tonic-gate #define ProcName (__syslog._ProcName) 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate static int syslogd_ok(void); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * Regrettably, there are several instances inside libc where 1427c478bd9Sstevel@tonic-gate * syslog() is called from the bottom of a deep call stack 1437c478bd9Sstevel@tonic-gate * and a critical lock was acquired near the top of the stack. 1447c478bd9Sstevel@tonic-gate * 1457c478bd9Sstevel@tonic-gate * Because syslog() uses stdio (and it is called from within stdio) 1467c478bd9Sstevel@tonic-gate * it runs the danger of deadlocking, perhaps with an interposed 1477c478bd9Sstevel@tonic-gate * malloc() when fork() is occurring concurrently, perhaps with 1487c478bd9Sstevel@tonic-gate * some other lock within libc. 1497c478bd9Sstevel@tonic-gate * 1507c478bd9Sstevel@tonic-gate * The only fix for this problem is to restructure libc not to do 1517c478bd9Sstevel@tonic-gate * this thing and always to call syslog() with no locks held. 1527c478bd9Sstevel@tonic-gate * This restructuring will require a substantial effort. 1537c478bd9Sstevel@tonic-gate * 1547c478bd9Sstevel@tonic-gate * Meanwhile, we just hope that on the rare occasion that syslog() 1557c478bd9Sstevel@tonic-gate * is called from within libc (such occurrences should "never happen") 1567c478bd9Sstevel@tonic-gate * that we don't get caught in a race condition deadlock. 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate void 1597c478bd9Sstevel@tonic-gate syslog(int pri, const char *fmt, ...) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate va_list ap; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1647c478bd9Sstevel@tonic-gate vsyslog(pri, fmt, ap); 1657c478bd9Sstevel@tonic-gate va_end(ap); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate void 1707c478bd9Sstevel@tonic-gate vsyslog(int pri, const char *fmt, va_list ap) 1717c478bd9Sstevel@tonic-gate { 1727c478bd9Sstevel@tonic-gate char *b, *f, *o; 1737c478bd9Sstevel@tonic-gate char c; 1747c478bd9Sstevel@tonic-gate int clen; 1757c478bd9Sstevel@tonic-gate char buf[MAXLINE + 2]; 1767c478bd9Sstevel@tonic-gate char outline[MAXLINE + 256]; /* pad to allow date, system name... */ 177*d1a17b3dSArne Jansen struct timeval now; 1787c478bd9Sstevel@tonic-gate pid_t pid; 1797c478bd9Sstevel@tonic-gate struct log_ctl hdr; 1807c478bd9Sstevel@tonic-gate struct strbuf dat; 1817c478bd9Sstevel@tonic-gate struct strbuf ctl; 1827c478bd9Sstevel@tonic-gate char timestr[26]; /* hardwired value 26 due to Posix */ 1837c478bd9Sstevel@tonic-gate size_t taglen; 1847c478bd9Sstevel@tonic-gate int olderrno = errno; 1857c478bd9Sstevel@tonic-gate struct stat statbuff; 1867c478bd9Sstevel@tonic-gate int procfd; 1877c478bd9Sstevel@tonic-gate char procfile[32]; 1887c478bd9Sstevel@tonic-gate psinfo_t p; 1897c478bd9Sstevel@tonic-gate int showpid; 1907c478bd9Sstevel@tonic-gate uint32_t msgid; 1917c478bd9Sstevel@tonic-gate char *msgid_start, *msgid_end; 192657b1f3dSraf int nowait; 1938f46313cSDavid Hanisch int ret; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Maximum tag length is 256 (the pad in outline) minus the size of the 1977c478bd9Sstevel@tonic-gate * other things that can go in the pad. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate #define MAX_TAG 230 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* see if we should just throw out this message */ 2027c478bd9Sstevel@tonic-gate if (pri < 0 || PRIFAC(pri) >= LOG_NFACILITIES || 2037c478bd9Sstevel@tonic-gate (PRIMASK(pri) & LogMask) == 0) 2047c478bd9Sstevel@tonic-gate return; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (LogFileInvalid) 2077c478bd9Sstevel@tonic-gate return; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * if openlog() has not been called by the application, 2117c478bd9Sstevel@tonic-gate * try to get the name of the application and set it 2127c478bd9Sstevel@tonic-gate * as the ident string for messages. If unable to get 2137c478bd9Sstevel@tonic-gate * it for any reason, fall back to using the default 2147c478bd9Sstevel@tonic-gate * of syslog. If we succeed in getting the name, also 2157c478bd9Sstevel@tonic-gate * turn on LOG_PID, to provide greater detail. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate showpid = 0; 2187c478bd9Sstevel@tonic-gate if (OpenLogCalled == 0) { 2198793b36bSNick Todd (void) sprintf(procfile, "/proc/%d/psinfo", (int)getpid()); 2207c478bd9Sstevel@tonic-gate if ((procfd = open(procfile, O_RDONLY)) >= 0) { 2217c478bd9Sstevel@tonic-gate if (read(procfd, &p, sizeof (psinfo_t)) >= 0) { 2227c478bd9Sstevel@tonic-gate (void) strncpy(ProcName, p.pr_fname, PRFNSZ); 2237c478bd9Sstevel@tonic-gate LogTag = (const char *) &ProcName; 2247c478bd9Sstevel@tonic-gate showpid = LOG_PID; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate (void) close(procfd); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate if (LogFile < 0) 2307c478bd9Sstevel@tonic-gate openlog(LogTag, LogStat|LOG_NDELAY|showpid, 0); 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if ((fstat(LogFile, &statbuff) != 0) || 2337c478bd9Sstevel@tonic-gate (!S_ISCHR(statbuff.st_mode)) || (statbuff.st_rdev != LogDev)) { 2347c478bd9Sstevel@tonic-gate LogFileInvalid = TRUE; 2357c478bd9Sstevel@tonic-gate return; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* set default facility if none specified */ 2397c478bd9Sstevel@tonic-gate if ((pri & LOG_FACMASK) == 0) 2407c478bd9Sstevel@tonic-gate pri |= LogFacility; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* build the header */ 2437c478bd9Sstevel@tonic-gate hdr.pri = pri; 2447c478bd9Sstevel@tonic-gate hdr.flags = SL_CONSOLE; 2457c478bd9Sstevel@tonic-gate hdr.level = 0; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* build the message */ 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * To avoid potential security problems, bounds checking is done 2507c478bd9Sstevel@tonic-gate * on outline and buf. 2517c478bd9Sstevel@tonic-gate * The following code presumes that the header information will 2527c478bd9Sstevel@tonic-gate * fit in 250-odd bytes, as was accounted for in the buffer size 2537c478bd9Sstevel@tonic-gate * allocation. This is dependent on the assumption that the LogTag 2547c478bd9Sstevel@tonic-gate * and the string returned by sprintf() for getpid() will return 2557c478bd9Sstevel@tonic-gate * be less than 230-odd characters combined. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate o = outline; 258*d1a17b3dSArne Jansen (void) gettimeofday(&now, NULL); 259*d1a17b3dSArne Jansen (void) sprintf(o, "%.15s.%03d ", ctime_r(&now.tv_sec, timestr, 26) + 4, 260*d1a17b3dSArne Jansen now.tv_usec / 1000); 2617c478bd9Sstevel@tonic-gate o += strlen(o); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (LogTag) { 2647c478bd9Sstevel@tonic-gate taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG; 2657c478bd9Sstevel@tonic-gate (void) strncpy(o, LogTag, taglen); 2667c478bd9Sstevel@tonic-gate o[taglen] = '\0'; 2677c478bd9Sstevel@tonic-gate o += strlen(o); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate if (LogStat & LOG_PID) { 2708793b36bSNick Todd (void) sprintf(o, "[%d]", (int)getpid()); 2717c478bd9Sstevel@tonic-gate o += strlen(o); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate if (LogTag) { 2747c478bd9Sstevel@tonic-gate (void) strcpy(o, ": "); 2757c478bd9Sstevel@tonic-gate o += 2; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate STRLOG_MAKE_MSGID(fmt, msgid); 2797c478bd9Sstevel@tonic-gate (void) sprintf(o, "[ID %u FACILITY_AND_PRIORITY] ", msgid); 2807c478bd9Sstevel@tonic-gate o += strlen(o); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate b = buf; 2837c478bd9Sstevel@tonic-gate f = (char *)fmt; 2847c478bd9Sstevel@tonic-gate while ((c = *f++) != '\0' && b < &buf[MAXLINE]) { 2857c478bd9Sstevel@tonic-gate char *errmsg; 2867c478bd9Sstevel@tonic-gate if (c != '%') { 2877c478bd9Sstevel@tonic-gate *b++ = c; 2887c478bd9Sstevel@tonic-gate continue; 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate if ((c = *f++) != 'm') { 2917c478bd9Sstevel@tonic-gate *b++ = '%'; 2927c478bd9Sstevel@tonic-gate *b++ = c; 2937c478bd9Sstevel@tonic-gate continue; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate if ((errmsg = strerror(olderrno)) == NULL) 2967c478bd9Sstevel@tonic-gate (void) snprintf(b, &buf[MAXLINE] - b, "error %d", 2977c478bd9Sstevel@tonic-gate olderrno); 2987c478bd9Sstevel@tonic-gate else { 2997c478bd9Sstevel@tonic-gate while (*errmsg != '\0' && b < &buf[MAXLINE]) { 3007c478bd9Sstevel@tonic-gate if (*errmsg == '%') { 3017c478bd9Sstevel@tonic-gate (void) strcpy(b, "%%"); 3027c478bd9Sstevel@tonic-gate b += 2; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate else 3057c478bd9Sstevel@tonic-gate *b++ = *errmsg; 3067c478bd9Sstevel@tonic-gate errmsg++; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate *b = '\0'; 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate b += strlen(b); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate if (b > buf && *(b-1) != '\n') /* ensure at least one newline */ 3137c478bd9Sstevel@tonic-gate *b++ = '\n'; 3147c478bd9Sstevel@tonic-gate *b = '\0'; 3157c478bd9Sstevel@tonic-gate /* LINTED variable format specifier */ 3167c478bd9Sstevel@tonic-gate (void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap); 3177c478bd9Sstevel@tonic-gate clen = (int)strlen(outline) + 1; /* add one for NULL byte */ 3187c478bd9Sstevel@tonic-gate if (clen > MAXLINE) { 3197c478bd9Sstevel@tonic-gate clen = MAXLINE; 3207c478bd9Sstevel@tonic-gate outline[MAXLINE-1] = '\0'; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * 1136432 points out that the underlying log driver actually 3257c478bd9Sstevel@tonic-gate * refuses to accept (ERANGE) messages longer than LOG_MAXPS 3267c478bd9Sstevel@tonic-gate * bytes. So it really doesn't make much sense to putmsg a 3277c478bd9Sstevel@tonic-gate * longer message.. 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate if (clen > LOG_MAXPS) { 3307c478bd9Sstevel@tonic-gate clen = LOG_MAXPS; 3317c478bd9Sstevel@tonic-gate outline[LOG_MAXPS-1] = '\0'; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* set up the strbufs */ 3357c478bd9Sstevel@tonic-gate ctl.maxlen = sizeof (struct log_ctl); 3367c478bd9Sstevel@tonic-gate ctl.len = sizeof (struct log_ctl); 3377c478bd9Sstevel@tonic-gate ctl.buf = (caddr_t)&hdr; 3387c478bd9Sstevel@tonic-gate dat.maxlen = sizeof (outline); 3397c478bd9Sstevel@tonic-gate dat.len = clen; 3407c478bd9Sstevel@tonic-gate dat.buf = outline; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* output the message to the local logger */ 3438f46313cSDavid Hanisch ret = putmsg(LogFile, &ctl, &dat, 0); 3447c478bd9Sstevel@tonic-gate if (!(LogStat & LOG_CONS)) 3457c478bd9Sstevel@tonic-gate return; 3468f46313cSDavid Hanisch if ((ret >= 0) && syslogd_ok()) 3478f46313cSDavid Hanisch return; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * Output the message to the console directly. To reduce visual 3517c478bd9Sstevel@tonic-gate * clutter, we strip out the message ID. 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate if ((msgid_start = strstr(outline, "[ID ")) != NULL && 3547c478bd9Sstevel@tonic-gate (msgid_end = strstr(msgid_start, "] ")) != NULL) 3557c478bd9Sstevel@tonic-gate (void) strcpy(msgid_start, msgid_end + 2); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate clen = strlen(outline) + 1; 3587c478bd9Sstevel@tonic-gate 359657b1f3dSraf nowait = (LogStat & LOG_NOWAIT); 360657b1f3dSraf pid = forkx(nowait? 0 : (FORK_NOSIGCHLD | FORK_WAITPID)); 361657b1f3dSraf if (pid == -1) 3627c478bd9Sstevel@tonic-gate return; 363657b1f3dSraf 3647c478bd9Sstevel@tonic-gate if (pid == 0) { 365657b1f3dSraf sigset_t sigs; 3667c478bd9Sstevel@tonic-gate int fd; 3677c478bd9Sstevel@tonic-gate 368657b1f3dSraf (void) sigset(SIGALRM, SIG_DFL); 369657b1f3dSraf (void) sigemptyset(&sigs); 370657b1f3dSraf (void) sigaddset(&sigs, SIGALRM); 371657b1f3dSraf (void) sigprocmask(SIG_UNBLOCK, &sigs, NULL); 3727c478bd9Sstevel@tonic-gate (void) alarm(5); 3737c478bd9Sstevel@tonic-gate if (((fd = open(sysmsg, O_WRONLY)) >= 0) || 3747c478bd9Sstevel@tonic-gate (fd = open(ctty, O_WRONLY)) >= 0) { 3757c478bd9Sstevel@tonic-gate (void) alarm(0); 3767c478bd9Sstevel@tonic-gate outline[clen - 1] = '\r'; 3777c478bd9Sstevel@tonic-gate (void) write(fd, outline, clen); 3787c478bd9Sstevel@tonic-gate (void) close(fd); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate _exit(0); 3817c478bd9Sstevel@tonic-gate } 382657b1f3dSraf if (!nowait) 383657b1f3dSraf while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) 384657b1f3dSraf continue; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate /* 3887c478bd9Sstevel@tonic-gate * Use a door call to syslogd to see if it's alive. 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate static int 3917c478bd9Sstevel@tonic-gate syslogd_ok(void) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate int d; 3947c478bd9Sstevel@tonic-gate int s; 3957c478bd9Sstevel@tonic-gate door_arg_t darg; 3967c478bd9Sstevel@tonic-gate door_info_t info; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if ((d = open(DOORFILE, O_RDONLY)) < 0) 3997c478bd9Sstevel@tonic-gate return (0); 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * see if our pid matches the pid of the door server. 4027c478bd9Sstevel@tonic-gate * If so, syslogd has called syslog(), probably as 4037c478bd9Sstevel@tonic-gate * a result of some name service library error, and 4047c478bd9Sstevel@tonic-gate * we don't want to let syslog continue and possibly 4057c478bd9Sstevel@tonic-gate * fork here. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate info.di_target = 0; 4087c478bd9Sstevel@tonic-gate if (__door_info(d, &info) < 0 || info.di_target == getpid()) { 4097c478bd9Sstevel@tonic-gate (void) close(d); 4107c478bd9Sstevel@tonic-gate return (0); 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate darg.data_ptr = NULL; 4137c478bd9Sstevel@tonic-gate darg.data_size = 0; 4147c478bd9Sstevel@tonic-gate darg.desc_ptr = NULL; 4157c478bd9Sstevel@tonic-gate darg.desc_num = 0; 4167c478bd9Sstevel@tonic-gate darg.rbuf = NULL; 4177c478bd9Sstevel@tonic-gate darg.rsize = 0; 4187c478bd9Sstevel@tonic-gate s = __door_call(d, &darg); 4197c478bd9Sstevel@tonic-gate (void) close(d); 4207c478bd9Sstevel@tonic-gate if (s < 0) 4217c478bd9Sstevel@tonic-gate return (0); /* failure - syslogd dead */ 4227c478bd9Sstevel@tonic-gate else 4237c478bd9Sstevel@tonic-gate return (1); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * OPENLOG -- open system log 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate void 4317c478bd9Sstevel@tonic-gate openlog(const char *ident, int logstat, int logfac) 4327c478bd9Sstevel@tonic-gate { 4337c478bd9Sstevel@tonic-gate struct stat statbuff; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate OpenLogCalled = 1; 4367c478bd9Sstevel@tonic-gate if (ident != NULL) 4377c478bd9Sstevel@tonic-gate LogTag = ident; 4387c478bd9Sstevel@tonic-gate LogStat = logstat; 4397c478bd9Sstevel@tonic-gate if (logfac != 0) 4407c478bd9Sstevel@tonic-gate LogFacility = logfac & LOG_FACMASK; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * if the fstat(2) fails or the st_rdev has changed 4447c478bd9Sstevel@tonic-gate * then we must open the file 4457c478bd9Sstevel@tonic-gate */ 4467c478bd9Sstevel@tonic-gate if ((fstat(LogFile, &statbuff) == 0) && 4477c478bd9Sstevel@tonic-gate (S_ISCHR(statbuff.st_mode)) && (statbuff.st_rdev == LogDev)) 4487c478bd9Sstevel@tonic-gate return; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (LogStat & LOG_NDELAY) { 4517c478bd9Sstevel@tonic-gate LogFile = open(logname, O_WRONLY); 4527c478bd9Sstevel@tonic-gate (void) fcntl(LogFile, F_SETFD, 1); 4537c478bd9Sstevel@tonic-gate (void) fstat(LogFile, &statbuff); 4547c478bd9Sstevel@tonic-gate LogDev = statbuff.st_rdev; 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate /* 4597c478bd9Sstevel@tonic-gate * CLOSELOG -- close the system log 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate void 4637c478bd9Sstevel@tonic-gate closelog(void) 4647c478bd9Sstevel@tonic-gate { 4657c478bd9Sstevel@tonic-gate struct stat statbuff; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate OpenLogCalled = 0; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* if the LogFile is invalid it can not be closed */ 4707c478bd9Sstevel@tonic-gate if (LogFileInvalid) 4717c478bd9Sstevel@tonic-gate return; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * if the fstat(2) fails or the st_rdev has changed 4757c478bd9Sstevel@tonic-gate * then we can not close the file 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate if ((fstat(LogFile, &statbuff) == 0) && (statbuff.st_rdev == LogDev)) { 4787c478bd9Sstevel@tonic-gate (void) close(LogFile); 4797c478bd9Sstevel@tonic-gate LogFile = -1; 4807c478bd9Sstevel@tonic-gate LogStat = 0; 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * SETLOGMASK -- set the log mask level 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate int 4887c478bd9Sstevel@tonic-gate setlogmask(int pmask) 4897c478bd9Sstevel@tonic-gate { 4907c478bd9Sstevel@tonic-gate int omask = 0; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate omask = LogMask; 4937c478bd9Sstevel@tonic-gate if (pmask != 0) 4947c478bd9Sstevel@tonic-gate LogMask = pmask; 4957c478bd9Sstevel@tonic-gate return (omask); 4967c478bd9Sstevel@tonic-gate } 497