1 /* ISC license. */
2 
3 #undef INTERNAL_MARK
4 #ifndef SYSLOG_NAMES
5 #define SYSLOG_NAMES
6 #endif
7 
8 #include <skalibs/nonposix.h>
9 #include <sys/types.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <syslog.h>
13 #include <skalibs/types.h>
14 #include <skalibs/sgetopt.h>
15 #include <skalibs/bytestr.h>
16 #include <skalibs/buffer.h>
17 #include <skalibs/strerr2.h>
18 #include <skalibs/stralloc.h>
19 #include <skalibs/env.h>
20 #include <skalibs/skamisc.h>
21 
22 #define USAGE "ucspilogd [ -D default ] [ var... ]"
23 #define dieusage() strerr_dieusage(100, USAGE)
24 
die(void)25 static inline void die (void)
26 {
27   strerr_diefu1sys(111, "write to stdout") ;
28 }
29 
30 
31  /*
32    Hack: INTERNAL_MARK is defined by all systems that
33    use the CODE stuff, and not by others (Solaris).
34 */
35 
36 #ifndef INTERNAL_MARK
37 
38 typedef struct CODE_s CODE, *CODE_ref ;
39 struct CODE_s
40 {
41   char *c_name ;
42   unsigned int c_val ;
43 } ;
44 
45 static CODE const prioritynames[] =
46 {
47   { "emerg", LOG_EMERG },
48   { "alert", LOG_ALERT },
49   { "crit", LOG_CRIT },
50   { "err", LOG_ERR },
51   { "warning", LOG_WARNING },
52   { "notice", LOG_NOTICE },
53   { "info", LOG_INFO },
54   { "debug", LOG_DEBUG },
55   { 0, -1 }
56 } ;
57 
58 static CODE const facilitynames[] =
59 {
60   { "kern", LOG_KERN },
61   { "user", LOG_USER },
62   { "mail", LOG_MAIL },
63   { "news", LOG_NEWS },
64   { "uucp", LOG_UUCP },
65   { "daemon", LOG_DAEMON },
66   { "auth", LOG_AUTH },
67   { "cron", LOG_CRON },
68   { "lpr", LOG_LPR },
69 #ifdef LOG_SYSLOG
70   { "syslog", LOG_SYSLOG },
71 #endif
72 #ifdef LOG_AUDIT
73   { "audit", LOG_AUDIT },
74 #endif
75   { "local0", LOG_LOCAL0 },
76   { "local1", LOG_LOCAL1 },
77   { "local2", LOG_LOCAL2 },
78   { "local3", LOG_LOCAL3 },
79   { "local4", LOG_LOCAL4 },
80   { "local5", LOG_LOCAL5 },
81   { "local6", LOG_LOCAL6 },
82   { "local7", LOG_LOCAL7 },
83   { 0, -1 }
84 } ;
85 
86 #define LOG_PRI(p) ((p) & LOG_PRIMASK)
87 #define LOG_FAC(p) (((p) & LOG_FACMASK) / (LOG_PRIMASK + 1))
88 
89 #endif
90 
91 
syslog_names(char const * line)92 static size_t syslog_names (char const *line)
93 {
94   size_t i ;
95   unsigned int fpr ;
96   int fp ;
97   CODE const *p = facilitynames ;
98 
99   if (line[0] != '<') return 0 ;
100   i = uint_scan(line+1, &fpr) ;
101   if (!i || (line[i+1] != '>')) return 0 ;
102   i += 2 ;
103 
104   fp = LOG_FAC(fpr) << 3 ;
105   for (; p->c_name ; p++) if (p->c_val == fp) break ;
106   if (p->c_name)
107   {
108     if ((buffer_puts(buffer_1, p->c_name) < 0)
109      || (buffer_put(buffer_1, ".", 1) < 1)) die() ;
110   }
111   else
112   {
113     if (buffer_put(buffer_1, "unknown.", 8) < 8) die() ;
114     i = 0 ;
115   }
116 
117   fp = LOG_PRI(fpr) ;
118   for (p = prioritynames ; p->c_name ; p++) if (p->c_val == fp) break ;
119   if (p->c_name)
120   {
121     if ((buffer_puts(buffer_1, p->c_name) < 0)
122      || (buffer_put(buffer_1, ": ", 2) < 2)) die() ;
123   }
124   else
125   {
126     if (buffer_put(buffer_1, "unknown: ", 9) < 9) die() ;
127     i = 0 ;
128   }
129   return i ;
130 }
131 
132 
main(int argc,char const * const * argv,char const * const * envp)133 int main (int argc, char const *const *argv, char const *const *envp)
134 {
135   char const *d = "<undefined>" ;
136   PROG = "ucspilogd" ;
137   {
138     subgetopt_t l = SUBGETOPT_ZERO ;
139     for (;;)
140     {
141       int opt = subgetopt_r(argc, argv, "D:", &l) ;
142       if (opt == -1) break ;
143       switch (opt)
144       {
145         case 'D' : d = l.arg ; break ;
146         default : dieusage() ;
147       }
148     }
149     argc -= l.ind ; argv += l.ind ;
150   }
151 
152   {
153     char const *envs[argc] ;
154     unsigned int i = 0 ;
155     for (; i < (unsigned int)argc ; i++)
156     {
157       envs[i] = env_get2(envp, argv[i]) ;
158       if (!envs[i]) envs[i] = d ;
159     }
160     for (;;)
161     {
162       size_t pos = 0 ;
163       satmp.len = 0 ;
164       {
165         int r = skagetlnsep(buffer_0f1, &satmp, "\n", 2) ;
166         if (r < 0)
167         {
168           if (errno != EPIPE || !stralloc_0(&satmp))
169             strerr_diefu1sys(111, "read from stdin") ;
170         }
171         if (!r) break ;
172       }
173       if (!satmp.len) continue ;
174       satmp.s[satmp.len-1] = '\n' ;
175       if ((satmp.s[0] == '@') && (satmp.len > 26) && (byte_chr(satmp.s, 26, ' ') == 25))
176       {
177         if (buffer_put(buffer_1, satmp.s, 26) < 26) die() ;
178         pos += 26 ;
179       }
180       for (i = 0 ; i < (unsigned int)argc ; i++)
181         if ((buffer_puts(buffer_1, envs[i]) < 0)
182          || (buffer_put(buffer_1, ": ", 2) < 2)) die() ;
183       pos += syslog_names(satmp.s + pos) ;
184       if (buffer_put(buffer_1, satmp.s + pos, satmp.len - pos) < (ssize_t)(satmp.len - pos)) die() ;
185     }
186   }
187   return 0 ;
188 }
189