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 }