fiss

Friedel's Initialization and Service Supervision
Log | Files | Refs | LICENSE

vlogger.c (4315B)


      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 
     16 const char* current_prog(void) {
     17 	return "vlogger";
     18 }
     19 
     20 static char pwd[PATH_MAX];
     21 
     22 struct ident {
     23 	const char* name;
     24 	int         value;
     25 };
     26 
     27 struct 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 
     42 struct 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 
     67 static 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 
     87 int 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 }