|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)inetd.c 5.6 (Berkeley) 4/29/86"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * Inetd - Internet super-server ! 19: * ! 20: * This program invokes all internet services as needed. ! 21: * connection-oriented services are invoked each time a ! 22: * connection is made, by creating a process. This process ! 23: * is passed the connection as file descriptor 0 and is ! 24: * expected to do a getpeername to find out the source host ! 25: * and port. ! 26: * ! 27: * Datagram oriented services are invoked when a datagram ! 28: * arrives; a process is created and passed a pending message ! 29: * on file descriptor 0. Datagram servers may either connect ! 30: * to their peer, freeing up the original socket for inetd ! 31: * to receive further messages on, or ``take over the socket'', ! 32: * processing all arriving datagrams and, eventually, timing ! 33: * out. The first type of server is said to be ``multi-threaded''; ! 34: * the second type of server ``single-threaded''. ! 35: * ! 36: * Inetd uses a configuration file which is read at startup ! 37: * and, possibly, at some later time in response to a hangup signal. ! 38: * The configuration file is ``free format'' with fields given in the ! 39: * order shown below. Continuation lines for an entry must being with ! 40: * a space or tab. All fields must be present in each entry. ! 41: * ! 42: * service name must be in /etc/services ! 43: * socket type stream/dgram/raw/rdm/seqpacket ! 44: * protocol must be in /etc/protocols ! 45: * wait/nowait single-threaded/multi-threaded ! 46: * user user to run daemon as ! 47: * server program full path name ! 48: * server program arguments maximum of MAXARGS (5) ! 49: * ! 50: * Comment lines are indicated by a `#' in column 1. ! 51: */ ! 52: #include <sys/param.h> ! 53: #include <sys/stat.h> ! 54: #include <sys/ioctl.h> ! 55: #include <sys/socket.h> ! 56: #include <sys/file.h> ! 57: #include <sys/wait.h> ! 58: #include <sys/time.h> ! 59: #include <sys/resource.h> ! 60: ! 61: #include <netinet/in.h> ! 62: #include <arpa/inet.h> ! 63: ! 64: #include <errno.h> ! 65: #include <stdio.h> ! 66: #include <signal.h> ! 67: #include <netdb.h> ! 68: #include <syslog.h> ! 69: #include <pwd.h> ! 70: ! 71: #define TOOMANY 40 /* don't start more than TOOMANY */ ! 72: #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ ! 73: #define RETRYTIME (60*10) /* retry after bind or server fail */ ! 74: ! 75: #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) ! 76: ! 77: extern int errno; ! 78: ! 79: int reapchild(), retry(); ! 80: char *index(); ! 81: char *malloc(); ! 82: ! 83: int debug = 0; ! 84: int nsock, maxsock; ! 85: fd_set allsock; ! 86: int options; ! 87: int timingout; ! 88: struct servent *sp; ! 89: ! 90: struct servtab { ! 91: char *se_service; /* name of service */ ! 92: int se_socktype; /* type of socket to use */ ! 93: char *se_proto; /* protocol used */ ! 94: short se_wait; /* single threaded server */ ! 95: short se_checked; /* looked at during merge */ ! 96: char *se_user; /* user name to run as */ ! 97: struct biltin *se_bi; /* if built-in, description */ ! 98: char *se_server; /* server program */ ! 99: #define MAXARGV 5 ! 100: char *se_argv[MAXARGV+1]; /* program arguments */ ! 101: int se_fd; /* open descriptor */ ! 102: struct sockaddr_in se_ctrladdr;/* bound address */ ! 103: int se_count; /* number started since se_time */ ! 104: struct timeval se_time; /* start of se_count */ ! 105: struct servtab *se_next; ! 106: } *servtab; ! 107: ! 108: int echo_stream(), discard_stream(), machtime_stream(); ! 109: int daytime_stream(), chargen_stream(); ! 110: int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg(); ! 111: ! 112: struct biltin { ! 113: char *bi_service; /* internally provided service name */ ! 114: int bi_socktype; /* type of socket supported */ ! 115: short bi_fork; /* 1 if should fork before call */ ! 116: short bi_wait; /* 1 if should wait for child */ ! 117: int (*bi_fn)(); /* function which performs it */ ! 118: } biltins[] = { ! 119: /* Echo received data */ ! 120: "echo", SOCK_STREAM, 1, 0, echo_stream, ! 121: "echo", SOCK_DGRAM, 0, 0, echo_dg, ! 122: ! 123: /* Internet /dev/null */ ! 124: "discard", SOCK_STREAM, 1, 0, discard_stream, ! 125: "discard", SOCK_DGRAM, 0, 0, discard_dg, ! 126: ! 127: /* Return 32 bit time since 1970 */ ! 128: "time", SOCK_STREAM, 0, 0, machtime_stream, ! 129: "time", SOCK_DGRAM, 0, 0, machtime_dg, ! 130: ! 131: /* Return human-readable time */ ! 132: "daytime", SOCK_STREAM, 0, 0, daytime_stream, ! 133: "daytime", SOCK_DGRAM, 0, 0, daytime_dg, ! 134: ! 135: /* Familiar character generator */ ! 136: "chargen", SOCK_STREAM, 1, 0, chargen_stream, ! 137: "chargen", SOCK_DGRAM, 0, 0, chargen_dg, ! 138: 0 ! 139: }; ! 140: ! 141: #define NUMINT (sizeof(intab) / sizeof(struct inent)) ! 142: char *CONFIG = "/etc/inetd.conf"; ! 143: char **Argv; ! 144: char *LastArg; ! 145: ! 146: main(argc, argv, envp) ! 147: int argc; ! 148: char *argv[], *envp[]; ! 149: { ! 150: register struct servtab *sep; ! 151: register struct passwd *pwd; ! 152: char *cp, buf[50]; ! 153: int pid, i, dofork; ! 154: struct sigvec sv; ! 155: ! 156: Argv = argv; ! 157: if (envp == 0 || *envp == 0) ! 158: envp = argv; ! 159: while (*envp) ! 160: envp++; ! 161: LastArg = envp[-1] + strlen(envp[-1]); ! 162: argc--, argv++; ! 163: while (argc > 0 && *argv[0] == '-') { ! 164: for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { ! 165: ! 166: case 'd': ! 167: debug = 1; ! 168: options |= SO_DEBUG; ! 169: break; ! 170: ! 171: default: ! 172: fprintf(stderr, ! 173: "inetd: Unknown flag -%c ignored.\n", *cp); ! 174: break; ! 175: } ! 176: nextopt: ! 177: argc--, argv++; ! 178: } ! 179: if (argc > 0) ! 180: CONFIG = argv[0]; ! 181: #ifndef DEBUG ! 182: if (fork()) ! 183: exit(0); ! 184: { int s; ! 185: for (s = 0; s < 10; s++) ! 186: (void) close(s); ! 187: } ! 188: (void) open("/", O_RDONLY); ! 189: (void) dup2(0, 1); ! 190: (void) dup2(0, 2); ! 191: { int tt = open("/dev/tty", O_RDWR); ! 192: if (tt > 0) { ! 193: ioctl(tt, TIOCNOTTY, (char *)0); ! 194: close(tt); ! 195: } ! 196: } ! 197: #endif ! 198: openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); ! 199: bzero((char *)&sv, sizeof(sv)); ! 200: sv.sv_mask = SIGBLOCK; ! 201: sv.sv_handler = retry; ! 202: sigvec(SIGALRM, &sv, (struct sigvec *)0); ! 203: config(); ! 204: sv.sv_handler = config; ! 205: sigvec(SIGHUP, &sv, (struct sigvec *)0); ! 206: sv.sv_handler = reapchild; ! 207: sigvec(SIGCHLD, &sv, (struct sigvec *)0); ! 208: ! 209: for (;;) { ! 210: int s, ctrl, n; ! 211: fd_set readable; ! 212: ! 213: while (nsock == 0) ! 214: sigpause(0); ! 215: readable = allsock; ! 216: if ((n = select(maxsock + 1, &readable, (fd_set *)0, ! 217: (fd_set *)0, (struct timeval *)0)) <= 0) { ! 218: if (n < 0 && errno != EINTR) ! 219: syslog(LOG_WARNING, "select: %m\n"); ! 220: sleep(1); ! 221: continue; ! 222: } ! 223: for (sep = servtab; n && sep; sep = sep->se_next) ! 224: if (FD_ISSET(sep->se_fd, &readable)) { ! 225: n--; ! 226: if (debug) ! 227: fprintf(stderr, "someone wants %s\n", sep->se_service); ! 228: if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { ! 229: ctrl = accept(sep->se_fd, (struct sockaddr *)0, ! 230: (int *)0); ! 231: if (debug) ! 232: fprintf(stderr, "accept, ctrl %d\n", ctrl); ! 233: if (ctrl < 0) { ! 234: if (errno == EINTR) ! 235: continue; ! 236: syslog(LOG_WARNING, "accept: %m"); ! 237: continue; ! 238: } ! 239: } else ! 240: ctrl = sep->se_fd; ! 241: (void) sigblock(SIGBLOCK); ! 242: pid = 0; ! 243: dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); ! 244: if (dofork) { ! 245: if (sep->se_count++ == 0) ! 246: (void)gettimeofday(&sep->se_time, ! 247: (struct timezone *)0); ! 248: else if (sep->se_count >= TOOMANY) { ! 249: struct timeval now; ! 250: ! 251: (void)gettimeofday(&now, (struct timezone *)0); ! 252: if (now.tv_sec - sep->se_time.tv_sec > ! 253: CNT_INTVL) { ! 254: sep->se_time = now; ! 255: sep->se_count = 1; ! 256: } else { ! 257: syslog(LOG_ERR, ! 258: "%s/%s server failing (looping), service terminated\n", ! 259: sep->se_service, sep->se_proto); ! 260: FD_CLR(sep->se_fd, &allsock); ! 261: (void) close(sep->se_fd); ! 262: sep->se_fd = -1; ! 263: sep->se_count = 0; ! 264: nsock--; ! 265: sigsetmask(0); ! 266: if (!timingout) { ! 267: timingout = 1; ! 268: alarm(RETRYTIME); ! 269: } ! 270: continue; ! 271: } ! 272: } ! 273: pid = fork(); ! 274: } ! 275: if (pid < 0) { ! 276: if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) ! 277: close(ctrl); ! 278: sigsetmask(0); ! 279: sleep(1); ! 280: continue; ! 281: } ! 282: if (pid && sep->se_wait) { ! 283: sep->se_wait = pid; ! 284: FD_CLR(sep->se_fd, &allsock); ! 285: nsock--; ! 286: } ! 287: sigsetmask(0); ! 288: if (pid == 0) { ! 289: #ifdef DEBUG ! 290: int tt; ! 291: ! 292: if (dofork && (tt = open("/dev/tty", O_RDWR)) > 0) { ! 293: ioctl(tt, TIOCNOTTY, 0); ! 294: close(tt); ! 295: } ! 296: #endif ! 297: if (dofork) ! 298: for (i = getdtablesize(); --i > 2; ) ! 299: if (i != ctrl) ! 300: close(i); ! 301: if (sep->se_bi) ! 302: (*sep->se_bi->bi_fn)(ctrl, sep); ! 303: else { ! 304: dup2(ctrl, 0); ! 305: close(ctrl); ! 306: dup2(0, 1); ! 307: dup2(0, 2); ! 308: if ((pwd = getpwnam(sep->se_user)) == NULL) { ! 309: syslog(LOG_ERR, ! 310: "getpwnam: %s: No such user", ! 311: sep->se_user); ! 312: if (sep->se_socktype != SOCK_STREAM) ! 313: recv(0, buf, sizeof (buf), 0); ! 314: _exit(1); ! 315: } ! 316: if (pwd->pw_uid) { ! 317: (void) setgid((gid_t)pwd->pw_gid); ! 318: initgroups(pwd->pw_name, pwd->pw_gid); ! 319: (void) setuid((uid_t)pwd->pw_uid); ! 320: } ! 321: if (debug) ! 322: fprintf(stderr, "%d execl %s\n", ! 323: getpid(), sep->se_server); ! 324: execv(sep->se_server, sep->se_argv); ! 325: if (sep->se_socktype != SOCK_STREAM) ! 326: recv(0, buf, sizeof (buf), 0); ! 327: syslog(LOG_ERR, "execv %s: %m", sep->se_server); ! 328: _exit(1); ! 329: } ! 330: } ! 331: if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) ! 332: close(ctrl); ! 333: } ! 334: } ! 335: } ! 336: ! 337: reapchild() ! 338: { ! 339: union wait status; ! 340: int pid; ! 341: register struct servtab *sep; ! 342: ! 343: for (;;) { ! 344: pid = wait3(&status, WNOHANG, (struct rusage *)0); ! 345: if (pid <= 0) ! 346: break; ! 347: if (debug) ! 348: fprintf(stderr, "%d reaped\n", pid); ! 349: for (sep = servtab; sep; sep = sep->se_next) ! 350: if (sep->se_wait == pid) { ! 351: if (status.w_status) ! 352: syslog(LOG_WARNING, ! 353: "%s: exit status 0x%x", ! 354: sep->se_server, status); ! 355: if (debug) ! 356: fprintf(stderr, "restored %s, fd %d\n", ! 357: sep->se_service, sep->se_fd); ! 358: FD_SET(sep->se_fd, &allsock); ! 359: nsock++; ! 360: sep->se_wait = 1; ! 361: } ! 362: } ! 363: } ! 364: ! 365: config() ! 366: { ! 367: register struct servtab *sep, *cp, **sepp; ! 368: struct servtab *getconfigent(), *enter(); ! 369: int omask; ! 370: ! 371: if (!setconfig()) { ! 372: syslog(LOG_ERR, "%s: %m", CONFIG); ! 373: return; ! 374: } ! 375: for (sep = servtab; sep; sep = sep->se_next) ! 376: sep->se_checked = 0; ! 377: while (cp = getconfigent()) { ! 378: for (sep = servtab; sep; sep = sep->se_next) ! 379: if (strcmp(sep->se_service, cp->se_service) == 0 && ! 380: strcmp(sep->se_proto, cp->se_proto) == 0) ! 381: break; ! 382: if (sep != 0) { ! 383: int i; ! 384: ! 385: omask = sigblock(SIGBLOCK); ! 386: if (cp->se_bi == 0) ! 387: sep->se_wait = cp->se_wait; ! 388: #define SWAP(a, b) { char *c = a; a = b; b = c; } ! 389: if (cp->se_user) ! 390: SWAP(sep->se_user, cp->se_user); ! 391: if (cp->se_server) ! 392: SWAP(sep->se_server, cp->se_server); ! 393: for (i = 0; i < MAXARGV; i++) ! 394: SWAP(sep->se_argv[i], cp->se_argv[i]); ! 395: sigsetmask(omask); ! 396: freeconfig(cp); ! 397: } else ! 398: sep = enter(cp); ! 399: sep->se_checked = 1; ! 400: sp = getservbyname(sep->se_service, sep->se_proto); ! 401: if (sp == 0) { ! 402: syslog(LOG_ERR, "%s/%s: unknown service", ! 403: sep->se_service, sep->se_proto); ! 404: continue; ! 405: } ! 406: if (sp->s_port != sep->se_ctrladdr.sin_port) { ! 407: sep->se_ctrladdr.sin_port = sp->s_port; ! 408: if (sep->se_fd != -1) ! 409: (void) close(sep->se_fd); ! 410: sep->se_fd = -1; ! 411: } ! 412: if (sep->se_fd == -1) ! 413: setup(sep); ! 414: } ! 415: endconfig(); ! 416: /* ! 417: * Purge anything not looked at above. ! 418: */ ! 419: omask = sigblock(SIGBLOCK); ! 420: sepp = &servtab; ! 421: while (sep = *sepp) { ! 422: if (sep->se_checked) { ! 423: sepp = &sep->se_next; ! 424: continue; ! 425: } ! 426: *sepp = sep->se_next; ! 427: if (sep->se_fd != -1) { ! 428: FD_CLR(sep->se_fd, &allsock); ! 429: nsock--; ! 430: (void) close(sep->se_fd); ! 431: } ! 432: freeconfig(sep); ! 433: free((char *)sep); ! 434: } ! 435: (void) sigsetmask(omask); ! 436: } ! 437: ! 438: retry() ! 439: { ! 440: register struct servtab *sep; ! 441: ! 442: timingout = 0; ! 443: for (sep = servtab; sep; sep = sep->se_next) ! 444: if (sep->se_fd == -1) ! 445: setup(sep); ! 446: } ! 447: ! 448: setup(sep) ! 449: register struct servtab *sep; ! 450: { ! 451: int on = 1; ! 452: ! 453: if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) { ! 454: syslog(LOG_ERR, "%s/%s: socket: %m", ! 455: sep->se_service, sep->se_proto); ! 456: return; ! 457: } ! 458: #define turnon(fd, opt) \ ! 459: setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) ! 460: if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && ! 461: turnon(sep->se_fd, SO_DEBUG) < 0) ! 462: syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); ! 463: if (turnon(sep->se_fd, SO_REUSEADDR) < 0) ! 464: syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); ! 465: #undef turnon ! 466: if (bind(sep->se_fd, &sep->se_ctrladdr, ! 467: sizeof (sep->se_ctrladdr)) < 0) { ! 468: syslog(LOG_ERR, "%s/%s: bind: %m", ! 469: sep->se_service, sep->se_proto); ! 470: (void) close(sep->se_fd); ! 471: sep->se_fd = -1; ! 472: if (!timingout) { ! 473: timingout = 1; ! 474: alarm(RETRYTIME); ! 475: } ! 476: return; ! 477: } ! 478: if (sep->se_socktype == SOCK_STREAM) ! 479: listen(sep->se_fd, 10); ! 480: FD_SET(sep->se_fd, &allsock); ! 481: nsock++; ! 482: if (sep->se_fd > maxsock) ! 483: maxsock = sep->se_fd; ! 484: } ! 485: ! 486: struct servtab * ! 487: enter(cp) ! 488: struct servtab *cp; ! 489: { ! 490: register struct servtab *sep; ! 491: int omask; ! 492: char *strdup(); ! 493: ! 494: sep = (struct servtab *)malloc(sizeof (*sep)); ! 495: if (sep == (struct servtab *)0) { ! 496: syslog(LOG_ERR, "Out of memory."); ! 497: exit(-1); ! 498: } ! 499: *sep = *cp; ! 500: sep->se_fd = -1; ! 501: omask = sigblock(SIGBLOCK); ! 502: sep->se_next = servtab; ! 503: servtab = sep; ! 504: sigsetmask(omask); ! 505: return (sep); ! 506: } ! 507: ! 508: FILE *fconfig = NULL; ! 509: struct servtab serv; ! 510: char line[256]; ! 511: char *skip(), *nextline(); ! 512: ! 513: setconfig() ! 514: { ! 515: ! 516: if (fconfig != NULL) { ! 517: fseek(fconfig, 0L, L_SET); ! 518: return (1); ! 519: } ! 520: fconfig = fopen(CONFIG, "r"); ! 521: return (fconfig != NULL); ! 522: } ! 523: ! 524: endconfig() ! 525: { ! 526: ! 527: if (fconfig == NULL) ! 528: return; ! 529: fclose(fconfig); ! 530: fconfig = NULL; ! 531: } ! 532: ! 533: struct servtab * ! 534: getconfigent() ! 535: { ! 536: register struct servtab *sep = &serv; ! 537: char *cp, *arg; ! 538: int argc; ! 539: ! 540: more: ! 541: while ((cp = nextline(fconfig)) && *cp == '#') ! 542: ; ! 543: if (cp == NULL) ! 544: return ((struct servtab *)0); ! 545: sep->se_service = strdup(skip(&cp)); ! 546: arg = skip(&cp); ! 547: if (strcmp(arg, "stream") == 0) ! 548: sep->se_socktype = SOCK_STREAM; ! 549: else if (strcmp(arg, "dgram") == 0) ! 550: sep->se_socktype = SOCK_DGRAM; ! 551: else if (strcmp(arg, "rdm") == 0) ! 552: sep->se_socktype = SOCK_RDM; ! 553: else if (strcmp(arg, "seqpacket") == 0) ! 554: sep->se_socktype = SOCK_SEQPACKET; ! 555: else if (strcmp(arg, "raw") == 0) ! 556: sep->se_socktype = SOCK_RAW; ! 557: else ! 558: sep->se_socktype = -1; ! 559: sep->se_proto = strdup(skip(&cp)); ! 560: arg = skip(&cp); ! 561: sep->se_wait = strcmp(arg, "wait") == 0; ! 562: sep->se_user = strdup(skip(&cp)); ! 563: sep->se_server = strdup(skip(&cp)); ! 564: if (strcmp(sep->se_server, "internal") == 0) { ! 565: register struct biltin *bi; ! 566: ! 567: for (bi = biltins; bi->bi_service; bi++) ! 568: if (bi->bi_socktype == sep->se_socktype && ! 569: strcmp(bi->bi_service, sep->se_service) == 0) ! 570: break; ! 571: if (bi->bi_service == 0) { ! 572: syslog(LOG_ERR, "internal service %s unknown\n", ! 573: sep->se_service); ! 574: goto more; ! 575: } ! 576: sep->se_bi = bi; ! 577: sep->se_wait = bi->bi_wait; ! 578: } ! 579: argc = 0; ! 580: for (arg = skip(&cp); cp; arg = skip(&cp)) ! 581: if (argc < MAXARGV) ! 582: sep->se_argv[argc++] = strdup(arg); ! 583: while (argc <= MAXARGV) ! 584: sep->se_argv[argc++] = NULL; ! 585: return (sep); ! 586: } ! 587: ! 588: freeconfig(cp) ! 589: register struct servtab *cp; ! 590: { ! 591: int i; ! 592: ! 593: if (cp->se_service) ! 594: free(cp->se_service); ! 595: if (cp->se_proto) ! 596: free(cp->se_proto); ! 597: if (cp->se_user) ! 598: free(cp->se_user); ! 599: if (cp->se_server) ! 600: free(cp->se_server); ! 601: for (i = 0; i < MAXARGV; i++) ! 602: if (cp->se_argv[i]) ! 603: free(cp->se_argv[i]); ! 604: } ! 605: ! 606: char * ! 607: skip(cpp) ! 608: char **cpp; ! 609: { ! 610: register char *cp = *cpp; ! 611: char *start; ! 612: ! 613: again: ! 614: while (*cp == ' ' || *cp == '\t') ! 615: cp++; ! 616: if (*cp == '\0') { ! 617: char c; ! 618: ! 619: c = getc(fconfig); ! 620: ungetc(c, fconfig); ! 621: if (c == ' ' || c == '\t') ! 622: if (cp = nextline(fconfig)) ! 623: goto again; ! 624: *cpp = (char *)0; ! 625: return ((char *)0); ! 626: } ! 627: start = cp; ! 628: while (*cp && *cp != ' ' && *cp != '\t') ! 629: cp++; ! 630: if (*cp != '\0') ! 631: *cp++ = '\0'; ! 632: *cpp = cp; ! 633: return (start); ! 634: } ! 635: ! 636: char * ! 637: nextline(fd) ! 638: FILE *fd; ! 639: { ! 640: char *cp; ! 641: ! 642: if (fgets(line, sizeof (line), fd) == NULL) ! 643: return ((char *)0); ! 644: cp = index(line, '\n'); ! 645: if (cp) ! 646: *cp = '\0'; ! 647: return (line); ! 648: } ! 649: ! 650: char * ! 651: strdup(cp) ! 652: char *cp; ! 653: { ! 654: char *new; ! 655: ! 656: if (cp == NULL) ! 657: cp = ""; ! 658: new = malloc((unsigned)(strlen(cp) + 1)); ! 659: if (new == (char *)0) { ! 660: syslog(LOG_ERR, "Out of memory."); ! 661: exit(-1); ! 662: } ! 663: strcpy(new, cp); ! 664: return (new); ! 665: } ! 666: ! 667: setproctitle(a, s) ! 668: char *a; ! 669: int s; ! 670: { ! 671: int size; ! 672: register char *cp; ! 673: struct sockaddr_in sin; ! 674: char buf[80]; ! 675: ! 676: cp = Argv[0]; ! 677: size = sizeof(sin); ! 678: if (getpeername(s, &sin, &size) == 0) ! 679: sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); ! 680: else ! 681: sprintf(buf, "-%s", a); ! 682: strncpy(cp, buf, LastArg - cp); ! 683: cp += strlen(cp); ! 684: while (cp < LastArg) ! 685: *cp++ = ' '; ! 686: } ! 687: ! 688: /* ! 689: * Internet services provided internally by inetd: ! 690: */ ! 691: ! 692: /* ARGSUSED */ ! 693: echo_stream(s, sep) /* Echo service -- echo data back */ ! 694: int s; ! 695: struct servtab *sep; ! 696: { ! 697: char buffer[BUFSIZ]; ! 698: int i; ! 699: ! 700: setproctitle("echo", s); ! 701: while ((i = read(s, buffer, sizeof(buffer))) > 0 && ! 702: write(s, buffer, i) > 0) ! 703: ; ! 704: exit(0); ! 705: } ! 706: ! 707: /* ARGSUSED */ ! 708: echo_dg(s, sep) /* Echo service -- echo data back */ ! 709: int s; ! 710: struct servtab *sep; ! 711: { ! 712: char buffer[BUFSIZ]; ! 713: int i, size; ! 714: struct sockaddr sa; ! 715: ! 716: size = sizeof(sa); ! 717: if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) ! 718: return; ! 719: (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); ! 720: } ! 721: ! 722: /* ARGSUSED */ ! 723: discard_stream(s, sep) /* Discard service -- ignore data */ ! 724: int s; ! 725: struct servtab *sep; ! 726: { ! 727: char buffer[BUFSIZ]; ! 728: ! 729: setproctitle("discard", s); ! 730: while (1) { ! 731: while (read(s, buffer, sizeof(buffer)) > 0) ! 732: ; ! 733: if (errno != EINTR) ! 734: break; ! 735: } ! 736: exit(0); ! 737: } ! 738: ! 739: /* ARGSUSED */ ! 740: discard_dg(s, sep) /* Discard service -- ignore data */ ! 741: int s; ! 742: struct servtab *sep; ! 743: { ! 744: char buffer[BUFSIZ]; ! 745: ! 746: (void) read(s, buffer, sizeof(buffer)); ! 747: } ! 748: ! 749: #include <ctype.h> ! 750: #define LINESIZ 72 ! 751: char ring[128]; ! 752: char *endring; ! 753: ! 754: initring() ! 755: { ! 756: register int i; ! 757: ! 758: endring = ring; ! 759: ! 760: for (i = 0; i <= 128; ++i) ! 761: if (isprint(i)) ! 762: *endring++ = i; ! 763: } ! 764: ! 765: /* ARGSUSED */ ! 766: chargen_stream(s, sep) /* Character generator */ ! 767: int s; ! 768: struct servtab *sep; ! 769: { ! 770: char text[LINESIZ+2]; ! 771: register int i; ! 772: register char *rp, *rs, *dp; ! 773: ! 774: setproctitle("discard", s); ! 775: if (endring == 0) ! 776: initring(); ! 777: ! 778: for (rs = ring; ; ++rs) { ! 779: if (rs >= endring) ! 780: rs = ring; ! 781: rp = rs; ! 782: dp = text; ! 783: i = MIN(LINESIZ, endring - rp); ! 784: bcopy(rp, dp, i); ! 785: dp += i; ! 786: if ((rp += i) >= endring) ! 787: rp = ring; ! 788: if (i < LINESIZ) { ! 789: i = LINESIZ - i; ! 790: bcopy(rp, dp, i); ! 791: dp += i; ! 792: if ((rp += i) >= endring) ! 793: rp = ring; ! 794: } ! 795: *dp++ = '\r'; ! 796: *dp++ = '\n'; ! 797: ! 798: if (write(s, text, dp - text) != dp - text) ! 799: break; ! 800: } ! 801: exit(0); ! 802: } ! 803: ! 804: /* ARGSUSED */ ! 805: chargen_dg(s, sep) /* Character generator */ ! 806: int s; ! 807: struct servtab *sep; ! 808: { ! 809: char text[LINESIZ+2]; ! 810: register int i; ! 811: register char *rp; ! 812: static char *rs = ring; ! 813: struct sockaddr sa; ! 814: int size; ! 815: ! 816: if (endring == 0) ! 817: initring(); ! 818: ! 819: size = sizeof(sa); ! 820: if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) ! 821: return; ! 822: rp = rs; ! 823: if (rs++ >= endring) ! 824: rs = ring; ! 825: i = MIN(LINESIZ - 2, endring - rp); ! 826: bcopy(rp, text, i); ! 827: if ((rp += i) >= endring) ! 828: rp = ring; ! 829: if (i < LINESIZ - 2) { ! 830: bcopy(rp, text, i); ! 831: if ((rp += i) >= endring) ! 832: rp = ring; ! 833: } ! 834: text[LINESIZ - 2] = '\r'; ! 835: text[LINESIZ - 1] = '\n'; ! 836: ! 837: (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); ! 838: } ! 839: ! 840: /* ! 841: * Return a machine readable date and time, in the form of the ! 842: * number of seconds since midnight, Jan 1, 1900. Since gettimeofday ! 843: * returns the number of seconds since midnight, Jan 1, 1970, ! 844: * we must add 2208988800 seconds to this figure to make up for ! 845: * some seventy years Bell Labs was asleep. ! 846: */ ! 847: ! 848: long ! 849: machtime() ! 850: { ! 851: struct timeval tv; ! 852: ! 853: if (gettimeofday(&tv, (struct timezone *)0) < 0) { ! 854: fprintf(stderr, "Unable to get time of day\n"); ! 855: return (0L); ! 856: } ! 857: return (htonl((long)tv.tv_sec + 2208988800)); ! 858: } ! 859: ! 860: /* ARGSUSED */ ! 861: machtime_stream(s, sep) ! 862: int s; ! 863: struct servtab *sep; ! 864: { ! 865: long result; ! 866: ! 867: result = machtime(); ! 868: (void) write(s, (char *) &result, sizeof(result)); ! 869: } ! 870: ! 871: /* ARGSUSED */ ! 872: machtime_dg(s, sep) ! 873: int s; ! 874: struct servtab *sep; ! 875: { ! 876: long result; ! 877: struct sockaddr sa; ! 878: int size; ! 879: ! 880: size = sizeof(sa); ! 881: if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) ! 882: return; ! 883: result = machtime(); ! 884: (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); ! 885: } ! 886: ! 887: /* ARGSUSED */ ! 888: daytime_stream(s, sep) /* Return human-readable time of day */ ! 889: int s; ! 890: struct servtab *sep; ! 891: { ! 892: char buffer[256]; ! 893: time_t time(), clock; ! 894: char *ctime(); ! 895: ! 896: clock = time((time_t *) 0); ! 897: ! 898: sprintf(buffer, "%s\r", ctime(&clock)); ! 899: (void) write(s, buffer, strlen(buffer)); ! 900: } ! 901: ! 902: /* ARGSUSED */ ! 903: daytime_dg(s, sep) /* Return human-readable time of day */ ! 904: int s; ! 905: struct servtab *sep; ! 906: { ! 907: char buffer[256]; ! 908: time_t time(), clock; ! 909: struct sockaddr sa; ! 910: int size; ! 911: char *ctime(); ! 912: ! 913: clock = time((time_t *) 0); ! 914: ! 915: size = sizeof(sa); ! 916: if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) ! 917: return; ! 918: sprintf(buffer, "%s\r", ctime(&clock)); ! 919: (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); ! 920: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.