1 /* logger.c - Log messages.
2  *
3  * Copyright 2013 Ilya Kuzmich <ilya.kuzmich@gmail.com>
4  *
5  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/logger.html
6  *
7  * Deviations from posix: specified manner and format, defined implementation.
8 
9 USE_LOGGER(NEWTOY(logger, "st:p:", TOYFLAG_USR|TOYFLAG_BIN))
10 
11 config LOGGER
12   bool "logger"
13   default y
14   help
15     usage: logger [-s] [-t TAG] [-p [FACILITY.]PRIORITY] [message...]
16 
17     Log message (or stdin) to syslog.
18 
19     -s	Also write message to stderr
20     -t	Use TAG instead of username to identify message source
21     -p	Specify PRIORITY with optional FACILITY. Default is "user.notice"
22 */
23 
24 #define FOR_logger
25 #include "toys.h"
26 
GLOBALS(char * priority;char * ident;)27 GLOBALS(
28   char *priority;
29   char *ident;
30 )
31 
32 // find str in names[], accepting unambiguous short matches
33 // returns offset into array of match, or -1 if no match
34 int arrayfind(char *str, char *names[], int len)
35 {
36   int try, i, matchlen = 0, found = -1, ambiguous = 1;
37 
38   for (try = 0; try<len; try++) {
39     for (i=0; ; i++) {
40       if (!str[i]) {
41         if (matchlen<i) found = try, ambiguous = 0;
42         if (matchlen==i) ambiguous++;
43         if (!names[try][i]) return try;
44         break;
45       }
46       if (!names[try][i]) break;
47       if (toupper(str[i]) != toupper(names[try][i])) break;
48     }
49   }
50   return ambiguous ? -1 : found;
51 }
52 
logger_main(void)53 void logger_main(void)
54 {
55   int facility = LOG_USER, priority = LOG_NOTICE, len;
56   char *s1, *s2, **arg,
57     *priorities[] = {"emerg", "alert", "crit", "error", "warning", "notice",
58                      "info", "debug"},
59     *facilities[] = {"kern", "user", "mail", "daemon", "auth", "syslog",
60                      "lpr", "news", "uucp", "cron", "authpriv", "ftp"};
61 
62   if (!TT.ident) TT.ident = xstrdup(xgetpwuid(geteuid())->pw_name);
63   if (toys.optflags & FLAG_p) {
64     if (!(s1 = strchr(TT.priority, '.'))) s1 = TT.priority;
65     else {
66       *s1++ = len = 0;
67       facility = arrayfind(TT.priority, facilities, ARRAY_LEN(facilities));
68       if (facility == -1 && strncasecmp(TT.priority, "local", 5)) {
69         facility = s1[5]-'0';
70         if (facility>7 || s1[6]) facility = -1;
71         if (facility>=0) facility += 16;
72       }
73       if (facility<0) error_exit("bad facility: %s", TT.priority);
74       facility *= 8;
75     }
76 
77     priority = arrayfind(s1, priorities, ARRAY_LEN(priorities));
78     if (priority<0) error_exit("bad priority: %s", s1);
79   }
80 
81   if (toys.optc) {
82     for (len = 0, arg = toys.optargs; *arg; arg++) len += strlen(*arg)+1;
83     s1 = s2 = xmalloc(len);
84     for (arg = toys.optargs; *arg; arg++) {
85       if (arg != toys.optargs) *s2++ = ' ';
86       s2 = stpcpy(s2, *arg);
87     }
88   } else {
89     toybuf[readall(0, toybuf, sizeof(toybuf)-1)] = 0;
90     s1 = toybuf;
91   }
92 
93   openlog(TT.ident, LOG_PERROR*!!(toys.optflags&FLAG_s), facility);
94   syslog(priority, "%s", s1);
95   closelog();
96 }
97