]> git.ipfire.org Git - thirdparty/util-linux.git/blame_incremental - misc-utils/logger.c
lib/monotonic: fix compiler warnings
[thirdparty/util-linux.git] / misc-utils / logger.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
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.
20 *
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.
32 *
33 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
34 * - added Native Language Support
35 * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
36 * - fixed strerr(errno) in gettext calls
37 */
38
39#include <errno.h>
40#include <limits.h>
41#include <unistd.h>
42#include <stdlib.h>
43#include <sys/time.h>
44#include <stdio.h>
45#include <ctype.h>
46#include <string.h>
47#include <sys/types.h>
48#include <sys/socket.h>
49#include <sys/un.h>
50#include <arpa/inet.h>
51#include <netdb.h>
52#include <getopt.h>
53#include <pwd.h>
54
55#include "all-io.h"
56#include "c.h"
57#include "closestream.h"
58#include "nls.h"
59#include "pathnames.h"
60#include "strutils.h"
61#include "xalloc.h"
62
63#define SYSLOG_NAMES
64#include <syslog.h>
65
66#ifdef HAVE_LIBSYSTEMD
67# include <systemd/sd-daemon.h>
68# include <systemd/sd-journal.h>
69#endif
70
71#ifdef HAVE_SYS_TIMEX_H
72# include <sys/timex.h>
73#endif
74
75enum {
76 TYPE_UDP = (1 << 1),
77 TYPE_TCP = (1 << 2),
78 ALL_TYPES = TYPE_UDP | TYPE_TCP
79};
80
81enum {
82 AF_UNIX_ERRORS_OFF = 0,
83 AF_UNIX_ERRORS_ON,
84 AF_UNIX_ERRORS_AUTO
85};
86
87enum {
88 OPT_PRIO_PREFIX = CHAR_MAX + 1,
89 OPT_JOURNALD,
90 OPT_RFC3164,
91 OPT_RFC5424,
92 OPT_SOCKET_ERRORS,
93 OPT_ID
94};
95
96struct logger_ctl {
97 int fd;
98 int pri;
99 pid_t pid; /* zero when unwanted */
100 char *tag;
101 char *unix_socket;
102 char *server;
103 char *port;
104 int socket_type;
105 void (*syslogfp)(const struct logger_ctl *ctl, const char *msg);
106 unsigned int
107 unix_socket_errors:1, /* whether to report or not errors */
108 prio_prefix:1, /* read priority from intput */
109 stderr_printout:1, /* output message to stderr */
110 rfc5424_time:1, /* include time stamp */
111 rfc5424_tq:1, /* include time quality markup */
112 rfc5424_host:1; /* include hostname */
113};
114
115static char *get_prio_prefix(char *msg, int *prio)
116{
117 int p;
118 char *end = NULL;
119 int facility = *prio & LOG_FACMASK;
120
121 errno = 0;
122 p = strtoul(msg + 1, &end, 10);
123
124 if (errno || !end || end == msg + 1 || end[0] != '>')
125 return msg;
126
127 if (p & LOG_FACMASK)
128 facility = p & LOG_FACMASK;
129
130 *prio = facility | (p & LOG_PRIMASK);
131 return end + 1;
132}
133
134static int decode(const char *name, CODE *codetab)
135{
136 register CODE *c;
137
138 if (name == NULL || *name == '\0')
139 return -1;
140 if (isdigit(*name)) {
141 int num;
142 char *end = NULL;
143
144 num = strtol(name, &end, 10);
145 if (errno || name == end || (end && *end))
146 return -1;
147 for (c = codetab; c->c_name; c++)
148 if (num == c->c_val)
149 return num;
150 return -1;
151 }
152 for (c = codetab; c->c_name; c++)
153 if (!strcasecmp(name, c->c_name))
154 return (c->c_val);
155
156 return -1;
157}
158
159static int pencode(char *s)
160{
161 int facility, level;
162 char *separator;
163
164 separator = strchr(s, '.');
165 if (separator) {
166 *separator = '\0';
167 facility = decode(s, facilitynames);
168 if (facility < 0)
169 errx(EXIT_FAILURE, _("unknown facility name: %s"), s);
170 s = ++separator;
171 } else
172 facility = LOG_USER;
173 level = decode(s, prioritynames);
174 if (level < 0)
175 errx(EXIT_FAILURE, _("unknown priority name: %s"), s);
176 return ((level & LOG_PRIMASK) | (facility & LOG_FACMASK));
177}
178
179static int unix_socket(struct logger_ctl *ctl, const char *path, const int socket_type)
180{
181 int fd, i;
182 static struct sockaddr_un s_addr; /* AF_UNIX address of local logger */
183
184 if (strlen(path) >= sizeof(s_addr.sun_path))
185 errx(EXIT_FAILURE, _("openlog %s: pathname too long"), path);
186
187 s_addr.sun_family = AF_UNIX;
188 strcpy(s_addr.sun_path, path);
189
190 for (i = 2; i; i--) {
191 int st = -1;
192
193 if (i == 2 && socket_type & TYPE_UDP)
194 st = SOCK_DGRAM;
195 if (i == 1 && socket_type & TYPE_TCP)
196 st = SOCK_STREAM;
197 if (st == -1 || (fd = socket(AF_UNIX, st, 0)) == -1)
198 continue;
199 if (connect(fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1) {
200 close(fd);
201 continue;
202 }
203 break;
204 }
205
206 if (i == 0) {
207 if (ctl->unix_socket_errors)
208 err(EXIT_FAILURE, _("socket %s"), path);
209 else
210 /* See --socket-errors manual page entry for
211 * explanation of this strange exit. */
212 exit(EXIT_SUCCESS);
213 }
214 return fd;
215}
216
217static int inet_socket(const char *servername, const char *port,
218 const int socket_type)
219{
220 int fd, errcode, i;
221 struct addrinfo hints, *res;
222 const char *p = port;
223
224 for (i = 2; i; i--) {
225 memset(&hints, 0, sizeof(hints));
226 if (i == 2 && socket_type & TYPE_UDP) {
227 hints.ai_socktype = SOCK_DGRAM;
228 if (port == NULL)
229 p = "syslog";
230 }
231 if (i == 1 && socket_type & TYPE_TCP) {
232 hints.ai_socktype = SOCK_STREAM;
233 if (port == NULL)
234 p = "syslog-conn";
235 }
236 if (hints.ai_socktype == 0)
237 continue;
238 hints.ai_family = AF_UNSPEC;
239 errcode = getaddrinfo(servername, p, &hints, &res);
240 if (errcode != 0)
241 errx(EXIT_FAILURE, _("failed to resolve name %s port %s: %s"),
242 servername, p, gai_strerror(errcode));
243 if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
244 freeaddrinfo(res);
245 continue;
246 }
247 if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) {
248 freeaddrinfo(res);
249 close(fd);
250 continue;
251 }
252
253 freeaddrinfo(res);
254 break;
255 }
256
257 if (i == 0)
258 errx(EXIT_FAILURE, _("failed to connect to %s port %s"), servername, p);
259
260 return fd;
261}
262
263#ifdef HAVE_LIBSYSTEMD
264static int journald_entry(FILE *fp)
265{
266 struct iovec *iovec;
267 char *buf = NULL;
268 ssize_t sz;
269 int n, lines, vectors = 8, ret;
270 size_t dummy = 0;
271
272 iovec = xmalloc(vectors * sizeof(struct iovec));
273 for (lines = 0; /* nothing */ ; lines++) {
274 buf = NULL;
275 sz = getline(&buf, &dummy, fp);
276 if (sz == -1)
277 break;
278 if (0 < sz && buf[sz - 1] == '\n') {
279 sz--;
280 buf[sz] = '\0';
281 }
282 if (lines == vectors) {
283 vectors *= 2;
284 if (IOV_MAX < vectors)
285 errx(EXIT_FAILURE, _("maximum input lines (%d) exceeded"), IOV_MAX);
286 iovec = xrealloc(iovec, vectors * sizeof(struct iovec));
287 }
288 iovec[lines].iov_base = buf;
289 iovec[lines].iov_len = sz;
290 }
291 ret = sd_journal_sendv(iovec, lines);
292 for (n = 0; n < lines; n++)
293 free(iovec[n].iov_base);
294 free(iovec);
295 return ret;
296}
297#endif
298
299static char *xgetlogin(void)
300{
301 char *cp;
302 struct passwd *pw;
303
304 if (!(cp = getlogin()) || !*cp)
305 cp = (pw = getpwuid(geteuid()))? pw->pw_name : "<someone>";
306 return cp;
307}
308
309static void syslog_rfc3164(const struct logger_ctl *ctl, const char *msg)
310{
311 char *buf, pid[30], *cp, *tp, *hostname, *dot;
312 time_t now;
313 int len;
314
315 *pid = '\0';
316 if (ctl->fd < 0)
317 return;
318 if (ctl->pid)
319 snprintf(pid, sizeof(pid), "[%d]", ctl->pid);
320
321 cp = ctl->tag ? ctl->tag : xgetlogin();
322
323 hostname = xgethostname();
324 dot = strchr(hostname, '.');
325 if (dot)
326 *dot = '\0';
327
328 time(&now);
329 tp = ctime(&now) + 4;
330
331 len = xasprintf(&buf, "<%d>%.15s %s %.200s%s: %.400s",
332 ctl->pri, tp, hostname, cp, pid, msg);
333
334 if (write_all(ctl->fd, buf, len) < 0)
335 warn(_("write failed"));
336 if (ctl->stderr_printout)
337 fprintf(stderr, "%s\n", buf);
338
339 free(hostname);
340 free(buf);
341}
342
343static void syslog_rfc5424(const struct logger_ctl *ctl, const char *msg)
344{
345 char *buf, *tag = NULL, *hostname = NULL;
346 char pid[32], time[64], timeq[80];
347#ifdef HAVE_SYS_TIMEX_H
348 struct ntptimeval ntptv;
349#endif
350 struct timeval tv;
351 struct tm *tm;
352 int len;
353
354 *pid = *time = *timeq = '\0';
355 if (ctl->fd < 0)
356 return;
357
358 if (ctl->rfc5424_time) {
359 gettimeofday(&tv, NULL);
360 if ((tm = localtime(&tv.tv_sec)) != NULL) {
361 char fmt[64];
362
363 const size_t i = strftime(fmt, sizeof(fmt),
364 " %Y-%m-%dT%H:%M:%S.%%06u%z ", tm);
365 /* patch TZ info to comply with RFC3339 (we left SP at end) */
366 fmt[i-1] = fmt[i-2];
367 fmt[i-2] = fmt[i-3];
368 fmt[i-3] = ':';
369 snprintf(time, sizeof(time), fmt, tv.tv_usec);
370 } else
371 err(EXIT_FAILURE, _("localtime() failed"));
372 }
373
374 if (ctl->rfc5424_host) {
375 hostname = xgethostname();
376 /* Arbitrary looking 'if (var < strlen()) checks originate from
377 * RFC 5424 - 6 Syslog Message Format definition. */
378 if (255 < strlen(hostname))
379 errx(EXIT_FAILURE, _("hostname '%s' is too long"),
380 hostname);
381 }
382
383 tag = ctl->tag ? ctl->tag : xgetlogin();
384
385 if (48 < strlen(tag))
386 errx(EXIT_FAILURE, _("tag '%s' is too long"), tag);
387
388 if (ctl->pid)
389 snprintf(pid, sizeof(pid), " %d", ctl->pid);
390
391 if (ctl->rfc5424_tq) {
392#ifdef HAVE_SYS_TIMEX_H
393 if (ntp_gettime(&ntptv) == TIME_OK)
394 snprintf(timeq, sizeof(timeq),
395 " [timeQuality tzKnown=\"1\" isSynced=\"1\" syncAccuracy=\"%ld\"]",
396 ntptv.maxerror);
397 else
398#endif
399 snprintf(timeq, sizeof(timeq),
400 " [timeQuality tzKnown=\"1\" isSynced=\"0\"]");
401 }
402
403 len = xasprintf(&buf, "<%d>1%s%s%s %s -%s%s %s", ctl->pri, time,
404 hostname ? " " : "",
405 hostname ? hostname : "",
406 tag, pid, timeq, msg);
407
408 if (write_all(ctl->fd, buf, len) < 0)
409 warn(_("write failed"));
410
411 if (ctl->stderr_printout)
412 fprintf(stderr, "%s\n", buf);
413
414 free(hostname);
415 free(buf);
416}
417
418static void parse_rfc5424_flags(struct logger_ctl *ctl, char *optarg)
419{
420 char *in, *tok;
421
422 in = optarg;
423 while ((tok = strtok(in, ","))) {
424 in = NULL;
425 if (!strcmp(tok, "notime")) {
426 ctl->rfc5424_time = 0;
427 ctl->rfc5424_tq = 0;
428 } else if (!strcmp(tok, "notq"))
429 ctl->rfc5424_tq = 0;
430 else if (!strcmp(tok, "nohost"))
431 ctl->rfc5424_host = 0;
432 else
433 warnx(_("ignoring unknown option argument: %s"), tok);
434 }
435}
436
437static int parse_unix_socket_errors_flags(char *optarg)
438{
439 if (!strcmp(optarg, "off"))
440 return AF_UNIX_ERRORS_OFF;
441 if (!strcmp(optarg, "on"))
442 return AF_UNIX_ERRORS_ON;
443 if (!strcmp(optarg, "auto"))
444 return AF_UNIX_ERRORS_AUTO;
445 warnx(_("invalid argument: %s: using automatic errors"), optarg);
446 return AF_UNIX_ERRORS_AUTO;
447}
448
449static void syslog_local(const struct logger_ctl *ctl, const char *msg)
450{
451 char *buf, *tag;
452 char time[32], pid[32];
453 struct timeval tv;
454 struct tm *tm;
455 int len;
456
457 gettimeofday(&tv, NULL);
458 tm = localtime(&tv.tv_sec);
459 strftime(time, sizeof(time), "%h %e %T", tm);
460
461 tag = ctl->tag ? ctl->tag : program_invocation_short_name;
462
463 if (ctl->pid)
464 snprintf(pid, sizeof(pid), "[%d]", ctl->pid);
465 else
466 pid[0] = '\0';
467
468 len = xasprintf(&buf, "<%d>%s %s%s: %s", ctl->pri, time, tag, pid, msg);
469 if (write_all(ctl->fd, buf, len) < 0)
470 warn(_("write failed"));
471 if (ctl->stderr_printout)
472 fprintf(stderr, "%s\n", buf);
473 free(buf);
474}
475
476static void logger_open(struct logger_ctl *ctl)
477{
478 if (ctl->server) {
479 ctl->fd = inet_socket(ctl->server, ctl->port, ctl->socket_type);
480 if (!ctl->syslogfp)
481 ctl->syslogfp = syslog_rfc5424;
482 return;
483 }
484 if (ctl->unix_socket) {
485 ctl->fd = unix_socket(ctl, ctl->unix_socket, ctl->socket_type);
486 if (!ctl->syslogfp)
487 ctl->syslogfp = syslog_rfc5424;
488 return;
489 }
490 ctl->fd = unix_socket(ctl, _PATH_DEVLOG, ctl->socket_type);
491 ctl->syslogfp = syslog_local;
492}
493
494static void logger_command_line(const struct logger_ctl *ctl, char **argv)
495{
496 char buf[4096];
497 char *p = buf;
498 const char *endp = buf + sizeof(buf) - 2;
499 size_t len;
500
501 while (*argv) {
502 len = strlen(*argv);
503 if (endp < p + len && p != buf) {
504 ctl->syslogfp(ctl, buf);
505 p = buf;
506 }
507 if (sizeof(buf) - 1 < len) {
508 ctl->syslogfp(ctl, *argv++);
509 continue;
510 }
511 if (p != buf)
512 *p++ = ' ';
513 memmove(p, *argv++, len);
514 *(p += len) = '\0';
515 }
516 if (p != buf)
517 ctl->syslogfp(ctl, buf);
518}
519
520static void logger_stdin(struct logger_ctl *ctl)
521{
522 char *msg;
523 int default_priority = ctl->pri;
524 char buf[1024];
525
526 while (fgets(buf, sizeof(buf), stdin) != NULL) {
527 int len = strlen(buf);
528
529 /* some glibc versions are buggy, they add an additional
530 * newline which is removed here. */
531 if (0 < len && buf[len - 1] == '\n')
532 buf[len - 1] = '\0';
533 msg = buf;
534 ctl->pri = default_priority;
535 if (ctl->prio_prefix && msg[0] == '<')
536 msg = get_prio_prefix(msg, &ctl->pri);
537 ctl->syslogfp(ctl, msg);
538 }
539}
540
541static void logger_close(const struct logger_ctl *ctl)
542{
543 if (close(ctl->fd) != 0)
544 err(EXIT_FAILURE, _("close failed"));
545}
546
547static void __attribute__ ((__noreturn__)) usage(FILE *out)
548{
549 fputs(USAGE_HEADER, out);
550 fprintf(out, _(" %s [options] [<message>]\n"), program_invocation_short_name);
551
552 fputs(USAGE_SEPARATOR, out);
553 fputs(_("Enter messages into the system log.\n"), out);
554
555 fputs(USAGE_OPTIONS, out);
556 fputs(_(" -i log the logger command's PID\n"), out);
557 fputs(_(" --id[=<id>] log the given <id>, or otherwise the PID\n"), out);
558 fputs(_(" -f, --file <file> log the contents of this file\n"), out);
559 fputs(_(" -p, --priority <prio> mark given message with this priority\n"), out);
560 fputs(_(" --prio-prefix look for a prefix on every line read from stdin\n"), out);
561 fputs(_(" -s, --stderr output message to standard error as well\n"), out);
562 fputs(_(" -t, --tag <tag> mark every line with this tag\n"), out);
563 fputs(_(" -n, --server <name> write to this remote syslog server\n"), out);
564 fputs(_(" -P, --port <number> use this UDP port\n"), out);
565 fputs(_(" -T, --tcp use TCP only\n"), out);
566 fputs(_(" -d, --udp use UDP only\n"), out);
567 fputs(_(" --rfc3164 use the obsolete BSD syslog protocol\n"), out);
568 fputs(_(" --rfc5424[=<snip>] use the syslog protocol (the default);\n"
569 " <snip> can be notime, or notq, and/or nohost\n"), out);
570 fputs(_(" -u, --socket <socket> write to this Unix socket\n"), out);
571 fputs(_(" --socket-errors[=<on|off|auto>]\n"
572 " print connection errors when using Unix sockets\n"), out);
573#ifdef HAVE_LIBSYSTEMD
574 fputs(_(" --journald[=<file>] write journald entry\n"), out);
575#endif
576
577 fputs(USAGE_SEPARATOR, out);
578 fputs(USAGE_HELP, out);
579 fputs(USAGE_VERSION, out);
580 fprintf(out, USAGE_MAN_TAIL("logger(1)"));
581
582 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
583}
584
585/*
586 * logger -- read and log utility
587 *
588 * Reads from an input and arranges to write the result on the system
589 * log.
590 */
591int main(int argc, char **argv)
592{
593 struct logger_ctl ctl = {
594 .fd = -1,
595 .pid = 0,
596 .pri = LOG_NOTICE,
597 .prio_prefix = 0,
598 .tag = NULL,
599 .unix_socket = NULL,
600 .unix_socket_errors = 0,
601 .server = NULL,
602 .port = NULL,
603 .socket_type = ALL_TYPES,
604 .rfc5424_time = 1,
605 .rfc5424_tq = 1,
606 .rfc5424_host = 1,
607 };
608 int ch;
609 int stdout_reopened = 0;
610 int unix_socket_errors_mode = AF_UNIX_ERRORS_AUTO;
611#ifdef HAVE_LIBSYSTEMD
612 FILE *jfd = NULL;
613#endif
614 static const struct option longopts[] = {
615 { "id", optional_argument, 0, OPT_ID },
616 { "stderr", no_argument, 0, 's' },
617 { "file", required_argument, 0, 'f' },
618 { "priority", required_argument, 0, 'p' },
619 { "tag", required_argument, 0, 't' },
620 { "socket", required_argument, 0, 'u' },
621 { "socket-errors", required_argument, 0, OPT_SOCKET_ERRORS },
622 { "udp", no_argument, 0, 'd' },
623 { "tcp", no_argument, 0, 'T' },
624 { "server", required_argument, 0, 'n' },
625 { "port", required_argument, 0, 'P' },
626 { "version", no_argument, 0, 'V' },
627 { "help", no_argument, 0, 'h' },
628 { "prio-prefix", no_argument, 0, OPT_PRIO_PREFIX },
629 { "rfc3164", no_argument, 0, OPT_RFC3164 },
630 { "rfc5424", optional_argument, 0, OPT_RFC5424 },
631#ifdef HAVE_LIBSYSTEMD
632 { "journald", optional_argument, 0, OPT_JOURNALD },
633#endif
634 { NULL, 0, 0, 0 }
635 };
636
637 setlocale(LC_ALL, "");
638 bindtextdomain(PACKAGE, LOCALEDIR);
639 textdomain(PACKAGE);
640 atexit(close_stdout);
641
642 while ((ch = getopt_long(argc, argv, "f:ip:st:u:dTn:P:Vh",
643 longopts, NULL)) != -1) {
644 switch (ch) {
645 case 'f': /* file to log */
646 if (freopen(optarg, "r", stdin) == NULL)
647 err(EXIT_FAILURE, _("file %s"), optarg);
648 stdout_reopened = 1;
649 break;
650 case 'i': /* log process id also */
651 ctl.pid = getpid();
652 break;
653 case OPT_ID:
654 if (optarg) {
655 const char *p = optarg;
656
657 if (*p == '=')
658 p++;
659 ctl.pid = strtoul_or_err(optarg, _("failed to parse id"));
660 } else
661 ctl.pid = getpid();
662 break;
663 case 'p': /* priority */
664 ctl.pri = pencode(optarg);
665 break;
666 case 's': /* log to standard error */
667 ctl.stderr_printout = 1;
668 break;
669 case 't': /* tag */
670 ctl.tag = optarg;
671 break;
672 case 'u': /* unix socket */
673 ctl.unix_socket = optarg;
674 break;
675 case 'd':
676 ctl.socket_type = TYPE_UDP;
677 break;
678 case 'T':
679 ctl.socket_type = TYPE_TCP;
680 break;
681 case 'n':
682 ctl.server = optarg;
683 break;
684 case 'P':
685 ctl.port = optarg;
686 break;
687 case 'V':
688 printf(UTIL_LINUX_VERSION);
689 exit(EXIT_SUCCESS);
690 case 'h':
691 usage(stdout);
692 case OPT_PRIO_PREFIX:
693 ctl.prio_prefix = 1;
694 break;
695 case OPT_RFC3164:
696 ctl.syslogfp = syslog_rfc3164;
697 break;
698 case OPT_RFC5424:
699 ctl.syslogfp = syslog_rfc5424;
700 if (optarg)
701 parse_rfc5424_flags(&ctl, optarg);
702 break;
703#ifdef HAVE_LIBSYSTEMD
704 case OPT_JOURNALD:
705 if (optarg) {
706 jfd = fopen(optarg, "r");
707 if (!jfd)
708 err(EXIT_FAILURE, _("cannot open %s"),
709 optarg);
710 } else
711 jfd = stdin;
712 break;
713#endif
714 case OPT_SOCKET_ERRORS:
715 unix_socket_errors_mode = parse_unix_socket_errors_flags(optarg);
716 break;
717 case '?':
718 default:
719 usage(stderr);
720 }
721 }
722 argc -= optind;
723 argv += optind;
724 if (stdout_reopened && argc)
725 warnx(_("--file <file> and <message> are mutually exclusive, message is ignored"));
726#ifdef HAVE_LIBSYSTEMD
727 if (jfd) {
728 int ret = journald_entry(jfd);
729 if (stdin != jfd)
730 fclose(jfd);
731 if (ret)
732 errx(EXIT_FAILURE, _("journald entry could not be written"));
733 return EXIT_SUCCESS;
734 }
735#endif
736 switch (unix_socket_errors_mode) {
737 case AF_UNIX_ERRORS_OFF:
738 ctl.unix_socket_errors = 0;
739 break;
740 case AF_UNIX_ERRORS_ON:
741 ctl.unix_socket_errors = 1;
742 break;
743 case AF_UNIX_ERRORS_AUTO:
744#ifdef HAVE_LIBSYSTEMD
745 ctl.unix_socket_errors = sd_booted();
746#else
747 ctl.unix_socket_errors = 0;
748#endif
749 break;
750 default:
751 abort();
752 }
753 logger_open(&ctl);
754 if (0 < argc)
755 logger_command_line(&ctl, argv);
756 else
757 /* Note. --file <arg> reopens stdin making the below
758 * function to be used for file inputs. */
759 logger_stdin(&ctl);
760 logger_close(&ctl);
761 return EXIT_SUCCESS;
762}