unix/fiss

src/vlogger/vlogger.c in master
Repositories | Summary | Log | Files | LICENSE

vlogger.c (4315B) download


  1
  2#include "../fsvs/message.h"
  3#include "config.h"
  4#include "util.h"
  5
  6#include <errno.h>
  7#include <libgen.h>
  8#include <limits.h>
  9#include <stdbool.h>
 10#include <stdlib.h>
 11#include <string.h>
 12#include <sys/syslog.h>
 13#include <unistd.h>
 14
 15
 16const char* current_prog(void) {
 17	return "vlogger";
 18}
 19
 20static char pwd[PATH_MAX];
 21
 22struct ident {
 23	const char* name;
 24	int         value;
 25};
 26
 27struct ident prioritynames[] = {
 28	{ "alert", LOG_ALERT },
 29	{ "crit", LOG_CRIT },
 30	{ "debug", LOG_DEBUG },
 31	{ "emerg", LOG_EMERG },
 32	{ "err", LOG_ERR },
 33	{ "error", LOG_ERR },
 34	{ "info", LOG_INFO },
 35	{ "notice", LOG_NOTICE },
 36	{ "panic", LOG_EMERG },
 37	{ "warn", LOG_WARNING },
 38	{ "warning", LOG_WARNING },
 39	{ 0, -1 }
 40};
 41
 42struct ident facilitynames[] = {
 43	{ "auth", LOG_AUTH },
 44	{ "authpriv", LOG_AUTHPRIV },
 45	{ "cron", LOG_CRON },
 46	{ "daemon", LOG_DAEMON },
 47	{ "ftp", LOG_FTP },
 48	{ "kern", LOG_KERN },
 49	{ "lpr", LOG_LPR },
 50	{ "mail", LOG_MAIL },
 51	{ "news", LOG_NEWS },
 52	{ "security", LOG_AUTH },
 53	{ "syslog", LOG_SYSLOG },
 54	{ "user", LOG_USER },
 55	{ "uucp", LOG_UUCP },
 56	{ "local0", LOG_LOCAL0 },
 57	{ "local1", LOG_LOCAL1 },
 58	{ "local2", LOG_LOCAL2 },
 59	{ "local3", LOG_LOCAL3 },
 60	{ "local4", LOG_LOCAL4 },
 61	{ "local5", LOG_LOCAL5 },
 62	{ "local6", LOG_LOCAL6 },
 63	{ "local7", LOG_LOCAL7 },
 64	{ 0, -1 }
 65};
 66
 67static void strpriority(char* facil_str, int* facility, int* level) {
 68	char*         prio_str = NULL;
 69	struct ident* ident;
 70
 71	if ((prio_str = strchr(facil_str, '.'))) {
 72		*prio_str = '\0';
 73		prio_str++;
 74		for (ident = prioritynames; ident->name; ident++) {
 75			if (streq(ident->name, prio_str))
 76				*level = ident->value;
 77		}
 78	}
 79	if (*facil_str) {
 80		for (ident = facilitynames; ident->name; ident++) {
 81			if (streq(ident->name, facil_str))
 82				*facility = ident->value;
 83		}
 84	}
 85}
 86
 87int main(int argc, char* argv[]) {
 88	char  buf[SV_VLOGGER_BUFFER];
 89	char *p, *e, *argv0;
 90	char* tag = NULL;
 91	int   c;
 92	bool  Sflag    = false;
 93	int   logflags = 0;
 94	int   facility = LOG_USER;
 95	int   level    = LOG_NOTICE;
 96
 97	argv0 = *argv;
 98
 99	if (streq(argv0, "./run")) {
100		// if running as a service, update facility and tag
101		p = getcwd(pwd, sizeof(pwd));
102		if (p != NULL && *pwd == '/') {
103			if (*(p = pwd + (strlen(pwd) - 1)) == '/')
104				*p = '\0';
105			if ((p = strrchr(pwd, '/')) && strncmp(p + 1, "log", 3) == 0 &&
106			    (*p = '\0', (p = strrchr(pwd, '/'))) && (*(p + 1) != '\0')) {
107				tag      = p + 1;
108				facility = LOG_DAEMON;
109				level    = LOG_NOTICE;
110			}
111		}
112	} else if (streq(basename(argv0), "logger")) {
113		/* behave just like logger(1) and only use syslog */
114		Sflag = true;
115	}
116
117	while ((c = getopt(argc, argv, "f:ip:Sst:")) != -1)
118		switch (c) {
119			case 'f':
120				if (freopen(optarg, "r", stdin) == NULL) {
121					print_errno("error: unable to reopen %s: %s\n", optarg);
122					return 1;
123				}
124				break;
125			case 'i':
126				logflags |= LOG_PID;
127				break;
128			case 'p':
129				strpriority(optarg, &facility, &level);
130				break;
131			case 'S':
132				Sflag = true;
133				break;
134			case 's':
135				logflags |= LOG_PERROR;
136				break;
137			case 't':
138				tag = optarg;
139				break;
140			default:
141				print_usage_exit(PROG_VLOGGER, 1);
142		}
143	argc -= optind;
144	argv += optind;
145
146	if (argc > 0)
147		Sflag = true;
148
149	if (!Sflag && access("/etc/vlogger", X_OK) != -1) {
150		struct ident* ident;
151		const char *  sfacility = "", *slevel = "";
152		for (ident = prioritynames; ident->name; ident++) {
153			if (ident->value == level)
154				slevel = ident->name;
155		}
156		for (ident = facilitynames; ident->name; ident++) {
157			if (ident->value == facility)
158				sfacility = ident->name;
159		}
160		execl("/etc/vlogger", argv0, tag ? tag : "", slevel, sfacility, NULL);
161		fprint(1, "error: unable to exec /etc/vlogger: %r\n");
162		exit(1);
163	}
164
165	openlog(tag ? tag : getlogin(), logflags, facility);
166
167	if (argc > 0) {
168		size_t len;
169		p  = buf;
170		*p = '\0';
171		e  = buf + sizeof(buf) - 2;
172		while (*argv) {
173			len = strlen(*argv);
174			if (p + len > e && p > buf) {
175				syslog(level | facility, "%s", buf);
176				p  = buf;
177				*p = '\0';
178			}
179			if (len > sizeof(buf) - 1) {
180				syslog(level | facility, "%s", *argv++);
181			} else {
182				if (p != buf) {
183					*p++ = ' ';
184					*p   = '\0';
185				}
186				strncat(p, *argv++, e - p);
187				p += len;
188			}
189		}
190		if (p != buf)
191			syslog(level | facility, "%s", buf);
192		return 0;
193	}
194
195	while (fgets(buf, sizeof(buf), stdin) != NULL)
196		syslog(level | facility, "%s", buf);
197
198	return 0;
199}