00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 #include <sys/types.h>
00087 #include <stdio.h>
00088 #include <ctype.h>
00089 #include <string.h>
00090 #include <unistd.h>
00091 #include <stdlib.h>
00092 #include <signal.h>
00093 #include <errno.h>
00094 #include <fcntl.h>
00095 #include <limits.h>
00096 #include <time.h>
00097 #include <sys/ioctl.h>
00098 #include <sys/select.h>
00099 #include <sys/wait.h>
00100 #include <net/netlib.h>
00101 #include <net/hton.h>
00102 #include <net/gen/in.h>
00103 #include <net/gen/udp.h>
00104 #include <net/gen/udp_io.h>
00105 #include <net/gen/netdb.h>
00106
00107 #define SYSLOG_NAMES
00108 #include <syslog.h>
00109 #define KLOGD 1
00110
00111 #define MAXLINE 512
00112 #define MAXSVLINE 256
00113
00114 #define DEFUPRI (LOG_USER|LOG_NOTICE)
00115 #define DEFSPRI (LOG_KERN|LOG_CRIT)
00116
00117
00118 #define IGN_CONS 0x001
00119 #define SYNC_FILE 0x002
00120 #define ADDDATE 0x004
00121 #define MARK 0x008
00122
00123 #define CTTY "/dev/log"
00124
00125 #define dprintf if(DbgOpt!=0)printf
00126 #if debug == 0
00127 #define DEBUG(statement)
00128 #else
00129 #define DEBUG(statement) statement
00130 #endif
00131 #if !defined PIDFILE
00132 #define PIDFILE "/var/run/syslogd.pid"
00133 #endif
00134
00135 #define UNAMESZ 8
00136 #define MAXUNAMES 20
00137 #define MAXFNAME 200
00138 #define MAXHOSTNAMELEN 64
00139
00140
00141
00142
00143 #define TIMERINTVL 30
00144 #define INTERVAL1 30
00145 #define INTERVAL2 60
00146 #define MAXREPEAT ((sizeof(repeatinterval)/sizeof(repeatinterval[0]))-1)
00147 #define REPEATTIME(f) ((f)->f_time+repeatinterval[(f)->f_repeatcount])
00148 #define BACKOFF(f) {if(++(f)->f_repeatcount>MAXREPEAT)(f)->f_repeatcount=MAXREPEAT;}
00149
00150
00151 #define F_UNUSED 0
00152 #define F_FILE 1
00153 #define F_TTY 2
00154 #define F_CONSOLE 3
00155 #define F_FORW 4
00156 #define F_USERS 5
00157 #define F_WALL 6
00158
00159 #define max(a,b) ((a)>=(b)?(a):(b))
00160
00161
00162 struct filed {
00163 struct filed *f_next;
00164 short f_type;
00165 short f_file;
00166 time_t f_time;
00167 char f_pmask[LOG_NFACILITIES + 1];
00168 union {
00169 char f_uname[MAXUNAMES][UNAMESZ + 1];
00170 char f_fname[MAXFNAME];
00171 } f_un;
00172 char f_prevline[MAXSVLINE];
00173 char f_lasttime[16];
00174 char f_prevhost[MAXHOSTNAMELEN + 1];
00175 int f_prevpri;
00176 int f_prevlen;
00177 int f_prevcount;
00178 int f_repeatcount;
00179 int f_flags;
00180 };
00181
00182 static const char *const TypeNames[] =
00183 {
00184 "UNUSED", "FILE", "TTY", "CONSOLE", "FORW", "USERS", "WALL", NULL,
00185 };
00186
00187 static struct filed *Files = NULL;
00188 static struct filed consfile;
00189 static int DbgOpt = 0;
00190 static char LocalHostName[MAXHOSTNAMELEN + 1];
00191 static int Initialized = 0;
00192 static int MarkInterval = 20 * 60;
00193 static int MarkSeq = 0;
00194 static time_t now;
00195
00196 static const char *ConfFile = "/etc/syslog.conf";
00197 static const char *PidFile = PIDFILE;
00198 static const char ctty[] = CTTY;
00199
00200 static const char ProgName[] = "syslogd:";
00201 static const char version[] = "1.3 (Minix)";
00202 static const char usage[] =
00203 "usage:\tsyslogd [-d] [-m markinterval] [-f conf-file]\n"
00204 "\t\t[-p listeningport] [-v] [-?]\n" ;
00205 static const int repeatinterval[] =
00206 {INTERVAL1, INTERVAL2,};
00207
00208
00209
00210
00211
00212
00213 void wallmsg(struct filed * fLog, char *message)
00214 {
00215
00216 return;
00217 }
00218
00219
00220
00221
00222
00223 void fprintlog(struct filed * fLog, int flags, char *message)
00224 {
00225 int len;
00226 char line[MAXLINE + 1];
00227 char repbuf[80];
00228
00229 if (message == NULL) {
00230 if (fLog->f_prevcount > 1) {
00231 sprintf(repbuf, "last message repeated %d times", fLog->f_prevcount);
00232 message = repbuf;
00233 } else
00234 message = fLog->f_prevline;
00235 }
00236 sprintf(line, "%s %s %s", fLog->f_lasttime, fLog->f_prevhost, message);
00237 DEBUG(dprintf("Logging to %s", TypeNames[fLog->f_type]);)
00238 fLog->f_time = now;
00239 switch (fLog->f_type) {
00240 case F_UNUSED:
00241 DEBUG(dprintf("\n");)
00242 break;
00243 case F_CONSOLE:
00244 if (flags & IGN_CONS) {
00245 case F_FORW:
00246 DEBUG(dprintf(" (ignored)\n");)
00247 break;
00248 }
00249 case F_TTY:
00250 case F_FILE:
00251 DEBUG(dprintf(" %s\n", fLog->f_un.f_fname);)
00252 strcat(line, fLog->f_type != F_FILE ? "\r\n" : "\n");
00253 len = strlen(line);
00254 if (write(fLog->f_file, line, len) != len) {
00255 ;
00256 } else if (flags & SYNC_FILE)
00257 sync();
00258 break;
00259 case F_USERS:
00260 case F_WALL:
00261 DEBUG(dprintf("\n");)
00262 strcat(line, "\r\n");
00263 wallmsg(fLog, line);
00264 break;
00265 }
00266 fLog->f_prevcount = 0;
00267 return;
00268 }
00269
00270
00271
00272
00273
00274
00275 void logmsg(int pri, char *msg, char *from, int flags)
00276 {
00277 struct filed *f;
00278 int fac, prilev;
00279 int omask, msglen;
00280 char *timestamp;
00281
00282 DEBUG(dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);)
00283
00284
00285
00286
00287 msglen = strlen(msg);
00288 if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
00289 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
00290 flags |= ADDDATE;
00291
00292 time(&now);
00293 if (flags & ADDDATE)
00294 timestamp = ctime(&now) + 4;
00295 else {
00296 timestamp = msg;
00297 msg += 16;
00298 msglen -= 16;
00299 }
00300
00301
00302 fac = (flags & MARK) ? LOG_NFACILITIES : LOG_FAC(pri);
00303 prilev = LOG_PRI(pri);
00304
00305
00306 if (!Initialized) {
00307
00308 f = &consfile;
00309 f->f_file = open(ctty, O_WRONLY | O_NOCTTY);
00310 if (f->f_file >= 0) {
00311 if (!DbgOpt) setsid();
00312 fprintlog(f, flags, msg);
00313 close(f->f_file);
00314 }
00315 } else {
00316 for (f = Files; f; f = f->f_next) {
00317
00318
00319 if (f->f_pmask[fac] < prilev || f->f_pmask[fac] == INTERNAL_NOPRI)
00320 continue;
00321
00322 if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) continue;
00323
00324
00325 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
00326 continue;
00327
00328
00329 if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
00330 !strcmp(msg, f->f_prevline) &&
00331 !strcmp(from, f->f_prevhost)) {
00332 strncpy(f->f_lasttime, timestamp, 15);
00333 f->f_prevcount += 1;
00334 DEBUG(dprintf("msg repeated %d times, %ld sec of %d\n",
00335 f->f_prevcount, now - f->f_time,
00336 repeatinterval[f->f_repeatcount]);)
00337
00338
00339
00340
00341 if (now > REPEATTIME(f)) {
00342 fprintlog(f, flags, (char *) NULL);
00343 BACKOFF(f);
00344 }
00345 } else {
00346
00347 if (f->f_prevcount) fprintlog(f, 0, (char *) NULL);
00348 f->f_repeatcount = 0;
00349 strncpy(f->f_lasttime, timestamp, 15);
00350 strncpy(f->f_prevhost, from, sizeof(f->f_prevhost));
00351 if (msglen < MAXSVLINE) {
00352 f->f_prevlen = msglen;
00353 f->f_prevpri = pri;
00354 strcpy(f->f_prevline, msg);
00355 fprintlog(f, flags, (char *) NULL);
00356 } else {
00357 f->f_prevline[0] = 0;
00358 f->f_prevlen = 0;
00359 fprintlog(f, flags, msg);
00360 }
00361 }
00362 }
00363 }
00364
00365
00366
00367
00368 return;
00369 }
00370
00371
00372
00373
00374
00375 void logerror(char *type)
00376 {
00377 char buf[100];
00378
00379 if (errno == 0) sprintf(buf, "%s %s", ProgName, type);
00380
00381 else if (errno >= _NERROR)
00382 sprintf(buf, "%s %s - error %d", ProgName, type, errno);
00383
00384 else
00385 sprintf(buf, "%s %s - %s", ProgName, type, strerror(errno));
00386
00387 errno = 0;
00388 dprintf("%s\n", buf);
00389 logmsg(LOG_SYSLOG | LOG_ERR, buf, LocalHostName, ADDDATE);
00390 return;
00391 }
00392
00393
00394
00395
00396
00397 void die(int sig)
00398 {
00399 struct filed *f;
00400 char buf[100];
00401
00402 for (f = Files; f != NULL; f = f->f_next) {
00403
00404 if (f->f_prevcount) fprintlog(f, 0, NULL);
00405 }
00406 if (sig >= 0) {
00407 DEBUG(dprintf("%s exiting on signal %d\n", ProgName, sig);)
00408 sprintf(buf, "exiting on signal %d", sig);
00409 errno = 0;
00410 logerror(buf);
00411 }
00412 unlink(PidFile);
00413 exit(sig == (-1) ? EXIT_FAILURE : EXIT_SUCCESS);
00414 }
00415
00416
00417
00418
00419
00420
00421 void domark(int sig)
00422 {
00423 struct filed *f;
00424
00425 now = time(NULL);
00426 MarkSeq += TIMERINTVL;
00427 if (MarkSeq >= MarkInterval) {
00428 logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE | MARK);
00429 MarkSeq = 0;
00430 }
00431 for (f = Files; f; f = f->f_next) {
00432 if (f->f_prevcount && now >= REPEATTIME(f)) {
00433 DEBUG(dprintf("flush %s: repeated %d times, %d sec.\n",
00434 TypeNames[f->f_type], f->f_prevcount,
00435 repeatinterval[f->f_repeatcount]);)
00436 fprintlog(f, 0, NULL);
00437 BACKOFF(f);
00438 }
00439 }
00440 signal(SIGALRM, domark);
00441 alarm(TIMERINTVL);
00442 return;
00443 }
00444
00445
00446
00447
00448
00449 int decode(char *name, const struct _code *codetab)
00450 {
00451 const struct _code *c;
00452 char *p;
00453 char buf[40];
00454
00455 DEBUG(dprintf("symbolic name: %s", name);)
00456 if (isdigit(*name)) return (atoi(name));
00457
00458 strcpy(buf, name);
00459 for (p = buf; *p; p += 1) {
00460 if (isupper(*p)) *p = tolower(*p);
00461 }
00462 for (c = codetab; c->c_name; c += 1) {
00463 if (!strcmp(buf, c->c_name)) {
00464 DEBUG(dprintf(" ==> %d\n", c->c_val);)
00465 return (c->c_val);
00466 }
00467 }
00468 return (-1);
00469 }
00470
00471
00472
00473
00474
00475 void cfline(char *line, struct filed * fLog)
00476 {
00477 char *p, *q, *bp;
00478 int ix, pri;
00479 char buf[MAXLINE];
00480 char xbuf[200];
00481
00482 DEBUG(dprintf("cfline(%s)\n", line);)
00483
00484
00485 errno = 0;
00486
00487
00488 memset(fLog, 0, sizeof(*fLog));
00489 for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)
00490 fLog->f_pmask[ix] = INTERNAL_NOPRI;
00491
00492
00493 for (p = line; *p && *p != '\t';) {
00494
00495
00496 for (q = p; *q && *q != '\t' && *q++ != '.';) continue;
00497
00498
00499 for (bp = buf; *q && !strchr("\t,;", *q);) *bp++ = *q++;
00500 *bp = '\0';
00501
00502
00503 while (strchr(", ;", *q)) q++;
00504
00505
00506 pri = decode(buf, PriNames);
00507 if (pri < 0) {
00508 sprintf(xbuf, "unknown priority name \"%s\"", buf);
00509 logerror(xbuf);
00510 return;
00511 }
00512
00513
00514 while (*p && !strchr("\t.;", *p)) {
00515 for (bp = buf; *p && !strchr("\t,;.", *p);) *bp++ = *p++;
00516 *bp = '\0';
00517 if (*buf == '*') {
00518 for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)
00519 if ((fLog->f_pmask[ix] < pri) ||
00520 (fLog->f_pmask[ix] == INTERNAL_NOPRI)) {
00521 fLog->f_pmask[ix] = pri;
00522 }
00523 } else {
00524 ix = decode(buf, FacNames);
00525 if (ix < 0) {
00526 sprintf(xbuf, "unknown facility name \"%s\"", buf);
00527 logerror(xbuf);
00528 return;
00529 }
00530 if ((fLog->f_pmask[ix >> 3] < pri) ||
00531 (fLog->f_pmask[ix >> 3] == INTERNAL_NOPRI)) {
00532 fLog->f_pmask[ix >> 3] = pri;
00533 }
00534 }
00535 while (*p == ',' || *p == ' ') p++;
00536 }
00537 p = q;
00538 }
00539
00540
00541 while (*p == '\t' || *p == ' ') p++;
00542
00543 DEBUG(dprintf("leading char in action: %c\n", *p);)
00544 switch (*p) {
00545 case '@':
00546 break;
00547
00548 case '/':
00549 strcpy(fLog->f_un.f_fname, p);
00550 DEBUG(dprintf("filename: %s\n", p); )
00551 if ((fLog->f_file = open(p, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0644)) < 0) {
00552 fLog->f_file = F_UNUSED;
00553 sprintf(xbuf, "unknown file/device (%s)", p);
00554 logerror(xbuf);
00555 break;
00556 }
00557 if (isatty(fLog->f_file)) {
00558 if (!DbgOpt) setsid();
00559 fLog->f_type = F_TTY;
00560 } else
00561 fLog->f_type = F_FILE;
00562 if (strcmp(p, ctty) == 0) fLog->f_type = F_CONSOLE;
00563 break;
00564
00565 case '*':
00566 DEBUG(dprintf("write-all\n");)
00567 fLog->f_type = F_WALL;
00568 break;
00569
00570 default:
00571 DEBUG(dprintf("users: %s\n", p); )
00572 for (ix = 0; ix < MAXUNAMES && *p; ix += 1) {
00573 for (q = p; *q && *q != ',';) q += 1;
00574 strncpy(fLog->f_un.f_uname[ix], p, UNAMESZ);
00575 if ((q - p) > UNAMESZ)
00576 fLog->f_un.f_uname[ix][UNAMESZ] = '\0';
00577 else
00578 fLog->f_un.f_uname[ix][q - p] = '\0';
00579 while (*q == ',' || *q == ' ') q++;
00580 p = q;
00581 }
00582 fLog->f_type = F_USERS;
00583 break;
00584 }
00585 }
00586
00587
00588
00589
00590
00591
00592 void printline(char *hname, char *msg)
00593 {
00594 char line[MAXLINE + 1];
00595 char *p = msg, *q = line;
00596 int ch, pri = DEFUPRI;
00597
00598
00599 if (*p == '<') {
00600 pri = 0;
00601 while (isdigit(*++p)) {
00602 if ((*p - '0') < 8) {
00603
00604 pri = 10 * pri + (*p - '0');
00605 } else
00606 pri = 10 * pri + 7;
00607 }
00608 if (*p == '>') ++p;
00609 }
00610 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) pri = DEFUPRI;
00611
00612
00613 if (LOG_FAC(pri) == LOG_KERN) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
00614
00615
00616 while ((ch = *p++ & 0177) != '\0' && q < &line[sizeof(line) - 1]) {
00617 if (ch == '\n')
00618 *q++ = ' ';
00619 else if (iscntrl(ch)) {
00620 *q++ = '^';
00621 *q++ = ch ^ 0100;
00622 } else
00623 *q++ = ch;
00624 }
00625 *q = '\0';
00626
00627 logmsg(pri, line, hname, 0);
00628 return;
00629 }
00630
00631
00632
00633
00634
00635
00636 void printkline(char *hname, char *msg)
00637 {
00638 char line[MAXLINE + 1];
00639 char *p = msg, *q = line;
00640 int ch, pri = DEFUPRI;
00641
00642
00643 sprintf(line, "kernel: %s", msg);
00644
00645 logmsg(LOG_KERN | LOG_INFO, line, hname, ADDDATE);
00646 return;
00647 }
00648
00649
00650
00651
00652
00653
00654 void init(int sig)
00655 {
00656 int i;
00657 FILE *cf;
00658 struct filed *fLog, *next, **nextp;
00659 char *p;
00660 char cline[BUFSIZ];
00661
00662 DEBUG(dprintf("init\n");)
00663
00664
00665 Initialized = 0;
00666 for (fLog = Files; fLog != NULL; fLog = next) {
00667
00668
00669 if (fLog->f_prevcount) fprintlog(fLog, 0, NULL);
00670
00671 switch (fLog->f_type) {
00672 case F_FILE:
00673 case F_TTY:
00674 case F_CONSOLE: close(fLog->f_file); break;
00675 }
00676 next = fLog->f_next;
00677 free((char *) fLog);
00678 }
00679 Files = NULL;
00680 nextp = &Files;
00681
00682
00683 if ((cf = fopen(ConfFile, "r")) != NULL) {
00684
00685 fLog = NULL;
00686 while (fgets(cline, sizeof(cline), cf) != NULL) {
00687
00688
00689 for (p = cline; isspace(*p); p += 1);
00690 if (*p == '\0' || *p == '#') continue;
00691 for (p = strchr(cline, '\0'); isspace(*--p););
00692 *++p = '\0';
00693 fLog = (struct filed *) calloc(1, sizeof(*fLog));
00694 *nextp = fLog;
00695 nextp = &fLog->f_next;
00696 cfline(cline, fLog);
00697 }
00698
00699
00700 fclose(cf);
00701 Initialized = 1;
00702 DEBUG (
00703 if (DbgOpt) {
00704 for (fLog = Files; fLog; fLog = fLog->f_next) {
00705 for (i = 0; i <= LOG_NFACILITIES; i += 1)
00706 if (fLog->f_pmask[i] == INTERNAL_NOPRI)
00707 printf("X ");
00708 else
00709 printf("%d ", fLog->f_pmask[i]);
00710 printf("%s: ", TypeNames[fLog->f_type]);
00711 switch (fLog->f_type) {
00712 case F_FILE:
00713 case F_TTY:
00714 case F_CONSOLE:
00715 printf("%s", fLog->f_un.f_fname);
00716 break;
00717 case F_FORW:
00718 break;
00719 case F_USERS:
00720 for (i = 0; i < MAXUNAMES && *fLog->f_un.f_uname[i]; i += 1)
00721 printf("%s, ", fLog->f_un.f_uname[i]);
00722 break;
00723 }
00724 printf("\n");
00725 }
00726 }
00727 )
00728 logmsg(LOG_SYSLOG | LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
00729 signal(SIGHUP, init);
00730 DEBUG(dprintf("%s restarted\n", ProgName);)
00731 } else {
00732 DEBUG(dprintf("cannot open %s\n", ConfFile);)
00733 *nextp = (struct filed *) calloc(1, sizeof(*fLog));
00734 cfline("*.ERR\t" CTTY, *nextp);
00735 (*nextp)->f_next = (struct filed *) calloc(1, sizeof(*fLog));
00736 cfline("*.PANIC\t*", (*nextp)->f_next);
00737 Initialized = 1;
00738 }
00739 return;
00740 }
00741
00742
00743
00744
00745
00746 void daemonize(char *line)
00747 {
00748 int lfd, len, pid;
00749
00750 if ((lfd = open(PidFile, O_CREAT | O_RDWR, 0600)) > 0) {
00751 len = read(lfd, line, 10);
00752 line[len] = '\0';
00753 close(lfd);
00754 if ((kill(len = atoi(line), 0) < 0 && errno == ESRCH) || len == 0) {
00755 if (!DbgOpt) {
00756
00757 if ((pid = fork()) > 0) {
00758
00759 lfd = open(PidFile, O_TRUNC | O_WRONLY);
00760 len = sprintf(line, "%5d", pid);
00761 write(lfd, line, len);
00762 close(lfd);
00763
00764
00765 exit(EXIT_SUCCESS);
00766 }
00767 sleep(1);
00768 setsid();
00769 chdir("/");
00770
00771 for (lfd = STDERR_FILENO + 1; lfd < OPEN_MAX; lfd += 1)
00772 close(lfd);
00773 }
00774 } else {
00775 fprintf(stderr, "\n%s already running\n", ProgName);
00776 exit(EXIT_FAILURE);
00777 }
00778 } else {
00779 fprintf(stderr, "\n%s can't open %s (%s)\n", ProgName, PidFile, strerror(errno));
00780 exit(EXIT_FAILURE);
00781 }
00782 return;
00783 }
00784
00785
00786
00787
00788
00789 int main(int argc, char **argv)
00790 {
00791 char *p, *udpdev, *eol;
00792 int nfd, kfd, len, fdmax;
00793 int ch, port = 0;
00794 fd_set fdset;
00795 struct nwio_udpopt udpopt;
00796 struct servent *sp;
00797 char line[MAXLINE + 1];
00798
00799 while ((ch = getopt(argc, argv, "df:m:p:v?")) != EOF) {
00800 switch ((char) ch) {
00801 case 'd':
00802 DbgOpt += 1;
00803 break;
00804 case 'f':
00805 ConfFile = optarg;
00806 break;
00807 case 'm':
00808 MarkInterval = atoi(optarg) * 60;
00809 break;
00810 case 'p':
00811 port = atoi(optarg);
00812 break;
00813 case 'v':
00814 fprintf(stderr, "%s version %s\n", ProgName, version);
00815 return EXIT_FAILURE;
00816 case '?':
00817 default:
00818 fprintf(stderr, usage);
00819 return EXIT_FAILURE;
00820 }
00821 }
00822 if (argc -= optind) {
00823 fprintf(stderr, usage);
00824 return EXIT_FAILURE;
00825 }
00826
00827 daemonize(line);
00828
00829
00830 gethostname(LocalHostName, sizeof(LocalHostName) - 1);
00831 if ((p = strchr(LocalHostName, '.'))) *p = '\0';
00832
00833 udpdev = (p = getenv("UDP_DEVICE")) ? p : UDP_DEVICE;
00834 sp = getservbyname("syslog", "udp");
00835
00836 signal(SIGTERM, die);
00837 signal(SIGINT, DbgOpt ? die : SIG_IGN);
00838 signal(SIGQUIT, DbgOpt ? die : SIG_IGN);
00839 signal(SIGALRM, domark);
00840
00841 alarm(TIMERINTVL);
00842
00843
00844 nfd = open(udpdev, O_NONBLOCK | O_RDONLY);
00845
00846
00847 udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_EN_LOC |
00848 NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
00849 NWUO_RWDATONLY | NWUO_DI_IPOPT;
00850 udpopt.nwuo_locport = udpopt.nwuo_remport =
00851 port == 0 ? sp->s_port : htons(port);
00852 udpopt.nwuo_remaddr = udpopt.nwuo_locaddr = htonl(0x7F000001L);
00853
00854 if(nfd >= 0) {
00855 while (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
00856 ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
00857 if (errno == EAGAIN) {
00858 sleep(1);
00859 continue;
00860 }
00861 logerror("Set/Get UDP options failed");
00862 return EXIT_FAILURE;
00863 }
00864 }
00865
00866
00867 kfd = open("/dev/klog", O_NONBLOCK | O_RDONLY);
00868
00869 if(kfd < 0 && nfd < 0) {
00870 logerror("open /dev/klog and udp device failed - can't log anything");
00871 return EXIT_FAILURE;
00872 }
00873
00874 fdmax = max(nfd, kfd) + 1;
00875
00876 DEBUG(dprintf("off & running....\n");)
00877
00878 init(-1);
00879
00880 for (;;) {
00881
00882 FD_ZERO(&fdset);
00883 if(nfd >= 0) FD_SET(nfd, &fdset);
00884 if(kfd >= 0) FD_SET(kfd, &fdset);
00885
00886 if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) {
00887 sleep(1);
00888 continue;
00889
00890 }
00891 if (nfd >= 0 && FD_ISSET(nfd, &fdset)) {
00892
00893
00894 len = read(nfd, line, MAXLINE);
00895 if (len > 0) {
00896 line[len] = '\0';
00897 dprintf("got a message (%d, %#x)\n", nfd, len);
00898 printline(LocalHostName, line);
00899
00900 } else if (len < 0) {
00901 if (errno != EINTR)
00902 logerror("Receive error from UDP channel");
00903
00904 } else {
00905 logerror("UDP channel has closed");
00906 close(nfd);
00907 die(-1);
00908 }
00909 }
00910 if (kfd >= 0 && FD_ISSET(kfd, &fdset)) {
00911 static char linebuf[5*1024];
00912
00913
00914 len = read(kfd, linebuf, sizeof(linebuf)-2);
00915 dprintf("got a message (%d, %#x)\n", kfd, len);
00916 for (ch = 0; ch < len; ch += 1)
00917 if (linebuf[ch] == '\0') linebuf[ch] = ' ';
00918 if (linebuf[len - 1] == '\n') len -= 1;
00919 linebuf[len] = '\n';
00920 linebuf[len + 1] = '\0';
00921 p = linebuf;
00922 while(eol = strchr(p, '\n')) {
00923 *eol = '\0';
00924 printkline(LocalHostName, p);
00925 p = eol+1;
00926 }
00927 }
00928 }
00929
00930 }
00931