11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* $OpenBSD: syslog.c,v 1.28 2005/08/08 08:05:34 espie Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1983, 1988, 1993 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The Regents of the University of California. All rights reserved. 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * documentation and/or other materials provided with the distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * may be used to endorse or promote products derived from this software 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * without specific prior written permission. 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h> 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h> 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/uio.h> 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <syslog.h> 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/un.h> 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netdb.h> 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <fcntl.h> 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <paths.h> 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <time.h> 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unistd.h> 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdarg.h> 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct syslog_data sdata = SYSLOG_DATA_INIT; 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectextern char *__progname; /* Program name, from crt0. */ 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void disconnectlog_r(struct syslog_data *); /* disconnect from syslogd */ 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void connectlog_r(struct syslog_data *); /* (re)connect to syslogd */ 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * syslog, vsyslog -- 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * print message on log file; output is intended for syslogd(8). 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsyslog(int pri, const char *fmt, ...) 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project va_list ap; 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project va_start(ap, fmt); 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project vsyslog(pri, fmt, ap); 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project va_end(ap); 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvsyslog(int pri, const char *fmt, va_list ap) 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project vsyslog_r(pri, &sdata, fmt, ap); 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectopenlog(const char *ident, int logstat, int logfac) 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project openlog_r(ident, logstat, logfac, &sdata); 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcloselog(void) 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project closelog_r(&sdata); 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* setlogmask -- set the log mask level */ 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsetlogmask(int pmask) 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return setlogmask_r(pmask, &sdata); 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Reentrant version of syslog, i.e. syslog_r() */ 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsyslog_r(int pri, struct syslog_data *data, const char *fmt, ...) 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project va_list ap; 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project va_start(ap, fmt); 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project vsyslog_r(pri, data, fmt, ap); 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project va_end(ap); 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap) 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int cnt; 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char ch, *p, *t; 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time_t now; 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int fd, saved_errno, error; 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TBUF_LEN 2048 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define FMT_LEN 1024 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *stdp = NULL, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN]; 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int tbuf_left, fmt_left, prlen; 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Check for invalid bits. */ 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) { 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data == &sdata) { 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project syslog(INTERNALLOG, 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "syslog: unknown facility/priority: %x", pri); 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project syslog_r(INTERNALLOG, data, 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "syslog_r: unknown facility/priority: %x", pri); 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pri &= LOG_PRIMASK|LOG_FACMASK; 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Check priority against setlogmask values. */ 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(LOG_MASK(LOG_PRI(pri)) & data->log_mask)) 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return; 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project saved_errno = errno; 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Set default facility if none specified. */ 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pri & LOG_FACMASK) == 0) 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pri |= data->log_fac; 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* If we have been called through syslog(), no need for reentrancy. */ 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data == &sdata) 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)time(&now); 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p = tbuf; 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tbuf_left = TBUF_LEN; 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DEC() \ 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { \ 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (prlen < 0) \ 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = 0; \ 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (prlen >= tbuf_left) \ 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = tbuf_left - 1; \ 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p += prlen; \ 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tbuf_left -= prlen; \ 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (0) 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = snprintf(p, tbuf_left, "<%d>", pri); 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project DEC(); 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * syslogd will expand time automagically for reentrant case, and 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * for normal case, just do like before 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data == &sdata) { 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now)); 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project DEC(); 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_stat & LOG_PERROR) 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project stdp = p; 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_tag == NULL) 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_tag = __progname; 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_tag != NULL) { 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = snprintf(p, tbuf_left, "%s", data->log_tag); 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project DEC(); 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_stat & LOG_PID) { 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = snprintf(p, tbuf_left, "[%ld]", (long)getpid()); 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project DEC(); 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_tag != NULL) { 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (tbuf_left > 1) { 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *p++ = ':'; 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tbuf_left--; 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (tbuf_left > 1) { 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *p++ = ' '; 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tbuf_left--; 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* strerror() is not reentrant */ 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) { 1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ch == '%' && fmt[1] == 'm') { 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ++fmt; 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data == &sdata) { 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = snprintf(t, fmt_left, "%s", 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strerror(saved_errno)); 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = snprintf(t, fmt_left, "Error %d", 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project saved_errno); 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (prlen < 0) 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = 0; 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (prlen >= fmt_left) 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = fmt_left - 1; 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t += prlen; 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fmt_left -= prlen; 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (ch == '%' && fmt[1] == '%' && fmt_left > 2) { 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *t++ = '%'; 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *t++ = '%'; 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fmt++; 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fmt_left -= 2; 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (fmt_left > 1) { 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *t++ = ch; 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fmt_left--; 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *t = '\0'; 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prlen = vsnprintf(p, tbuf_left, fmt_cpy, ap); 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project DEC(); 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cnt = p - tbuf; 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Output to stderr if requested. */ 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_stat & LOG_PERROR) { 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct iovec iov[2]; 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[0].iov_base = stdp; 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[0].iov_len = cnt - (stdp - tbuf); 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[1].iov_base = "\n"; 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[1].iov_len = 1; 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)writev(STDERR_FILENO, iov, 2); 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Get connected, output the message to the local logger. */ 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!data->opened) 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project openlog_r(data->log_tag, data->log_stat, 0, data); 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project connectlog_r(data); 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If the send() failed, there are two likely scenarios: 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1) syslogd was restarted 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2) /dev/log is out of socket buffer space 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We attempt to reconnect to /dev/log to take care of 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * case #1 and keep send()ing data to cover case #2 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * to give syslogd a chance to empty its socket buffer. 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((error = send(data->log_file, tbuf, cnt, 0)) < 0) { 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno != ENOBUFS) { 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project disconnectlog_r(data); 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project connectlog_r(data); 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project usleep(1); 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((error = send(data->log_file, tbuf, cnt, 0)) >= 0) 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (errno == ENOBUFS); 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Output the message to the console; try not to block 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * as a blocking console should not stop other processes. 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Make sure the error reported is the one from the syslogd failure. 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error == -1 && (data->log_stat & LOG_CONS) && 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (fd = open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) { 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct iovec iov[2]; 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p = strchr(tbuf, '>') + 1; 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[0].iov_base = p; 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[0].iov_len = cnt - (p - tbuf); 2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[1].iov_base = "\r\n"; 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project iov[1].iov_len = 2; 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)writev(fd, iov, 2); 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)close(fd); 2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data != &sdata) 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project closelog_r(data); 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdisconnectlog_r(struct syslog_data *data) 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If the user closed the FD and opened another in the same slot, 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * that's their problem. They should close it before calling on 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * system services. 2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_file != -1) { 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project close(data->log_file); 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_file = -1; 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->connected = 0; /* retry connect */ 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconnectlog_r(struct syslog_data *data) 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project union { 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct sockaddr syslogAddr; 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct sockaddr_un syslogAddrUn; 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } u; 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define SyslogAddr u.syslogAddrUn 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_file == -1) { 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((data->log_file = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return; 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)fcntl(data->log_file, F_SETFD, 1); 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_file != -1 && !data->connected) { 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&SyslogAddr, '\0', sizeof(SyslogAddr)); 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* BIONIC: no sun_len field to fill on Linux */ 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project SyslogAddr.sun_len = sizeof(SyslogAddr); 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project SyslogAddr.sun_family = AF_UNIX; 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(SyslogAddr.sun_path, _PATH_LOG, 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sizeof(SyslogAddr.sun_path)); 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (connect(data->log_file, &u.syslogAddr, 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sizeof(SyslogAddr)) == -1) { 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)close(data->log_file); 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_file = -1; 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->connected = 1; 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectopenlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data) 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ident != NULL) 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_tag = ident; 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_stat = logstat; 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_fac = logfac; 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (data->log_stat & LOG_NDELAY) /* open immediately */ 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project connectlog_r(data); 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->opened = 1; /* ident and facility has been set */ 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcloselog_r(struct syslog_data *data) 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)close(data->log_file); 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_file = -1; 3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->connected = 0; 3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_tag = NULL; 3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* setlogmask -- set the log mask level */ 3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsetlogmask_r(int pmask, struct syslog_data *data) 3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int omask; 3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project omask = data->log_mask; 3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pmask != 0) 3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project data->log_mask = pmask; 3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (omask); 3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 369