1 /* $OpenBSD: syslogc.c,v 1.12 2007/01/03 13:25:21 mpf 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 <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 #define DEFAULT_CTLSOCK "/var/run/syslogd.sock" 30 31 #define MAX_MEMBUF_NAME 64 /* Max length of membuf log name */ 32 33 /* 34 * Client protocol NB. all numeric fields in network byte order 35 */ 36 #define CTL_VERSION 1 37 38 /* Request */ 39 struct ctl_cmd { 40 u_int32_t version; 41 #define CMD_READ 1 /* Read out log */ 42 #define CMD_READ_CLEAR 2 /* Read and clear log */ 43 #define CMD_CLEAR 3 /* Clear log */ 44 #define CMD_LIST 4 /* List available logs */ 45 #define CMD_FLAGS 5 /* Query flags only */ 46 #define CMD_READ_CONT 6 /* Read out log continuously */ 47 u_int32_t cmd; 48 char logname[MAX_MEMBUF_NAME]; 49 }; 50 51 /* Reply */ 52 struct ctl_reply_hdr { 53 u_int32_t version; 54 #define CTL_HDR_FLAG_OVERFLOW 0x01 55 u_int32_t flags; 56 /* Reply text follows, up to MAX_MEMBUF long */ 57 }; 58 59 static void 60 usage(void) 61 { 62 extern char *__progname; 63 64 fprintf(stderr, "Usage: %s [-Ccfhoq] [-s ctlsock] logname\n", __progname); 65 exit(1); 66 } 67 68 int 69 main(int argc, char **argv) 70 { 71 const char *ctlsock_path; 72 char buf[8192]; 73 struct sockaddr_un ctl; 74 int ctlsock, ch, oflag, rval; 75 FILE *ctlf; 76 extern char *optarg; 77 extern int optind; 78 struct ctl_cmd cc; 79 struct ctl_reply_hdr rr; 80 81 memset(&cc, '\0', sizeof(cc)); 82 83 ctlsock_path = DEFAULT_CTLSOCK; 84 rval = oflag = 0; 85 while ((ch = getopt(argc, argv, "Ccfhoqs:")) != -1) { 86 switch (ch) { 87 case 'C': 88 cc.cmd = CMD_CLEAR; 89 break; 90 case 'c': 91 cc.cmd = CMD_READ_CLEAR; 92 break; 93 case 'h': 94 usage(); 95 break; 96 case 'f': 97 cc.cmd = CMD_READ_CONT; 98 break; 99 case 'o': 100 cc.cmd = CMD_FLAGS; 101 oflag = 1; 102 break; 103 case 'q': 104 cc.cmd = CMD_LIST; 105 break; 106 case 's': 107 ctlsock_path = optarg; 108 break; 109 default: 110 usage(); 111 break; 112 } 113 } 114 115 if (cc.cmd == 0) 116 cc.cmd = CMD_READ; 117 118 if ((cc.cmd != CMD_LIST && optind != argc - 1) || 119 (cc.cmd == CMD_LIST && optind != argc)) 120 usage(); 121 122 if (cc.cmd != CMD_LIST) { 123 if (strlcpy(cc.logname, argv[optind], sizeof(cc.logname)) >= 124 sizeof(cc.logname)) 125 errx(1, "Specified log name is too long"); 126 } 127 128 memset(&ctl, '\0', sizeof(ctl)); 129 strlcpy(ctl.sun_path, ctlsock_path, sizeof(ctl.sun_path)); 130 ctl.sun_family = AF_UNIX; 131 132 if ((ctlsock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 133 err(1, "socket"); 134 if (connect(ctlsock, (struct sockaddr *)&ctl, sizeof(ctl)) == -1) 135 err(1, "connect: %s", ctl.sun_path); 136 if ((ctlf = fdopen(ctlsock, "r+")) == NULL) 137 err(1, "fdopen"); 138 139 cc.version = htonl(CTL_VERSION); 140 cc.cmd = htonl(cc.cmd); 141 /* Send command */ 142 if (fwrite(&cc, sizeof(cc), 1, ctlf) != 1) 143 err(1, "fwrite"); 144 145 fflush(ctlf); 146 setlinebuf(ctlf); 147 148 /* Fetch header */ 149 if (fread(&rr, sizeof(rr), 1, ctlf) != 1) 150 err(1, "fread header"); 151 152 if (ntohl(rr.version) != CTL_VERSION) 153 errx(1, "unsupported syslogd version"); 154 155 /* Write out reply */ 156 while ((fgets(buf, sizeof(buf), ctlf)) != NULL) { 157 if (!strcmp(buf, "<ENOBUFS>\n")) 158 fprintf(stderr, "syslogc [%s]: Lines were dropped!\n", 159 cc.logname); 160 else 161 fputs(buf, stdout); 162 } 163 164 if (oflag && (ntohl(rr.flags) & CTL_HDR_FLAG_OVERFLOW)) { 165 printf("%s has overflowed\n", cc.logname); 166 rval = 1; 167 } 168 169 fclose(ctlf); 170 close(ctlsock); 171 172 exit(rval); 173 } 174