xref: /openbsd-src/usr.sbin/syslogc/syslogc.c (revision ffb9ed4e90b64bb430a8652798f12b2c4baf96b0)
1 /* $OpenBSD: syslogc.c,v 1.1 2004/01/04 08:30:21 djm Exp $ */
2 
3 /*
4  * Copyright (c) 2004 Damien Miller
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 
23 #include <err.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #define DEFAULT_CTLSOCK		"/var/run/syslogd.sock"
31 
32 #define MAX_MEMBUF_NAME	64		/* Max length of membuf log name */
33 struct ctl_cmd {
34 #define CMD_READ	1	/* Read out log */
35 #define CMD_READ_CLEAR	2	/* Read and clear log */
36 #define CMD_CLEAR	3	/* Clear log */
37 #define CMD_LIST	4	/* List available logs */
38 	int	cmd;
39 	char	logname[MAX_MEMBUF_NAME];
40 };
41 
42 static void
43 usage(void)
44 {
45 	extern char *__progname;
46 
47 	fprintf(stderr, "Usage: %s [-Ccq] [-s ctlsock] logname\n", __progname);
48 	exit(1);
49 }
50 
51 int
52 main(int argc, char **argv)
53 {
54 	const char *ctlsock_path;
55 	char buf[8192];
56 	struct sockaddr_un ctl;
57 	socklen_t ctllen;
58 	int ctlsock, ch;
59 	FILE *ctlf;
60 	extern char *optarg;
61 	extern int optind;
62 	struct ctl_cmd cc;
63 
64 	memset(&cc, '\0', sizeof(cc));
65 
66 	ctlsock_path = DEFAULT_CTLSOCK;
67 	while ((ch = getopt(argc, argv, "Cchqs:")) != -1) {
68 		switch (ch) {
69 		case 'h':
70 			usage();
71 			break;
72 		case 'q':
73 			cc.cmd = CMD_LIST;
74 			break;
75 		case 'c':
76 			cc.cmd = CMD_READ_CLEAR;
77 			break;
78 		case 'C':
79 			cc.cmd = CMD_CLEAR;
80 			break;
81 		case 's':
82 			ctlsock_path = optarg;
83 			break;
84 		default:
85 			fprintf(stderr, "Invalid commandline option.\n");
86 			usage();
87 			break;
88 		}
89 	}
90 
91 	if (cc.cmd == 0)
92 		cc.cmd = CMD_READ;
93 
94 	if ((cc.cmd != CMD_LIST && optind != argc - 1) ||
95 	    (cc.cmd == CMD_LIST && optind != argc))
96 		usage();
97 
98 	if (cc.cmd != CMD_LIST) {
99 		if (strlcpy(cc.logname, argv[optind], sizeof(cc.logname)) >
100 		    sizeof(cc.logname))
101 			errx(1, "Specified log name is too long");
102 	}
103 
104 	strlcpy(ctl.sun_path, ctlsock_path, sizeof(ctl.sun_path));
105 	ctl.sun_path[sizeof(ctl.sun_path) - 1] = '\0';
106 	ctl.sun_family = AF_UNIX;
107 
108 	if ((ctlsock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
109 		err(1, "ctl socket() error");
110 	if (connect(ctlsock, (struct sockaddr*)&ctl, sizeof(ctl)) == -1)
111 		err(1, "ctl connect(\"%s\") error", ctl.sun_path);
112 	if ((ctlf = fdopen(ctlsock, "r+")) == NULL)
113 		err(1, "fdopen");
114 	/* Send command */
115 	if (fwrite(&cc, sizeof(cc), 1, ctlf) <= 0)
116 		err(1, "fwrite");
117 
118 	fflush(ctlf);
119 	setlinebuf(ctlf);
120 
121 	/* Write out reply */
122 	while((fgets(buf, sizeof(buf), ctlf)) != NULL)
123 		fputs(buf, stdout);
124 
125 	fclose(ctlf);
126 	close(ctlsock);
127 
128 	exit(0);
129 }
130