Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / network / stacks / AROSTCP / C / logger.c
blob019d8604220b350e62d4210c23f577bc4d7430ec
1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 static const char copyright[] =
35 "$VER: logger v1.0"
36 "Copyright (c) 1983, 1993 The Regents of the University of California. All rights reserved.\n"
37 "Copygigjt (c) 2005 - 2006 Pavel Fedin";
39 #include <sys/cdefs.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
45 #include <ctype.h>
46 #if !defined(__AROS__)
47 #include <err.h>
48 #endif
49 #include <netdb.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
55 #include <proto/socket.h>
56 #include <proto/miami.h>
58 #include <proto/exec.h>
59 #include <dos/dos.h>
60 struct Library *SocketBase;
61 struct Library *MiamiBase;
63 #define SYSLOG_NAMES
64 #include <syslog.h>
66 #define D(x)
68 int decode(char *, CODE *);
69 int pencode(char *);
70 static void logmessage(int, char *, char *);
71 static void usage(void);
73 struct socks {
74 int sock;
75 int addrlen;
76 struct sockaddr addr;
79 #ifdef INET6
80 int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
81 #else
82 int family = PF_INET; /* protocol family (IPv4 only) */
83 #endif
84 int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
87 * logger -- read and log utility
89 * Reads from an input and arranges to write the result on the system
90 * log.
92 int
93 main(int argc, char *argv[])
95 int ch, logflags, pri;
96 char *tag, *host, buf[1024];
98 #if defined(__AROS__)
99 if (!(SocketBase = OpenLibrary("bsdsocket.library", 3)))
101 return RETURN_FAIL;
103 if (!(SocketBase = OpenLibrary("miami.library", 0)))
105 return RETURN_FAIL;
107 #endif
109 tag = NULL;
110 host = NULL;
111 pri = LOG_USER | LOG_NOTICE;
112 logflags = 0;
113 while ((ch = getopt(argc, argv, "46Af:h:ip:st:")) != -1)
114 switch((char)ch) {
115 case '4':
116 family = PF_INET;
117 break;
118 #ifdef INET6
119 case '6':
120 family = PF_INET6;
121 break;
122 #endif
123 case 'A':
124 send_to_all++;
125 break;
126 case 'f': /* file to log */
127 if (freopen(optarg, "r", stdin) == NULL)
129 #warning "TODO: NicJA - we dont have err()"
130 #if !defined(__AROS__)
131 err(1, "%s", optarg);
132 #else
133 //return RETURN_FAIL;
134 #endif
136 break;
137 case 'h': /* hostname to deliver to */
138 host = optarg;
139 break;
140 case 'i': /* log process id also */
141 logflags |= LOG_PID;
142 break;
143 case 'p': /* priority */
144 pri = pencode(optarg);
145 break;
146 case 's': /* log to standard error */
147 logflags |= LOG_PERROR;
148 break;
149 case 't': /* tag */
150 tag = optarg;
151 break;
152 case '?':
153 default:
154 usage();
156 argc -= optind;
157 argv += optind;
159 /* setup for logging */
160 #warning "TODO: NicJA - openlog() & getlogin()??"
161 #if !defined(__AROS__)
162 openlog(tag ? tag : getlogin(), logflags, 0);
163 #else
164 //openlog(tag, logflags, 0);
165 #endif
166 (void) fclose(stdout);
168 /* log input line if appropriate */
169 if (argc > 0) {
170 char *p, *endp;
171 size_t len;
173 for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) {
174 len = strlen(*argv);
175 if (p + len > endp && p > buf) {
176 logmessage(pri, host, buf);
177 p = buf;
179 if (len > sizeof(buf) - 1)
180 logmessage(pri, host, *argv++);
181 else {
182 if (p != buf)
183 *p++ = ' ';
184 bcopy(*argv++, p, len);
185 *(p += len) = '\0';
188 if (p != buf)
189 logmessage(pri, host, buf);
190 } else
191 while (fgets(buf, sizeof(buf), stdin) != NULL)
192 logmessage(pri, host, buf);
193 exit(0);
197 * Send the message to syslog, either on the local host, or on a remote host
199 void
200 logmessage(int pri, char *host, char *buf)
202 static struct socks *socks;
203 static int nsock = 0;
204 struct addrinfo hints, *res, *r;
205 char *line;
206 int maxs, len, sock, error, i, lsent;
208 if (host == NULL) {
209 D(fprintf(stderr, "Logging text: %s\n", buf);)
210 syslog(pri, "%s", buf);
211 return;
214 if (nsock <= 0) { /* set up socket stuff */
215 /* resolve hostname */
216 memset(&hints, 0, sizeof(hints));
217 hints.ai_family = family;
218 hints.ai_socktype = SOCK_DGRAM;
219 error = getaddrinfo(host, "syslog", &hints, &res);
220 if (error == EAI_SERVICE) {
221 #warning "TODO: NicJA - We dont have warnx()"
222 #if !defined(__AROS__)
223 warnx("syslog/udp: unknown service"); /* not fatal */
224 #endif
225 error = getaddrinfo(host, "514", &hints, &res);
227 if (error)
229 #warning "TODO: NicJA - We dont have errx()"
230 #if !defined(__AROS__)
231 errx(1, "%s: %s", gai_strerror(error), host);
232 #endif
234 /* count max number of sockets we may open */
235 for (maxs = 0, r = res; r; r = r->ai_next, maxs++);
236 socks = malloc(maxs * sizeof(struct socks));
237 if (!socks)
239 #warning "TODO: NicJA - We dont have errx()"
240 #if !defined(__AROS__)
241 errx(1, "couldn't allocate memory for sockets");
242 #endif
245 for (r = res; r; r = r->ai_next) {
246 sock = socket(r->ai_family, r->ai_socktype,
247 r->ai_protocol);
248 if (sock < 0)
249 continue;
250 memcpy(&socks[nsock].addr, r->ai_addr, r->ai_addrlen);
251 socks[nsock].addrlen = r->ai_addrlen;
252 socks[nsock++].sock = sock;
254 freeaddrinfo(res);
255 if (nsock <= 0)
257 #warning "TODO: NicJA - We dont have errx()"
258 #if !defined(__AROS__)
259 errx(1, "socket");
260 #endif
264 #if defined(__AROS__)
265 char line_tmp[256];
266 sprintf(line_tmp, "<%d>%s", pri, buf);
267 len = strlen(line_tmp + 1);
268 line = line_tmp;
269 if (len > 0)
270 #else
271 if ((len = asprintf(&line, "<%d>%s", pri, buf)) == -1)
272 #endif
274 #warning "TODO: NicJA - We dont have errx()"
275 #if !defined(__AROS__)
276 errx(1, "asprintf");
277 #endif
280 lsent = -1;
281 for (i = 0; i < nsock; ++i) {
282 lsent = sendto(socks[i].sock, line, len, 0,
283 (struct sockaddr *)&socks[i].addr,
284 socks[i].addrlen);
285 if (lsent == len && !send_to_all)
286 break;
288 if (lsent != len) {
289 if (lsent == -1)
291 #warning "TODO: NicJA - We dont have warn()"
292 #if !defined(__AROS__)
293 warn ("sendto");
294 #endif
296 else
298 #warning "TODO: NicJA - We dont have warnx()"
299 #if !defined(__AROS__)
300 warnx ("sendto: short send - %d bytes", lsent);
301 #endif
305 free(line);
309 * Decode a symbolic name to a numeric value
312 pencode(char *s)
314 char *save;
315 int fac, lev;
317 for (save = s; *s && *s != '.'; ++s);
318 if (*s) {
319 *s = '\0';
320 fac = decode(save, facilitynames);
321 if (fac < 0)
323 #warning "TODO: NicJA - We dont have errx()"
324 #if !defined(__AROS__)
325 errx(1, "unknown facility name: %s", save);
326 #endif
328 *s++ = '.';
330 else {
331 fac = 0;
332 s = save;
334 lev = decode(s, prioritynames);
335 if (lev < 0)
337 #warning "TODO: NicJA - We dont have errx()"
338 #if !defined(__AROS__)
339 errx(1, "unknown priority name: %s", save);
340 #endif
342 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
346 decode(char *name, CODE *codetab)
348 CODE *c;
350 if (isdigit(*name))
351 return (atoi(name));
353 for (c = codetab; c->c_name; c++)
354 if (!strcasecmp(name, c->c_name))
355 return (c->c_val);
357 return (-1);
360 static void
361 usage(void)
363 (void)fprintf(stderr, "usage: %s\n",
364 "logger [-46Ais] [-f file] [-h host] [-p pri] [-t tag] [message ...]"
366 exit(1);