1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <unistd.h>
4 #include <pwd.h>
5 #include <grp.h>
6 #include <stdio.h>
7 #include "error.h"
8 #include "strerr.h"
9 #include "open.h"
10 #include "buffer.h"
11 
12 #if defined(__sun__) && defined(__sparc__) && defined(__unix__) && defined(__svr4__)
13 #define SOLARIS
14 #include <sys/utsname.h>
15 #include "scan.h"
16 #endif
17 
18 #ifndef SOLARIS
19 #include <paths.h>
20 #endif
21 #ifndef _PATH_KLOG
22 #define _PATH_KLOG "/dev/klog"
23 #endif
24 
25 #define USAGE1 " unix|inet|klog|ucspi acct logacct [/etc/sv] [/logdir]"
26 #define USAGE2 " notify acct grp [/etc/sv] [pipe]"
27 
28 #define VERSION "$Id: socklog-conf.c,v 1.14 2006/03/06 12:56:34 pape Exp $"
29 #define WARNING "socklog-conf: warning: "
30 #define FATAL "socklog-conf: fatal: "
31 
32 #define CONF_DIR "/etc/sv"
33 #define LOG_DIR_UNIX "/var/log/socklog"
34 #define LOG_DIR_INET "/var/log/socklog-inet"
35 #define LOG_DIR_UCSPI_TCP "/var/log/socklog-ucspi-tcp"
36 #define LOG_DIR_KLOG "/var/log/socklog-klog"
37 #define PATH_NOTIFY "/var/log/socklog/.notify"
38 
39 #define CONF_UNIX 0
40 #define CONF_INET 1
41 #define CONF_UCSPI_TCP 2
42 #define CONF_NOTIFY 3
43 #define CONF_KLOG 4
44 
45 const char *progname;
46 
usage()47 void usage() {
48   strerr_warn3("usage: ", progname, USAGE1, 0);
49   strerr_die4x(1, "usage: ", progname, USAGE2, "\n");
50 }
51 
52 const char *dir;
53 const char *fn;
54 char buf[1024];
55 int fd;
56 buffer b;
57 
58 char *user;
59 char *loguser;
60 const char *path;
61 
62 struct passwd *upw, *pw;
63 struct group *gr;
64 
fail()65 void fail() {
66   if (fn[0] == '/')
67     strerr_die4sys(111, FATAL, "unable to create ", fn, ": ");
68   else
69     strerr_die6sys(111, FATAL, "unable to create ", dir, "/", fn, ": ");
70 }
71 
start(const char * s)72 void start(const char *s) {
73   fn = s;
74   fd = open_trunc(fn);
75   if (fd == -1) fail();
76   buffer_init(&b, write, fd, buf, sizeof buf);
77 }
78 
outs(const char * s)79 void outs(const char *s) {
80   if (buffer_puts(&b, s) == -1) fail();
81 }
82 
finish(void)83 void finish(void) {
84   if (buffer_flush(&b) == -1) fail();
85   if (fsync(fd) == -1) fail();
86   close(fd);
87 }
88 
perm(int mode)89 void perm(int mode) { if (chmod(fn, mode) == -1) fail(); }
90 
mkfile(const char * f,const char * s)91 void mkfile(const char *f, const char *s) {
92   start(f);
93   outs(s); outs("\n");
94   finish();
95 }
96 
makedir(const char * s)97 void makedir(const char *s) {
98   fn =s;
99   if (mkdir(fn, 0750) == -1) fail();
100 }
makechdir(const char * s)101 void makechdir(const char *s) {
102   makedir(s);
103   if (chown(s, pw->pw_uid, pw->pw_gid) == -1)
104     strerr_die6sys(111, FATAL, "unable to set owner of ", dir, "/", s, ": ");
105 }
106 
conf_unix()107 void conf_unix() {
108 #ifdef SOLARIS
109 #if WANT_SUN_DOOR
110   struct utsname u;
111   unsigned long sunos_version;
112   uname(&u);
113   scan_ulong(u.release+strlen(u.release)-1, &sunos_version);
114 #endif
115 #endif
116   makedir("socklog-unix");
117   perm(0750);
118   makedir("socklog-unix/log");
119   perm(0755);
120 
121   makechdir(path);
122   if (symlink(path, "socklog-unix/log/main") == -1)
123     strerr_die4sys(111, FATAL, "unable to link ", path, ": ");
124   makechdir("socklog-unix/log/main/auth");
125   mkfile("socklog-unix/log/main/auth/config", "s999999\nn5\n-*\n+auth.*\n+authpriv.*");
126   makechdir("socklog-unix/log/main/cron");
127   mkfile("socklog-unix/log/main/cron/config", "s999999\nn5\n-*\n+cron.*");
128   makechdir("socklog-unix/log/main/daemon");
129   mkfile("socklog-unix/log/main/daemon/config", "s999999\nn5\n-*\n+daemon.*");
130   makechdir("socklog-unix/log/main/debug");
131   mkfile("socklog-unix/log/main/debug/config", "s999999\nn5\n-*\n+*.debug*");
132   makechdir("socklog-unix/log/main/ftp");
133   mkfile("socklog-unix/log/main/ftp/config", "s999999\nn5\n-*\n+ftp.*");
134   makechdir("socklog-unix/log/main/kern");
135   mkfile("socklog-unix/log/main/kern/config", "s999999\nn5\n-*\n+kern.*");
136   makechdir("socklog-unix/log/main/local");
137   mkfile("socklog-unix/log/main/local/config", "s999999\nn5\n-*\n+local.*");
138   makechdir("socklog-unix/log/main/mail");
139   mkfile("socklog-unix/log/main/mail/config", "s999999\nn5\n-*\n+mail.*");
140   makechdir("socklog-unix/log/main/main");
141   mkfile("socklog-unix/log/main/main/config", "s999999\nn10");
142   makechdir("socklog-unix/log/main/news");
143   mkfile("socklog-unix/log/main/news/config", "s999999\nn5\n-*\n+news.*");
144   makechdir("socklog-unix/log/main/syslog");
145   mkfile("socklog-unix/log/main/syslog/config", "s999999\nn5\n-*\n+syslog.*");
146   makechdir("socklog-unix/log/main/user");
147   mkfile("socklog-unix/log/main/user/config", "s999999\nn5\n-*\n+user.*");
148 
149   start("socklog-unix/run");
150   outs("#!/bin/sh\n");
151   outs("exec 2>&1\n");
152 #ifndef SOLARIS
153   outs("exec chpst -U"); outs(user); outs(" socklog unix /dev/log\n");
154 #else
155   outs("exec chpst -U"); outs(user); outs(" socklog sun_stream /dev/log");
156 #if WANT_SUN_DOOR
157   if (sunos_version == 7) outs(" /etc/.syslog_door");
158   if (sunos_version >= 8) outs(" /var/run/syslog_door");
159 #endif
160   outs("\n");
161 #endif
162   finish();
163   perm(0750);
164 
165   start("socklog-unix/check");
166   outs("#!/bin/sh\n");
167   outs("exec 2>/dev/null\n");
168   outs("exec socklog-check unix /dev/log\n");
169   finish();
170   perm(0755);
171 
172   start("socklog-unix/log/run");
173   outs("#!/bin/sh\n");
174   outs("exec chpst -u");
175   outs(loguser);
176   outs(" svlogd \\\n");
177   outs("  main/main main/auth main/cron main/daemon main/debug main/ftp \\\n");
178   outs("  main/kern main/local main/mail main/news main/syslog main/user\n");
179   finish();
180   perm(0750);
181 }
182 
conf_inet()183 void conf_inet() {
184   makedir("socklog-inet");
185   perm(0750);
186   makedir("socklog-inet/log");
187   perm(0755);
188 
189   makechdir(path);
190   if (symlink(path, "socklog-inet/log/main") == -1)
191     strerr_die4sys(111, FATAL, "unable to link ", path, ": ");
192   makechdir("socklog-inet/log/main/main");
193   mkfile("socklog-inet/log/main/main/config", "s999999\nn10");
194 
195   start("socklog-inet/run");
196   outs("#!/bin/sh\n");
197   outs("exec 2>&1\n");
198   outs("exec chpst -U"); outs(user); outs(" socklog inet 0 514\n");
199   finish();
200   perm(0750);
201 
202   start("socklog-inet/log/run");
203   outs("#!/bin/sh\n");
204   outs("exec chpst -u");
205   outs(loguser);
206   outs(" svlogd -t main/main\n");
207   finish();
208   perm(0750);
209 }
210 
conf_ucspi_tcp()211 void conf_ucspi_tcp() {
212   makedir("socklog-ucspi-tcp");
213   perm(0750);
214   makedir("socklog-ucspi-tcp/log");
215   perm(0755);
216 
217   makechdir(path);
218   if (symlink(path, "socklog-ucspi-tcp/log/main") == -1)
219     strerr_die4sys(111, FATAL, "unable to link ", path, ": ");
220   makechdir("socklog-ucspi-tcp/log/main/main");
221   mkfile("socklog-ucspi-tcp/log/main/main/config", "s999999\nn10");
222 
223   start("socklog-ucspi-tcp/run");
224   outs("#!/bin/sh\n");
225   outs("PORT=10116\n");
226   outs("exec 2>&1\n");
227   outs("exec tcpsvd -vllogserver -u");
228   outs(user);
229   outs(" 0 \"$PORT\" socklog ucspi TCPREMOTEIP\n");
230   finish();
231   perm(0750);
232 
233   start("socklog-ucspi-tcp/log/run");
234   outs("#!/bin/sh\n");
235   outs("exec chpst -u");
236   outs(loguser);
237   outs(" svlogd -t main/main\n");
238   finish();
239   perm(0750);
240 }
241 
conf_klog()242 void conf_klog() {
243   makedir("socklog-klog");
244   perm(0750);
245   makedir("socklog-klog/log");
246   perm(0755);
247 
248   makechdir(path);
249   if (symlink(path, "socklog-klog/log/main") == -1)
250     strerr_die4sys(111, FATAL, "unable to link ", path, ": ");
251   makechdir("socklog-klog/log/main/main");
252   mkfile("socklog-klog/log/main/main/config", "s999999\nn10");
253 
254   start("socklog-klog/run");
255   outs("#!/bin/sh\n");
256   outs("exec <"); outs(_PATH_KLOG); outs("\n");
257   outs("exec 2>&1\n");
258   outs("exec chpst -u");
259   outs(user);
260   outs(" socklog ucspi\n");
261   finish();
262   perm(0750);
263 
264   start("socklog-klog/log/run");
265   outs("#!/bin/sh\n");
266   outs("exec chpst -u");
267   outs(loguser);
268   outs(" svlogd -t main/main\n");
269   finish();
270   perm(0750);
271 }
272 
conf_notify()273 void conf_notify() {
274   makedir("socklog-notify");
275   perm(0755);
276 
277   umask(007);
278   if (mkfifo(path, 0620) == -1)
279     strerr_die4sys(111, FATAL, "unable to create \"", path, "\": ");
280   umask(022);
281   if (chown(path, upw->pw_uid, gr->gr_gid) == -1)
282     strerr_die4sys(111, FATAL, "unable to set owner of ", path, ": ");
283 
284   start("socklog-notify/run");
285   outs("#!/bin/sh -e\n");
286   outs("MAILTO=root\n");
287   outs("PIPE="); outs(path); outs("\n\n");
288   outs("if [ ! -p \"$PIPE\" ]; then mkfifo -m0620 \"$PIPE\"; chown ");
289   outs(user); outs(":"); outs(loguser);
290   outs(" \"$PIPE\"; fi\n");
291   outs("exec <> \"$PIPE\"\n");
292   outs("exec chpst -u");
293   outs(user);
294   outs(" uncat -s49999 -t180 \\\n");
295   outs("  env MAILUSER=log MAILNAME='socklog notify' \\\n");
296   outs("    mail -s socklog-notify $MAILTO\n");
297   finish();
298   perm(0750);
299 }
300 
main(int argc,char ** argv)301 int main(int argc, char **argv) {
302   int mode =0;
303 
304   progname =*argv++;
305   umask(022);
306 
307   if (! *argv) usage();
308   switch (**argv) {
309   case 'u':
310     if (! *(++*argv)) usage();
311     switch (**argv) {
312     case 'n':
313       mode =CONF_UNIX;
314       break;
315     case 'c':
316       mode =CONF_UCSPI_TCP;
317       break;
318     default:
319       usage();
320     }
321     break;
322   case 'i':
323     mode =CONF_INET;
324     break;
325   case 'n':
326     mode =CONF_NOTIFY;
327     break;
328   case 'k':
329     mode =CONF_KLOG;
330     break;
331   case '-':
332     if ((*argv)[1] && (*argv)[1] == 'V') {
333       strerr_warn2(VERSION, "\n", 0);
334     }
335   default:
336     usage();
337   }
338   argv++;
339 
340   user =*argv++;
341   if (!user) usage();
342   loguser =*argv++;
343   if (!loguser) usage();
344   dir =*argv++;
345   if (!dir) {
346     dir =CONF_DIR;
347   } else {
348     if (dir[0] != '/') usage();
349     if (*argv) {
350       path =*argv;
351       if (path[0] != '/') usage();
352     }
353   }
354 
355   upw =getpwnam(user);
356   if (!upw) strerr_die3x(111, FATAL, "unknown account ", user);
357   if (mode != CONF_NOTIFY) {
358     pw =getpwnam(loguser);
359     if (!pw) strerr_die3x(111, FATAL, "unknown account ", loguser);
360   } else {
361     gr =getgrnam(loguser);
362     if (!gr) strerr_die3x(111, FATAL, "unknown group ", loguser);
363   }
364 
365   if (chdir(dir) == -1) {
366     if (errno != error_noent)
367       strerr_die4sys(111, FATAL, "unable to switch to ", dir, ": ");
368 
369     if (mkdir(dir, 0700) == -1)
370       strerr_die4sys(111, FATAL, "unable to create ", dir, ": ");
371     if (chmod(dir, 0750) == -1)
372       strerr_die4sys(111, FATAL, "unable to set mode of ", dir, ": ");
373     if (chdir(dir) == -1)
374       strerr_die4sys(111, FATAL, "unable to switch to ", dir, ": ");
375   }
376 
377   switch(mode) {
378   case CONF_UNIX:
379     if (!path) path =LOG_DIR_UNIX;
380     conf_unix();
381     break;
382   case CONF_INET:
383     if (!path) path =LOG_DIR_INET;
384     conf_inet();
385     break;
386   case CONF_UCSPI_TCP:
387     if (!path) path =LOG_DIR_UCSPI_TCP;
388     conf_ucspi_tcp();
389     break;
390   case CONF_KLOG:
391     if (!path) path =LOG_DIR_KLOG;
392     conf_klog();
393     break;
394   case CONF_NOTIFY:
395     if (!path) path =PATH_NOTIFY;
396     conf_notify();
397     break;
398   }
399   return(0);
400 }
401