Remove wheel submodule - will re-add later with new URL
[dmon:dmon.git] / dslog.c
1 /*
2  * dslog.c
3  * Copyright (C) 2010 Adrian Perez <aperez@igalia.com>
4  *
5  * Distributed under terms of the MIT license.
6  */
7
8 #include "wheel.h"
9 #include "util.h"
10 #include <stdlib.h>
11 #include <syslog.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15
16
17 #ifdef NO_MULTICALL
18 # define dslog_main main
19 #endif /* NO_MULTICALL */
20
21
22 #ifndef DEFAULT_FACILITY
23 #define DEFAULT_FACILITY "daemon"
24 #endif /* !DEFAULT_FACILITY */
25
26
27 #ifndef DEFAULT_PRIORITY
28 #define DEFAULT_PRIORITY "warning"
29 #endif /* !DEFAULT_PRIORITY */
30
31
32 static int
33 name_to_facility (const char *name)
34 {
35     static const struct {
36         const char *name;
37         int         code;
38     } map[] = {
39 #ifdef LOG_AUTHPRIV
40         { "auth",     LOG_AUTHPRIV },
41 #else  /* LOG_AUTHPRIV */
42         { "auth",     LOG_AUTH     },
43 #endif /* LOG_AUTHPRIV */
44         { "cron",     LOG_CRON     },
45         { "daemon",   LOG_DAEMON   },
46         { "ftp",      LOG_FTP      },
47         { "kern",     LOG_KERN     },
48         { "kernel",   LOG_KERN     },
49         { "local0",   LOG_LOCAL0   },
50         { "local1",   LOG_LOCAL1   },
51         { "local2",   LOG_LOCAL2   },
52         { "local3",   LOG_LOCAL3   },
53         { "local4",   LOG_LOCAL4   },
54         { "local5",   LOG_LOCAL5   },
55         { "local6",   LOG_LOCAL6   },
56         { "local7",   LOG_LOCAL7   },
57         { "lpr",      LOG_LPR      },
58         { "print",    LOG_LPR      },
59         { "printer",  LOG_LPR      },
60         { "mail",     LOG_MAIL     },
61         { "news",     LOG_NEWS     },
62         { "user",     LOG_USER     },
63         { "uucp",     LOG_UUCP     },
64         { NULL,       0            },
65     };
66     unsigned i = 0;
67
68     while (map[i].name) {
69         if (strcasecmp (name, map[i].name) == 0)
70             return map[i].code;
71         i++;
72     }
73
74     return -1;
75 }
76
77
78 static int
79 name_to_priority (const char *name)
80 {
81     static const struct {
82         const char *name;
83         int         code;
84     } map[] = {
85         { "emerg",     LOG_EMERG   },
86         { "emergency", LOG_EMERG   },
87         { "alert",     LOG_ALERT   },
88         { "crit",      LOG_CRIT    },
89         { "critical",  LOG_CRIT    },
90         { "err",       LOG_ERR     },
91         { "error",     LOG_ERR     },
92         { "warn",      LOG_WARNING },
93         { "warning",   LOG_WARNING },
94         { "notice",    LOG_NOTICE  },
95         { "info",      LOG_INFO    },
96         { "debug",     LOG_DEBUG   },
97         { NULL,        0           },
98     };
99     unsigned i = 0;
100
101     while (map[i].name) {
102         if (strcasecmp (map[i].name, name) == 0)
103             return map[i].code;
104         i++;
105     }
106
107     return -1;
108 }
109
110
111 static wbool running = W_YES;
112
113
114 static w_opt_status_t
115 _facility_option (const w_opt_context_t *ctx)
116 {
117     int *facility;
118
119     w_assert (ctx);
120     w_assert (ctx->argument);
121     w_assert (ctx->argument[0]);
122     w_assert (ctx->option);
123     w_assert (ctx->option->extra);
124
125     facility = (int*) ctx->option->extra;
126
127     return ((*facility = name_to_facility (ctx->argument[0])) == -1)
128          ? W_OPT_BAD_ARG
129          : W_OPT_OK;
130 }
131
132
133 static w_opt_status_t
134 _priority_option (const w_opt_context_t *ctx)
135 {
136     int *priority;
137
138     w_assert (ctx);
139     w_assert (ctx->argument);
140     w_assert (ctx->argument[0]);
141     w_assert (ctx->option);
142     w_assert (ctx->option->extra);
143
144     priority = (int*) ctx->option->extra;
145
146     return ((*priority = name_to_priority (ctx->argument[0])) == -1)
147          ? W_OPT_BAD_ARG
148          : W_OPT_OK;
149 }
150
151
152 int
153 dslog_main (int argc, char **argv)
154 {
155     int flags = 0;
156     int facility = name_to_facility (DEFAULT_FACILITY);
157     int priority = name_to_priority (DEFAULT_PRIORITY);
158     wbool console = W_NO;
159     char *env_opts = NULL;
160     w_buf_t linebuf = W_BUF;
161     w_buf_t overflow = W_BUF;
162     unsigned consumed;
163
164     w_opt_t dslog_options[] = {
165         { 1, 'f', "facility", _facility_option, &facility,
166             "Log facility (default: daemon)." },
167         { 1, 'p', "priority", _priority_option, &priority,
168             "Log priority (default: warning)." },
169         { 0, 'c', "console", W_OPT_BOOL, &console,
170             "Log to console if sending messages to logger fails." },
171         W_OPT_END
172     };
173
174
175     if ((env_opts = getenv ("DSLOG_OPTIONS")) != NULL)
176         replace_args_string (env_opts, &argc, &argv);
177
178     consumed = w_opt_parse (dslog_options, NULL, NULL, "name", argc, argv);
179
180     if (console)
181         flags |= LOG_CONS;
182
183     /* We will be no longer using standard output. */
184     w_io_close (w_stdout);
185
186     if (consumed >= (unsigned) argc)
187         w_die ("$s: process name not specified.\n", argv[0]);
188
189     openlog (argv[consumed], flags, facility);
190
191     while (running) {
192         ssize_t ret = w_io_read_line (w_stdin, &linebuf, &overflow, 0);
193
194         if (ret == W_IO_ERR) {
195             w_io_format (w_stderr, "$s: error reading input: $E\n", argv[0]);
196             exit (111);
197         }
198
199         if (w_buf_length (&linebuf))
200             syslog (priority, "%s", w_buf_str (&linebuf));
201
202         w_buf_reset (&linebuf);
203
204         if (ret == W_IO_EOF) /* EOF reached */
205             break;
206     }
207
208     closelog ();
209
210         exit (EXIT_SUCCESS);
211 }
212
213 /* vim: expandtab shiftwidth=4 tabstop=4
214  */