#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <syslog.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <limits.h>
#include <pwd.h>
#include <errno.h>
#define LOG_MARK (LOG_NFACILITIES << 3)
#define LOGGER_BUFLEN 1024
struct code {
char *c_name;
int c_val;
};
static struct code PriNames[] = {
"panic", LOG_EMERG,
"emerg", LOG_EMERG,
"alert", LOG_ALERT,
"crit", LOG_CRIT,
"err", LOG_ERR,
"error", LOG_ERR,
"warn", LOG_WARNING,
"warning", LOG_WARNING,
"notice", LOG_NOTICE,
"info", LOG_INFO,
"debug", LOG_DEBUG,
NULL, -1
};
static struct code FacNames[] = {
"kern", LOG_KERN,
"user", LOG_USER,
"mail", LOG_MAIL,
"daemon", LOG_DAEMON,
"auth", LOG_AUTH,
"security", LOG_AUTH,
"mark", LOG_MARK,
"syslog", LOG_SYSLOG,
"lpr", LOG_LPR,
"news", LOG_NEWS,
"uucp", LOG_UUCP,
"altcron", LOG_ALTCRON,
"authpriv", LOG_AUTHPRIV,
"ftp", LOG_FTP,
"ntp", LOG_NTP,
"audit", LOG_AUDIT,
"console", LOG_CONSOLE,
"cron", LOG_CRON,
"local0", LOG_LOCAL0,
"local1", LOG_LOCAL1,
"local2", LOG_LOCAL2,
"local3", LOG_LOCAL3,
"local4", LOG_LOCAL4,
"local5", LOG_LOCAL5,
"local6", LOG_LOCAL6,
"local7", LOG_LOCAL7,
NULL, -1
};
static int pencode(char *);
static int decode(char *, struct code *);
static void bailout(char *, char *);
static void usage(void);
int
main(int argc, char **argv)
{
char tmp[23];
char *tag = NULL;
char *infile = NULL;
char *buf = NULL;
size_t buflen;
int pri = LOG_NOTICE;
int logflags = 0;
int opt;
int pid_len = 0;
struct passwd *pw;
uid_t u;
char fmt_uid[16];
char *p, *endp;
size_t len;
ptrdiff_t offset = 0;
int status = 0;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
while ((opt = getopt(argc, argv, "it:p:f:")) != EOF)
switch (opt) {
case 't':
tag = optarg;
break;
case 'p':
pri = pencode(optarg);
break;
case 'i':
logflags |= LOG_PID;
pid_len = sprintf(tmp, "%ld", (long)getpid());
pid_len = (pid_len <= 0) ? 0 : pid_len +2;
break;
case 'f':
if (strcmp(optarg, "-") == 0)
break;
infile = optarg;
if (freopen(infile, "r", stdin) == NULL) {
(void) fprintf(stderr, gettext("logger: "));
perror(infile);
exit(1);
}
break;
default:
usage();
}
argc -= optind;
argv = &argv[optind];
if ((tag == NULL) && ((tag = getlogin()) == NULL)) {
u = getuid();
if ((pw = getpwuid(u)) == NULL) {
(void) sprintf(fmt_uid, "%u", u);
tag = fmt_uid;
} else
tag = pw->pw_name;
}
openlog(tag, logflags, 0);
(void) fclose(stdout);
if (argc > 0) {
int i;
len = 0;
for (i = 0; i < argc; i++) {
len += strlen(argv[i]) + 1;
}
if ((buf = malloc(len + 1)) == NULL) {
perror("logger");
exit(1);
}
buf[0] = '\0';
for (i = 0; i < argc; i++) {
if (i != 0) {
(void) strcat(buf, " ");
}
(void) strcat(buf, argv[i]);
}
#ifdef DEBUG
(void) fprintf(stderr, "len=%d, buf >%s<\n", len, buf);
#endif
syslog(pri, "%s", buf);
} else {
if ((buf = malloc(LOGGER_BUFLEN)) == NULL) {
perror("logger");
exit(1);
}
buflen = LOGGER_BUFLEN;
p = buf;
endp = buf + buflen;
offset = 0;
while (fgets(p, endp - p, stdin) != NULL) {
len = strlen(p);
if (p[len - 1] == '\n') {
#ifdef DEBUG
(void) fprintf(stderr,
"p-buf =%d, len=%d, buflen=%d, buf >%s<\n",
p-buf, len, buflen, buf);
#endif
syslog(pri, "%s", buf);
p = buf;
offset = 0;
} else if (len < endp - p - 1) {
p += len;
offset += len;
#ifdef DEBUG
(void) fprintf(stderr,
"p-buf=%d, len=%d, buflen=%d, buf >%s<\n",
p-buf, len, buflen, buf);
#endif
continue;
} else {
buflen += LOGGER_BUFLEN;
offset += len;
#ifdef DEBUG
(void) fprintf(stderr,
"Realloc endp-p=%d, len=%d, offset=%d, "
"buflen %d\n",
endp - p, len, offset, buflen);
#endif
if ((buf = realloc(buf, buflen)) == NULL) {
perror("logger");
exit(1);
}
p = buf + offset;
endp = buf + buflen;
}
}
if (feof(stdin)) {
if (p > buf) {
#ifdef DEBUG
(void) fprintf(stderr,
"(2) p-buf=%d, len=%d, buflen=%d, "
"buf >%s<\n",
p-buf, len, buflen, buf);
#endif
syslog(pri, "%s", buf);
}
} else {
perror("logger");
if (p > buf) {
*p = '\0';
syslog(pri, "%s", buf);
}
status = 1;
}
}
free(buf);
return (status);
}
static int
pencode(char *s)
{
char *p;
int lev;
int fac = 0;
for (p = s; *s && *s != '.'; s++)
;
if (*s) {
*s = '\0';
fac = decode(p, FacNames);
if (fac < 0)
bailout("unknown facility name: ", p);
*s++ = '.';
} else
s = p;
lev = decode(s, PriNames);
if (lev < 0)
bailout("unknown priority name: ", s);
return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
}
static int
decode(char *name, struct code *codetab)
{
struct code *c;
if (isdigit(*name))
return (atoi(name));
for (c = codetab; c->c_name; c++)
if (strcasecmp(name, c->c_name) == 0)
return (c->c_val);
return (-1);
}
static void
bailout(char *a, char *b)
{
(void) fprintf(stderr, gettext("logger: %s%s\n"), a, b);
exit(1);
}
static void
usage(void)
{
(void) fprintf(stderr, gettext(
"Usage:\tlogger string\n"
"\tlogger [-i] [-f filename] [-p priority] [-t tag] "
"[message] ...\n"));
exit(1);
}