blob: dfbc557ecfee7c8e2338fc5e25e5b7a29990fba1 [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;
Eric Andersenbefda6e1999-11-25 08:06:22 +0000123 char *message, buf[1024], buf1[1024];
Eric Andersen3843e961999-11-25 07:30:46 +0000124 time_t now;
125 size_t addrLength;
126
127 /* Parse any options */
128 while (--argc > 0 && **(++argv) == '-') {
Eric Andersenbefda6e1999-11-25 08:06:22 +0000129 if (*((*argv)+1) == '\0') {
130 fromStdinFlag=TRUE;
131 }
Eric Andersen3843e961999-11-25 07:30:46 +0000132 while (*(++(*argv))) {
133 switch (**argv) {
134 case 's':
135 toStdErrFlag = TRUE;
136 break;
137 case 'p':
138 if (--argc == 0) {
139 usage(logger_usage);
140 }
141 pri = pencode(*(++argv));
142 if (--argc == 0) {
143 usage(logger_usage);
144 }
145 ++argv;
146 break;
147 default:
148 usage(logger_usage);
149 }
150 }
151 }
152
Eric Andersenbefda6e1999-11-25 08:06:22 +0000153 if (fromStdinFlag==TRUE) {
154 /* read from stdin */
155 int i=0;
156 char c;
157 while ((c = getc(stdin)) != EOF && i<sizeof(buf1)) {
158 buf1[i++]=c;
Eric Andersen3843e961999-11-25 07:30:46 +0000159 }
Eric Andersenbefda6e1999-11-25 08:06:22 +0000160 message=buf1;
161 } else {
162 if (argc>=1) {
163 message=*argv;
164 } else {
165 fprintf(stderr, "No message\n");
166 exit( FALSE);
167 }
Eric Andersen3843e961999-11-25 07:30:46 +0000168 }
169
170 memset(&sunx, 0, sizeof(sunx));
171 sunx.sun_family = AF_UNIX; /* Unix domain socket */
172 strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path));
173 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) {
174 perror("Couldn't obtain descriptor for socket " _PATH_LOG);
175 exit( FALSE);
176 }
177
178 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
179
180 if (connect(fd, (struct sockaddr *) &sunx, addrLength)) {
181 perror("Could not connect to socket " _PATH_LOG);
182 exit( FALSE);
183 }
184
185 time(&now);
186 snprintf (buf, sizeof(buf), "<%d>%.15s %s", pri, ctime(&now)+4, message);
187
188 if (toStdErrFlag==TRUE)
189 fprintf(stderr, "%s\n", buf);
190
191 write( fd, buf, sizeof(buf));
192
193 close(fd);
194 exit( TRUE);
195}
196