Upload Tizen:Base source
[framework/base/util-linux-ng.git] / misc-utils / logger.c
1 /*
2  * Copyright (c) 1983, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
34  * - added Native Language Support
35  * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
36  * - fixed strerr(errno) in gettext calls
37  */
38
39 #include <errno.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <stdio.h>
44 #include <ctype.h>
45 #include <string.h>
46 #include <strings.h>
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/un.h>
50 #include "nls.h"
51
52 #define SYSLOG_NAMES
53 #include <syslog.h>
54
55 int     decode __P((char *, CODE *));
56 int     pencode __P((char *));
57 void    usage __P((void));
58
59 static int optd = 0;
60
61 static int
62 myopenlog(const char *sock) {
63        int fd;
64        static struct sockaddr_un s_addr; /* AF_UNIX address of local logger */
65
66        if (strlen(sock) >= sizeof(s_addr.sun_path)) {
67                printf (_("logger: openlog: pathname too long\n"));
68                exit(1);
69        }
70
71        s_addr.sun_family = AF_UNIX;
72        (void)strcpy(s_addr.sun_path, sock);
73
74        if ((fd = socket(AF_UNIX, optd ? SOCK_DGRAM : SOCK_STREAM, 0)) == -1) {
75                printf (_("socket: %s.\n"), strerror(errno));
76                exit (1);
77        }
78
79        if (connect(fd, (struct sockaddr *) &s_addr, sizeof(s_addr)) == -1) {
80                printf (_("connect: %s.\n"), strerror(errno));
81                exit (1);
82        }
83        return fd;
84 }
85
86 static void
87 mysyslog(int fd, int logflags, int pri, char *tag, char *msg) {
88        char buf[1000], pid[30], *cp, *tp;
89        time_t now;
90
91        if (fd > -1) {
92                if (logflags & LOG_PID)
93                        snprintf (pid, sizeof(pid), "[%d]", getpid());
94                else
95                        pid[0] = 0;
96                if (tag)
97                        cp = tag;
98                else {
99                        cp = getlogin();
100                        if (!cp)
101                                cp = "<someone>";
102                }
103                (void)time(&now);
104                tp = ctime(&now)+4;
105
106                snprintf(buf, sizeof(buf), "<%d>%.15s %.200s%s: %.400s",
107                         pri, tp, cp, pid, msg);
108
109                if (write(fd, buf, strlen(buf)+1) < 0)
110                        return; /* error */
111        }
112 }
113
114 /*
115  * logger -- read and log utility
116  *
117  *      Reads from an input and arranges to write the result on the system
118  *      log.
119  */
120 int
121 main(int argc, char **argv) {
122         int ch, logflags, pri;
123         char *tag, buf[1024];
124         char *usock = NULL;
125         int LogSock = -1;
126
127         setlocale(LC_ALL, "");
128         bindtextdomain(PACKAGE, LOCALEDIR);
129         textdomain(PACKAGE);
130
131         tag = NULL;
132         pri = LOG_NOTICE;
133         logflags = 0;
134         while ((ch = getopt(argc, argv, "f:ip:st:u:d")) != -1)
135                 switch((char)ch) {
136                 case 'f':               /* file to log */
137                         if (freopen(optarg, "r", stdin) == NULL) {
138                                 int errsv = errno;
139                                 (void)fprintf(stderr, _("logger: %s: %s.\n"),
140                                     optarg, strerror(errsv));
141                                 exit(1);
142                         }
143                         break;
144                 case 'i':               /* log process id also */
145                         logflags |= LOG_PID;
146                         break;
147                 case 'p':               /* priority */
148                         pri = pencode(optarg);
149                         break;
150                 case 's':               /* log to standard error */
151                         logflags |= LOG_PERROR;
152                         break;
153                 case 't':               /* tag */
154                         tag = optarg;
155                         break;
156                 case 'u':               /* unix socket */
157                         usock = optarg;
158                         break;
159                 case 'd':
160                         optd = 1;       /* use datagrams */
161                         break;
162                 case '?':
163                 default:
164                         usage();
165                 }
166         argc -= optind;
167         argv += optind;
168
169         /* setup for logging */
170         if (!usock)
171                 openlog(tag ? tag : getlogin(), logflags, 0);
172         else
173                 LogSock = myopenlog(usock);
174
175         (void) fclose(stdout);
176
177         /* log input line if appropriate */
178         if (argc > 0) {
179                 register char *p, *endp;
180                 int len;
181
182                 for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) {
183                         len = strlen(*argv);
184                         if (p + len > endp && p > buf) {
185                             if (!usock)
186                                 syslog(pri, "%s", buf);
187                             else
188                                 mysyslog(LogSock, logflags, pri, tag, buf);
189                                 p = buf;
190                         }
191                         if (len > sizeof(buf) - 1) {
192                             if (!usock)
193                                 syslog(pri, "%s", *argv++);
194                             else
195                                 mysyslog(LogSock, logflags, pri, tag, *argv++);
196                         } else {
197                                 if (p != buf)
198                                         *p++ = ' ';
199                                 memmove(p, *argv++, len);
200                                 *(p += len) = '\0';
201                         }
202                 }
203                 if (p != buf) {
204                     if (!usock)
205                         syslog(pri, "%s", buf);
206                     else
207                         mysyslog(LogSock, logflags, pri, tag, buf);
208                 }
209         } else
210                 while (fgets(buf, sizeof(buf), stdin) != NULL) {
211                     /* glibc is buggy and adds an additional newline,
212                        so we have to remove it here until glibc is fixed */
213                     int len = strlen(buf);
214
215                     if (len > 0 && buf[len - 1] == '\n')
216                             buf[len - 1] = '\0';
217
218                     if (!usock)
219                         syslog(pri, "%s", buf);
220                     else
221                         mysyslog(LogSock, logflags, pri, tag, buf);
222                 }
223         if (!usock)
224                 closelog();
225         else
226                 close(LogSock);
227         exit(0);
228 }
229
230 /*
231  *  Decode a symbolic name to a numeric value
232  */
233 int
234 pencode(s)
235         register char *s;
236 {
237         char *save;
238         int fac, lev;
239
240         for (save = s; *s && *s != '.'; ++s);
241         if (*s) {
242                 *s = '\0';
243                 fac = decode(save, facilitynames);
244                 if (fac < 0) {
245                         (void)fprintf(stderr,
246                             _("logger: unknown facility name: %s.\n"), save);
247                         exit(1);
248                 }
249                 *s++ = '.';
250         }
251         else {
252                 fac = LOG_USER;
253                 s = save;
254         }
255         lev = decode(s, prioritynames);
256         if (lev < 0) {
257                 (void)fprintf(stderr,
258                     _("logger: unknown priority name: %s.\n"), save);
259                 exit(1);
260         }
261         return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
262 }
263
264 int
265 decode(name, codetab)
266         char *name;
267         CODE *codetab;
268 {
269         register CODE *c;
270
271         if (isdigit(*name))
272                 return (atoi(name));
273
274         for (c = codetab; c->c_name; c++)
275                 if (!strcasecmp(name, c->c_name))
276                         return (c->c_val);
277
278         return (-1);
279 }
280
281 void
282 usage()
283 {
284         (void)fprintf(stderr,
285             _("usage: logger [-is] [-f file] [-p pri] [-t tag] [-u socket] [ message ... ]\n"));
286         exit(1);
287 }