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