blob: 5ef622dc31e593a0f09492d1b3c4d48190e92d54 [file] [log] [blame]
Eric Andersen3843e961999-11-25 07:30:46 +00001/*
2 * Mini logger implementation for busybox
3 *
4 * Copyright (C) 1999 by Lineo, inc.
5 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include "internal.h"
24#include <stdio.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <unistd.h>
28#include <time.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <signal.h>
33#include <ctype.h>
34#include <netdb.h>
35
36#if !defined BB_SYSLOGD
37
38#define SYSLOG_NAMES
39#include <sys/syslog.h>
40
41#else
42/* We have to do this since the header file defines static
43 * structues. Argh.... bad libc, bad, bad...
44 */
45#include <sys/syslog.h>
46typedef struct _code {
47 char *c_name;
48 int c_val;
49} CODE;
50extern CODE prioritynames[];
51extern CODE facilitynames[];
52#endif
53
54static const char logger_usage[] =
55 "logger [OPTION]... [MESSAGE]\n\n"
56 "Write MESSAGE to the system log. If MESSAGE is '-', log stdin.\n\n"
57 "Options:\n"
58 "\t-s\tLog to stderr as well as the system log.\n"
59 "\t-p\tEnter the message with the specified priority.\n"
60 "\t\tThis may be numerical or a ``facility.level'' pair.\n";
61
62
63/* Decode a symbolic name to a numeric value
64 * this function is based on code
65 * Copyright (c) 1983, 1993
66 * The Regents of the University of California. All rights reserved.
67 */
68static int
69decode(char* name, CODE* codetab)
70{
71 CODE *c;
72
73 if (isdigit(*name))
74 return (atoi(name));
75 for (c = codetab; c->c_name; c++) {
76 if (!strcasecmp(name, c->c_name)) {
77 return (c->c_val);
78 }
79 }
80
81 return (-1);
82}
83
84/* Decode a symbolic name to a numeric value
85 * this function is based on code
86 * Copyright (c) 1983, 1993
87 * The Regents of the University of California. All rights reserved.
88 */
89static int
90pencode(char* s)
91{
92 char *save;
93 int lev, fac=LOG_USER;
94
95 for (save = s; *s && *s != '.'; ++s);
96 if (*s) {
97 *s = '\0';
98 fac = decode(save, facilitynames);
99 if (fac < 0) {
100 fprintf(stderr, "unknown facility name: %s\n", save);
101 exit( FALSE);
102 }
103 *s++ = '.';
104 }
105 else {
106 s = save;
107 }
108 lev = decode(s, prioritynames);
109 if (lev < 0) {
110 fprintf(stderr, "unknown priority name: %s\n", save);
111 exit( FALSE);
112 }
113 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
114}
115
116
117extern int logger_main(int argc, char **argv)
118{
119 struct sockaddr_un sunx;
120 int fd, pri = LOG_USER|LOG_NOTICE;
Eric Andersenbefda6e1999-11-25 08:06:22 +0000121 int fromStdinFlag=FALSE;
Eric Andersen3843e961999-11-25 07:30:46 +0000122 int toStdErrFlag=FALSE;
Erik Andersen1c5b2581999-12-16 20:59:36 +0000123 int stopLookingAtMeLikeThat=FALSE;
Eric Andersenbefda6e1999-11-25 08:06:22 +0000124 char *message, buf[1024], buf1[1024];
Eric Andersen3843e961999-11-25 07:30:46 +0000125 time_t now;
126 size_t addrLength;
127
128 /* Parse any options */
129 while (--argc > 0 && **(++argv) == '-') {
Eric Andersenbefda6e1999-11-25 08:06:22 +0000130 if (*((*argv)+1) == '\0') {
131 fromStdinFlag=TRUE;
132 }
Erik Andersen1c5b2581999-12-16 20:59:36 +0000133 stopLookingAtMeLikeThat=FALSE;
134 while (*(++(*argv)) && stopLookingAtMeLikeThat==FALSE) {
Eric Andersen3843e961999-11-25 07:30:46 +0000135 switch (**argv) {
136 case 's':
137 toStdErrFlag = TRUE;
138 break;
139 case 'p':
140 if (--argc == 0) {
141 usage(logger_usage);
142 }
143 pri = pencode(*(++argv));
Erik Andersen1c5b2581999-12-16 20:59:36 +0000144 stopLookingAtMeLikeThat=TRUE;
Eric Andersen3843e961999-11-25 07:30:46 +0000145 break;
146 default:
147 usage(logger_usage);
148 }
149 }
150 }
151
Eric Andersenbefda6e1999-11-25 08:06:22 +0000152 if (fromStdinFlag==TRUE) {
153 /* read from stdin */
154 int i=0;
155 char c;
156 while ((c = getc(stdin)) != EOF && i<sizeof(buf1)) {
157 buf1[i++]=c;
Eric Andersen3843e961999-11-25 07:30:46 +0000158 }
Eric Andersenbefda6e1999-11-25 08:06:22 +0000159 message=buf1;
160 } else {
161 if (argc>=1) {
162 message=*argv;
163 } else {
164 fprintf(stderr, "No message\n");
165 exit( FALSE);
166 }
Eric Andersen3843e961999-11-25 07:30:46 +0000167 }
168
169 memset(&sunx, 0, sizeof(sunx));
170 sunx.sun_family = AF_UNIX; /* Unix domain socket */
171 strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path));
172 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) {
173 perror("Couldn't obtain descriptor for socket " _PATH_LOG);
174 exit( FALSE);
175 }
176
177 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
178
179 if (connect(fd, (struct sockaddr *) &sunx, addrLength)) {
180 perror("Could not connect to socket " _PATH_LOG);
181 exit( FALSE);
182 }
183
184 time(&now);
185 snprintf (buf, sizeof(buf), "<%d>%.15s %s", pri, ctime(&now)+4, message);
186
187 if (toStdErrFlag==TRUE)
188 fprintf(stderr, "%s\n", buf);
189
190 write( fd, buf, sizeof(buf));
191
192 close(fd);
193 exit( TRUE);
194}
195