Index: trunk/servmon/smlog.cxx |
— | — | @@ -10,6 +10,7 @@ |
11 | 11 | struct loglsnd : smthr::daemon { |
12 | 12 | loglsnd(void) { |
13 | 13 | } |
| 14 | + |
14 | 15 | void start(void) { |
15 | 16 | smnet::lsnrp s (new smnet::lsnr(smnet::unix)); |
16 | 17 | std::remove("/tmp/servmon.log"); |
— | — | @@ -17,13 +18,25 @@ |
18 | 19 | try { |
19 | 20 | s->lsn(); |
20 | 21 | } catch (smnet::sckterr& e) { |
21 | | - SMI(log)->logmsg(0, std::string("Listen failed for log socket: ") + e.what()); |
| 22 | + SMI(log)->logmsg(0, std::string("Listen failed for UNIX log socket: ") + e.what()); |
22 | 23 | return; |
23 | 24 | } |
24 | 25 | boost::function<void(smnet::scktp, int)> f = |
25 | 26 | boost::bind(&loglsnd::newc, this, _1, _2); |
26 | 27 | SMI(smnet::smpx)->add(f, static_pointer_cast<smnet::sckt>(s), smnet::smpx::srd); |
| 28 | + |
| 29 | + s = smnet::lsnrp(new smnet::lsnr(smnet::internet)); |
| 30 | + s->svc("8577"); |
| 31 | + try { |
| 32 | + s->lsn(); |
| 33 | + } catch (smnet::sckterr& e) { |
| 34 | + SMI(log)->logmsg(0, std::string("Listen failed for IP log socket: ") + e.what()); |
| 35 | + return; |
| 36 | + } |
| 37 | + f = boost::bind(&loglsnd::newc, this, _1, _2); |
| 38 | + SMI(smnet::smpx)->add(f, static_pointer_cast<smnet::sckt>(s), smnet::smpx::srd); |
27 | 39 | } |
| 40 | + |
28 | 41 | void newc(smnet::scktp sckt_, int) { |
29 | 42 | smnet::lsnrp s = dynamic_pointer_cast<smnet::lsnr>(sckt_); |
30 | 43 | try { |
— | — | @@ -35,39 +48,61 @@ |
36 | 49 | SMI(log)->logmsg(0, std::string("Accept failed for log socket: ") + e.what()); |
37 | 50 | } |
38 | 51 | } |
39 | | - void cdata(smnet::scktp s_, int) { |
40 | | - smnet::clntp c = dynamic_pointer_cast<smnet::clnt>(s_); |
41 | | - std::vector<u_char> data; |
42 | | - std::string levs; |
| 52 | + |
| 53 | + std::map<smnet::scktp, std::string> data; |
| 54 | + |
| 55 | + void cdata(smnet::scktp s, int) { |
| 56 | + smnet::clntp c = dynamic_pointer_cast<smnet::clnt>(s); |
| 57 | + std::vector<u_char> thisdata; |
43 | 58 | std::string msg; |
44 | 59 | try { |
45 | | - c->rd(data); |
46 | | - } catch (smnet::sckterr&) { |
47 | | - goto errout; |
| 60 | + c->rd(thisdata); |
| 61 | + } catch (smnet::scktcls&) { |
| 62 | + finish(s); |
| 63 | + SMI(smnet::smpx)->rm(c); |
| 64 | + return; |
| 65 | + } catch (smnet::sckterr& e) { |
| 66 | + data.erase(s); |
| 67 | + SMI(smnet::smpx)->rm(c); |
| 68 | + return; |
48 | 69 | } |
49 | | - msg.assign(data.begin(), data.end()); |
| 70 | + |
| 71 | + msg.assign(thisdata.begin(), thisdata.end()); |
| 72 | + data[s] += msg; |
| 73 | + } |
| 74 | + |
| 75 | + void finish(smnet::scktp s) { |
| 76 | + std::string levs; |
| 77 | + std::string& msg = data[s]; |
| 78 | + |
50 | 79 | levs = smutl::car(msg); |
51 | 80 | if (levs.empty()) { |
52 | 81 | SMI(log)->logmsg(0, "Malformed log message from socket"); |
53 | 82 | goto errout; |
54 | 83 | } |
| 84 | + |
55 | 85 | while (!msg.empty() and msg[0] == ' ') |
56 | 86 | msg.erase(msg.begin()); |
| 87 | + |
57 | 88 | if (msg.empty()) { |
58 | 89 | SMI(log)->logmsg(0, "Malformed log message from socket"); |
59 | 90 | goto errout; |
60 | 91 | } |
| 92 | + |
61 | 93 | int lev; |
62 | 94 | try { |
63 | 95 | lev = lexical_cast<int>(levs); |
64 | 96 | } catch (bad_lexical_cast&) { |
65 | 97 | goto errout; |
66 | 98 | } |
| 99 | + |
67 | 100 | if (lev < 0 || lev > 16) |
68 | 101 | goto errout; |
| 102 | + |
69 | 103 | SMI(log)->logmsg(lev, msg); |
70 | 104 | errout: |
71 | | - SMI(smnet::smpx)->rm(c); |
| 105 | + data.erase(s); |
| 106 | + SMI(smnet::smpx)->rm(s); |
72 | 107 | } |
73 | 108 | }; |
74 | 109 | } // anonymous namespace |
Index: trunk/servmon/include/smthr.hxx |
— | — | @@ -43,6 +43,7 @@ |
44 | 44 | class thrbase { |
45 | 45 | public: |
46 | 46 | thrbase(); |
| 47 | + virtual ~thrbase() {} |
47 | 48 | virtual void run(void); |
48 | 49 | virtual void start(void) = 0; |
49 | 50 | }; |
Index: trunk/servmon/SConstruct |
— | — | @@ -35,5 +35,5 @@ |
36 | 36 | env.Command('sminfo.cxx', 'sminfo.sh', '/bin/sh $SOURCE >$TARGET') |
37 | 37 | |
38 | 38 | env.Program ('servmon', srcs) |
39 | | -env.Program ('smlogmsg', ['smlogmsg.c']) |
| 39 | +env.Program ('smlogmsg', ['smlogmsg.c'], LIBS = [], LINKFLAGS = '-static') |
40 | 40 | env.Alias('install', prefix) |
Index: trunk/servmon/smlogmsg.c |
— | — | @@ -1,53 +1,92 @@ |
2 | 2 | /* @(#) $Header$ */ |
| 3 | +#include <sys/types.h> |
3 | 4 | #include <sys/socket.h> |
4 | 5 | #include <sys/un.h> |
5 | 6 | |
| 7 | +#include <netdb.h> |
| 8 | + |
6 | 9 | #include <stdio.h> |
7 | 10 | #include <string.h> |
8 | 11 | #include <stdlib.h> |
9 | 12 | #include <errno.h> |
10 | 13 | #include <unistd.h> |
11 | 14 | |
| 15 | +int tflag, uflag; |
| 16 | +const char *progname, *host; |
| 17 | +char *level = "0"; |
| 18 | + |
| 19 | +static void usage(void); |
| 20 | +static int sock_unix(const char *hostname); |
| 21 | +static int sock_tcp(const char *pathname); |
| 22 | + |
12 | 23 | int |
13 | 24 | main(int argc, char *argv[]) |
14 | 25 | { |
15 | | - struct sockaddr_un sa; |
16 | | - socklen_t len; |
17 | | - int s; |
18 | | - struct iovec iovec[3]; |
| 26 | +struct iovec iovec[3]; |
| 27 | + int s, i; |
19 | 28 | |
20 | | - if (argc != 3) { |
21 | | - fprintf(stderr, "usage: %s <log level> <message>\n", argv[0]); |
22 | | - exit(8); |
| 29 | + progname = argv[0]; |
| 30 | + |
| 31 | + while ((i = getopt(argc, argv, "tul:H:h:" |
| 32 | +#ifdef __linux__ |
| 33 | + "+" |
| 34 | +#endif |
| 35 | + )) != -1) { |
| 36 | + switch(i) { |
| 37 | + case 't': |
| 38 | + tflag++; |
| 39 | + break; |
| 40 | + case 'u': |
| 41 | + uflag++; |
| 42 | + break; |
| 43 | + case 'l': |
| 44 | + level = optarg; |
| 45 | + break; |
| 46 | + case 'H': |
| 47 | + host = optarg; |
| 48 | + break; |
| 49 | + case 'h': |
| 50 | + default: |
| 51 | + usage(); |
| 52 | + } |
23 | 53 | } |
| 54 | + |
| 55 | + argc -= optind; |
| 56 | + argv += optind; |
24 | 57 | |
25 | | - bzero(&sa, sizeof(sa)); |
26 | | - sa.sun_family = AF_UNIX; |
27 | | - strcpy(sa.sun_path, "/tmp/servmon.log"); |
28 | | - len = SUN_LEN(&sa); |
29 | | - |
30 | | - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { |
31 | | - perror("socket"); |
| 58 | + if (argc != 1) { |
| 59 | + fprintf(stderr, "%s: %s arguments\n", progname, |
| 60 | + argc == 0 ? "not enough" : "too many"); |
| 61 | + usage(); |
| 62 | + } |
| 63 | + |
| 64 | + if (tflag && uflag) { |
| 65 | + fprintf(stderr, "%s: -t and -u may not be specified together\n", progname); |
32 | 66 | exit(8); |
33 | 67 | } |
34 | 68 | |
35 | | - if (connect(s, (struct sockaddr *) &sa, len) < 0) { |
36 | | - perror("connect"); |
| 69 | + if (tflag && !host) { |
| 70 | + fprintf(stderr, "%s: -t requires -H <host>\n", progname); |
37 | 71 | exit(8); |
38 | 72 | } |
| 73 | + |
| 74 | + if (tflag) |
| 75 | + s = sock_tcp(host); |
| 76 | + else |
| 77 | + s = sock_unix(host ? host : "/tmp/servmon.log"); |
39 | 78 | |
40 | 79 | /* |
41 | 80 | * servmon truncates messages longer than this. |
42 | 81 | */ |
43 | | - if (strlen(argv[2]) > 4096) |
44 | | - argv[2][4096] = '\0'; |
| 82 | + if (strlen(argv[0]) > 4096) |
| 83 | + argv[0][4096] = '\0'; |
45 | 84 | |
46 | | - iovec[0].iov_base = argv[1]; |
47 | | - iovec[0].iov_len = strlen(argv[1]); |
| 85 | + iovec[0].iov_base = level; |
| 86 | + iovec[0].iov_len = strlen(level); |
48 | 87 | iovec[1].iov_base = " "; |
49 | 88 | iovec[1].iov_len = 1; |
50 | | - iovec[2].iov_base = argv[2]; |
51 | | - iovec[2].iov_len = strlen(argv[2]); |
| 89 | + iovec[2].iov_base = argv[0]; |
| 90 | + iovec[2].iov_len = strlen(argv[0]); |
52 | 91 | |
53 | 92 | if (writev(s, iovec, 3) < 0) { |
54 | 93 | perror("write"); |
— | — | @@ -56,3 +95,70 @@ |
57 | 96 | |
58 | 97 | exit(0); |
59 | 98 | } |
| 99 | + |
| 100 | +static void |
| 101 | +usage(void) |
| 102 | +{ |
| 103 | + fprintf(stderr, "usage: %s [-ut] [-l level] [-H host] <message>\n", progname); |
| 104 | + exit(8); |
| 105 | +} |
| 106 | + |
| 107 | +static int |
| 108 | +sock_unix(const char *sockname) |
| 109 | +{ |
| 110 | +struct sockaddr_un sa; |
| 111 | + int s; |
| 112 | + socklen_t len; |
| 113 | + |
| 114 | + bzero(&sa, sizeof(sa)); |
| 115 | + sa.sun_family = AF_UNIX; |
| 116 | + strncpy(sa.sun_path, sockname, sizeof(sa.sun_path) - 1); |
| 117 | + |
| 118 | + if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { |
| 119 | + perror("socket"); |
| 120 | + exit(8); |
| 121 | + } |
| 122 | + |
| 123 | + if (connect(s, (struct sockaddr *) &sa, len) < 0) { |
| 124 | + perror("connect"); |
| 125 | + exit(8); |
| 126 | + } |
| 127 | + |
| 128 | + return s; |
| 129 | +} |
| 130 | + |
| 131 | +static int |
| 132 | +sock_tcp(const char *hostname) |
| 133 | +{ |
| 134 | +struct sockaddr_storage sa; |
| 135 | +struct addrinfo hints, *res, *each; |
| 136 | + int i; |
| 137 | + |
| 138 | + bzero(&sa, sizeof(sa)); |
| 139 | + bzero(&hints, sizeof(hints)); |
| 140 | + hints.ai_socktype = SOCK_STREAM; |
| 141 | + |
| 142 | + if ((i = getaddrinfo(hostname, "8577", &hints, &res)) != 0) { |
| 143 | + fprintf(stderr, "%s: %s\n", progname, gai_strerror(i)); |
| 144 | + exit(8); |
| 145 | + } |
| 146 | + |
| 147 | + for (each = res; each; each = each->ai_next) { |
| 148 | + int s; |
| 149 | + if ((s = socket(each->ai_family, each->ai_socktype, each->ai_protocol)) < 0) { |
| 150 | + fprintf(stderr, "%s: socket: %s\n", progname, strerror(errno)); |
| 151 | + continue; |
| 152 | + } |
| 153 | + |
| 154 | + if (connect(s, each->ai_addr, each->ai_addrlen) < 0) { |
| 155 | + fprintf(stderr, "%s: connect: %s\n", progname, strerror(errno)); |
| 156 | + continue; |
| 157 | + } |
| 158 | + |
| 159 | + freeaddrinfo(res); |
| 160 | + return s; |
| 161 | + } |
| 162 | + |
| 163 | + freeaddrinfo(res); |
| 164 | + exit(8); |
| 165 | +} |