source: code/logger.c@ f3c60e6

Last change on this file since f3c60e6 was 3fdebb8, checked in by Florian Obser <florian@…>, 11 years ago

log "Today is...", input mikeb

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2014 Mike Belopuhov
3 * Copyright (c) 2009 Michael Shalayeff
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
14 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/param.h>
19#include <sys/socket.h>
20#include <sys/stat.h>
21#include <sys/time.h>
22#include <sys/types.h>
23#include <sys/uio.h>
24#include <errno.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <syslog.h>
30#include <sysexits.h>
31#include <time.h>
32#include <login_cap.h>
33#include <event.h>
34#include <pwd.h>
35
36#include "icb.h"
37#include "icbd.h"
38
39void logger_dispatch(int, short, void *);
40FILE *logger_open(char *);
41void logger_tick(void);
42
43struct icbd_logentry {
44 char group[ICB_MAXGRPLEN];
45 char nick[ICB_MAXNICKLEN];
46 size_t length;
47};
48
49struct {
50 char group[ICB_MAXGRPLEN];
51 FILE *fp;
52} logfiles[10];
53int nlogfiles;
54
55int logger_pipe;
56
57char file_ts[sizeof "0000-00"];
58char line_ts[sizeof "00:00"];
59struct event ev_tick;
60
61extern char logprefix[MAXPATHLEN/2];
62extern int dologging;
63
64int
65logger_init(void)
66{
67 static struct event ev;
68 struct passwd *pw;
69 int pipes[2];
70
71 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipes) == -1) {
72 syslog(LOG_ERR, "socketpair: %m");
73 exit(EX_OSERR);
74 }
75
76 switch (fork()) {
77 case -1:
78 syslog(LOG_ERR, "fork: %m");
79 exit(EX_OSERR);
80 case 0:
81 break;
82
83 default:
84 close(pipes[1]);
85 logger_pipe = pipes[0];
86 return (0);
87 }
88
89 setproctitle("logger");
90 close(pipes[0]);
91
92 if ((pw = getpwnam(ICBD_USER)) == NULL) {
93 syslog(LOG_ERR, "No passwd entry for %s", ICBD_USER);
94 exit(EX_NOUSER);
95 }
96
97 if (setusercontext(NULL, pw, pw->pw_uid,
98 LOGIN_SETALL & ~LOGIN_SETUSER) < 0)
99 exit(EX_NOPERM);
100
101 if (chroot(pw->pw_dir) < 0) {
102 syslog(LOG_ERR, "%s: %m", pw->pw_dir);
103 exit(EX_UNAVAILABLE);
104 }
105
106 if (chdir("/") < 0) {
107 syslog(LOG_ERR, "chdir: %m");
108 exit(EX_UNAVAILABLE);
109 }
110
111 if (setuid(pw->pw_uid) < 0) {
112 syslog(LOG_ERR, "%d: %m", pw->pw_uid);
113 exit(EX_NOPERM);
114 }
115
116 event_init();
117
118 /* event for message processing */
119 event_set(&ev, pipes[1], EV_READ | EV_PERSIST, logger_dispatch, NULL);
120 if (event_add(&ev, NULL) < 0) {
121 syslog(LOG_ERR, "event_add: %m");
122 exit (EX_UNAVAILABLE);
123 }
124
125 evtimer_set(&ev_tick, (void (*)(int, short, void *))logger_tick, NULL);
126 logger_tick();
127 return event_dispatch();
128}
129
130void
131logger_dispatch(int fd, short event, void *arg __attribute__((unused)))
132{
133 char buf[ICB_MSGSIZE];
134 struct icbd_logentry e;
135 struct iovec iov[2];
136 FILE *fp = NULL;
137 int i;
138
139 if (event != EV_READ)
140 return;
141
142 bzero(&e, sizeof e);
143 iov[0].iov_base = &e;
144 iov[0].iov_len = sizeof e;
145
146 iov[1].iov_base = buf;
147 iov[1].iov_len = sizeof buf;
148
149 if (readv(fd, iov, 2) < (ssize_t)sizeof e) {
150 syslog(LOG_ERR, "logger read: %m");
151 exit(EX_DATAERR);
152 }
153
154 /* XXX */
155 if (iov[1].iov_len < e.length) {
156 syslog(LOG_ERR, "logger read %lu out of %lu",
157 iov[1].iov_len, e.length);
158 }
159
160 for (i = 0; i < nlogfiles; i++)
161 if (strcmp(logfiles[i].group, e.group) == 0)
162 fp = logfiles[i].fp;
163 if (!fp && (fp = logger_open(e.group)) == NULL)
164 return;
165 if (strlen(e.nick) == 0)
166 fprintf(fp, "[%s] %s\n", line_ts, buf);
167 else
168 fprintf(fp, "[%s] <%s> %s\n", line_ts, e.nick, buf);
169}
170
171FILE *
172logger_open(char *group)
173{
174 char path[MAXPATHLEN];
175 FILE *fp = NULL;
176
177 snprintf(path, sizeof path, "%s/%s", logprefix, group);
178 if (mkdir(path, 0755) < 0 && errno != EEXIST) {
179 syslog(LOG_ERR, "%s: %m", group);
180 return (NULL);
181 }
182 snprintf(path, sizeof path, "%s/%s/%s", logprefix, group, file_ts);
183 if ((fp = fopen(path, "a")) == NULL) {
184 syslog(LOG_ERR, "%s: %m", path);
185 return (NULL);
186 }
187 setvbuf(fp, NULL, _IOLBF, 0);
188 if (verbose)
189 syslog(LOG_DEBUG, "logger_open: %s", path);
190 strlcpy(logfiles[nlogfiles].group, group, ICB_MAXGRPLEN);
191 logfiles[nlogfiles++].fp = fp;
192 return (fp);
193}
194
195void
196logger(char *group, char *nick, char *what)
197{
198 struct icbd_logentry e;
199 struct iovec iov[2];
200
201 if (!dologging)
202 return;
203
204 strlcpy(e.group, group, ICB_MAXGRPLEN);
205 strlcpy(e.nick, nick, ICB_MAXNICKLEN);
206 e.length = strlen(what) + 1;
207
208 iov[0].iov_base = &e;
209 iov[0].iov_len = sizeof e;
210
211 iov[1].iov_base = what;
212 iov[1].iov_len = e.length;
213
214 if (writev(logger_pipe, iov, 2) == -1)
215 syslog(LOG_ERR, "logger write: %m");
216}
217
218void
219logger_tick(void)
220{
221 static int last_mon = -1, last_mday = -1;
222 struct timeval tv = { 60, 0 };
223 char buf[128];
224 struct tm *tm;
225 time_t t;
226 int i;
227
228 time(&t);
229 tm = gmtime(&t);
230 if (last_mon != tm->tm_mon) {
231 snprintf(file_ts, sizeof file_ts, "%04d-%02d", tm->tm_year +
232 1900, tm->tm_mon + 1);
233 last_mon = tm->tm_mon;
234 /* rotate log files */
235 for (i = 0; i < nlogfiles; i++) {
236 fclose(logfiles[i].fp);
237 logfiles[i].fp = NULL;
238 }
239 nlogfiles = 0;
240 }
241 if (tm->tm_mday != last_mday) {
242 strftime(buf, sizeof(buf),
243 "Today is %a %b %e %Y %H:%M %Z (%z)", tm);
244 for (i = 0; i < nlogfiles; i++)
245 fprintf(logfiles[i].fp, "%s\n", buf);
246 last_mday = tm->tm_mday;
247 }
248 snprintf(line_ts, sizeof line_ts, "%02d:%02d", tm->tm_hour,
249 tm->tm_min);
250 if (evtimer_add(&ev_tick, &tv) < 0) {
251 syslog(LOG_ERR, "evtimer_add: %m");
252 exit (EX_UNAVAILABLE);
253 }
254}
Note: See TracBrowser for help on using the repository browser.