xref: /haiku/src/bin/logger.cpp (revision bc3955fea5b07e2e94a27fc05e4bb58fe6f0319b)
1 /*
2  * Copyright 2006-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <SupportDefs.h>
8 
9 #include <pwd.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <syslog.h>
14 #include <unistd.h>
15 
16 
17 #define DEFAULT_PRIORITY LOG_DEBUG
18 #define DEFAULT_FACILITY LOG_USER
19 
20 
21 extern const char *__progname;
22 static const char *sProgramName = __progname;
23 
24 
25 struct mapping {
26 	const char*	name;
27 	int			value;
28 };
29 
30 static mapping sPriorities[] = {
31 	{ "emerg",		LOG_EMERG },
32 	{ "panic",		LOG_PANIC },
33 	{ "alert",		LOG_ALERT },
34 	{ "critical",	LOG_CRIT },
35 	{ "crit",		LOG_CRIT },
36 	{ "error",		LOG_ERR },
37 	{ "err",		LOG_ERR },
38 	{ "warning", 	LOG_WARNING },
39 	{ "warn",		LOG_WARNING },
40 	{ "notice",		LOG_NOTICE },
41 	{ "info",		LOG_INFO },
42 	{ "debug",		LOG_DEBUG },
43 	{ NULL,			DEFAULT_PRIORITY },
44 };
45 
46 static mapping sFacilities[] = {
47 	{ "kernel",		LOG_KERN },
48 	{ "kern",		LOG_KERN },
49 	{ "user",		LOG_USER },
50 	{ "mail",		LOG_MAIL },
51 	{ "daemon",		LOG_DAEMON },
52 	{ "auth",		LOG_AUTH },
53 	{ "security",	LOG_AUTH },
54 	{ "syslog",		LOG_SYSLOG },
55 	{ "lpr",		LOG_LPR },
56 	{ "news",		LOG_NEWS },
57 	{ "uucp",		LOG_UUCP },
58 	{ "cron",		LOG_CRON },
59 	{ "authpriv",	LOG_AUTHPRIV },
60 	{ NULL,			DEFAULT_FACILITY },
61 };
62 
63 
64 static int
65 lookup_mapping(struct mapping* mappings, const char *string)
66 {
67 	int32 i;
68 	for (i = 0; mappings[i].name != NULL; i++) {
69 		if (!strcasecmp(string, mappings[i].name))
70 			break;
71 	}
72 
73 	return mappings[i].value;
74 }
75 
76 
77 static int
78 get_facility(const char *option)
79 {
80 	char facility[256];
81 	strlcpy(facility, option, sizeof(facility));
82 
83 	char *end = strchr(facility, '.');
84 	if (end == NULL) {
85 		// there is no facility specified
86 		return DEFAULT_FACILITY;
87 	}
88 
89 	end[0] = '\0';
90 
91 	return lookup_mapping(sFacilities, facility);
92 }
93 
94 
95 static int
96 get_priority(const char *option)
97 {
98 	char *priority = strchr(option, '.');
99 	if (priority == NULL) {
100 		// there is no facility specified
101 		return DEFAULT_PRIORITY;
102 	}
103 
104 	return lookup_mapping(sPriorities, ++priority);
105 }
106 
107 
108 static void
109 usage(void)
110 {
111 	fprintf(stderr, "usage: %s [-i] [-t <tag>] [-p <[facility.]priority>] "
112 			"<message>\n\n"
113 		"Sends a message to the system logging facility.\n"
114 		"If <message> is omitted, the message is read from stdin.\n\n"
115 		"   -i\tAdds the team ID to the log.\n"
116 		"   -t\tSpecifies the tag under which this message is posted.\n"
117 		"   -p\tSets the facility and priority this is logged under.\n"
118 		"    \t<facility> can be one of:\n"
119 		"\t\tkern, user, mail, daemon, auth, syslog, lpr, news,\n"
120 		"\t\tuucp, cron, authpriv\n"
121 		"    \t<priority> can be one of:\n"
122 		"\t\tdebug, info, notice, warning, warn, error, err,\n"
123 		"\t\tcritical, crit,alert, panic, emerg.\n", sProgramName);
124 
125 	exit(-1);
126 }
127 
128 
129 int
130 main(int argc, char **argv)
131 {
132 	struct passwd* passwd = getpwuid(geteuid());
133 	const char* tag = NULL;
134 	int facility = DEFAULT_FACILITY;
135 	int priority = DEFAULT_PRIORITY;
136 	int options = 0;
137 
138 	// read arguments
139 
140 	int option;
141 	while ((option = getopt(argc, argv, "it:p:")) != -1) {
142 		switch (option) {
143 		    case 'i':	// log team ID
144 				options |= LOG_PID;
145 				break;
146 
147 		    case 't':	// tag
148 				tag = optarg;
149 				break;
150 
151 		    case 'p':	// facility/priority
152 				facility = get_facility(optarg);
153 				priority = get_priority(optarg);
154 				break;
155 
156 		    default:
157 				usage();
158 				break;
159 		}
160 	}
161 
162 	if (tag == NULL && passwd != NULL)
163 		tag = passwd->pw_name;
164 
165 	argc -= optind;
166 	argv = &argv[optind];
167 
168 	openlog(tag, options, facility);
169 
170 	if (argc > 0) {
171 		// take message from arguments
172 
173 		char* buffer = NULL;
174 		int32 length = 0;
175 
176 		for (int32 i = 0; i < argc; i++) {
177 			int32 newLength = length + strlen(argv[i]) + 1;
178 
179 			buffer = (char *)realloc(buffer, newLength + 1);
180 			if (buffer == NULL) {
181 				fprintf(stderr, "%s: out of memory\n", sProgramName);
182 				return -1;
183 			}
184 
185 			strcpy(buffer + length, argv[i]);
186 			length = newLength;
187 
188 			buffer[length - 1] = ' ';
189 		}
190 
191 		if (length > 1 && buffer[length - 2] != '\n') {
192 			buffer[length - 1] = '\n';
193 			buffer[length] = '\0';
194 		} else
195 			buffer[length - 1] = '\0';
196 
197 		syslog(priority, "%s", buffer);
198 		free(buffer);
199 	} else {
200 		// read messages from stdin
201 
202 		char buffer[65536];
203 		while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
204 			syslog(priority, "%s", buffer);
205 		}
206 	}
207 
208 	closelog();
209 	return 0;
210 }
211 
212