|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)ftpd.c 4.28 (Berkeley) 9/22/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * FTP server. ! 7: */ ! 8: #include <sys/param.h> ! 9: #include <sys/stat.h> ! 10: #include <sys/ioctl.h> ! 11: #include <sys/file.h> ! 12: #include <wait.h> ! 13: ! 14: #include <sys/inet/in.h> ! 15: ! 16: #include "ftp.h" ! 17: ! 18: #include <stdio.h> ! 19: #include <signal.h> ! 20: #include <pwd.h> ! 21: #include <setjmp.h> ! 22: #include <errno.h> ! 23: ! 24: /* ! 25: * File containing login names ! 26: * NOT to be used on this machine. ! 27: * Commonly used to disallow uucp. ! 28: */ ! 29: #define FTPUSERS "/etc/ftpusers" ! 30: ! 31: extern int errno; ! 32: extern char *sys_errlist[]; ! 33: extern char *crypt(); ! 34: extern char version[]; ! 35: extern char *home; /* pointer to home directory for glob */ ! 36: extern FILE *popen(), *fopen(); ! 37: extern int pclose(), fclose(); ! 38: ! 39: struct socket { ! 40: unsigned short sport; ! 41: unsigned short dport; ! 42: long saddr; ! 43: long daddr; ! 44: } his_addr, data_dest, data_source, ctrl_addr; ! 45: ! 46: int data; ! 47: jmp_buf errcatch; ! 48: int logged_in; ! 49: struct passwd *pw; ! 50: int debug; ! 51: int timeout; ! 52: int logging; ! 53: int guest; ! 54: int type; ! 55: int form; ! 56: int stru; /* avoid C keyword */ ! 57: int mode; ! 58: int usedefault = 1; /* for data transfers */ ! 59: char hostname[32]; ! 60: char remotehost[32]; ! 61: ! 62: ! 63: /* ! 64: * Timeout intervals for retrying connections ! 65: * to hosts that don't accept PORT cmds. This ! 66: * is a kludge, but given the problems with TCP... ! 67: */ ! 68: #define SWAITMAX 90 /* wait at most 90 seconds */ ! 69: #define SWAITINT 5 /* interval between retries */ ! 70: ! 71: int swaitmax = SWAITMAX; ! 72: int swaitint = SWAITINT; ! 73: ! 74: int lostconn(); ! 75: int reapchild(); ! 76: int getdatasock(); ! 77: FILE *dataconn(); ! 78: ! 79: main(argc, argv) ! 80: int argc; ! 81: char *argv[]; ! 82: { ! 83: int ctrl, s, options = 0; ! 84: char *cp; ! 85: int dev; ! 86: struct in_service *servp; ! 87: ! 88: servp = in_service("ftp", "tcp", 0); ! 89: if (servp == 0) { ! 90: fprintf(stderr, "ftpd: ftp/tcp: unknown service\n"); ! 91: exit(1); ! 92: } ! 93: ctrl_addr.sport = servp->port; ! 94: data_source.sport = servp->port - 1; ! 95: while (argc > 0 && *argv[0] == '-') { ! 96: for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { ! 97: ! 98: case 'v': ! 99: debug = 1; ! 100: break; ! 101: ! 102: case 'd': ! 103: debug = 1; ! 104: break; ! 105: ! 106: case 'l': ! 107: logging = 1; ! 108: break; ! 109: ! 110: case 't': ! 111: timeout = atoi(++cp); ! 112: goto nextopt; ! 113: break; ! 114: ! 115: default: ! 116: fprintf(stderr, "Unknown flag -%c ignored.\n", *cp); ! 117: break; ! 118: } ! 119: nextopt: ! 120: argc--, argv++; ! 121: } ! 122: signal(SIGPIPE, SIG_IGN); ! 123: signal(SIGHUP, SIG_IGN); ! 124: ! 125: do { ! 126: s = tcp_sock(); ! 127: if (s < 0) { ! 128: perror("ftpd: socket");; ! 129: sleep(5); ! 130: continue; ! 131: } ! 132: if (tcp_listen(s, servp->port, 0, 0) < 0) { ! 133: close(s); ! 134: s = -1; ! 135: sleep(30); ! 136: continue; ! 137: } ! 138: } while (s < 0); ! 139: ! 140: signal(SIGCHLD, reapchild); ! 141: for (;;) { ! 142: int ctrl; ! 143: ! 144: ctrl = tcp_accept(s, &his_addr.saddr, &his_addr.sport, &dev); ! 145: fprintf(stderr, "accept req from %s, port %d\n", inet_ntoa(his_addr.saddr), his_addr.sport); ! 146: if (ctrl < 0) { ! 147: if (errno == EINTR) ! 148: continue; ! 149: perror("ftpd: accept"); ! 150: sleep(1); ! 151: continue; ! 152: } ! 153: switch(fork()) { ! 154: case -1: ! 155: printf("Out of processes\n"); ! 156: break; ! 157: case 0: ! 158: signal (SIGCHLD, SIG_IGN); ! 159: dolog(&his_addr); ! 160: close(s); ! 161: dup2(ctrl, 0), close(ctrl), dup2(0, 1); ! 162: /* ! 163: * Set up default state ! 164: */ ! 165: logged_in = 0; ! 166: data = -1; ! 167: type = TYPE_A; ! 168: form = FORM_N; ! 169: stru = STRU_F; ! 170: mode = MODE_S; ! 171: /* try to do this equivalently ! 172: (void) getsockname(0, &ctrl_addr, sizeof (ctrl_addr)); ! 173: gethostname(hostname, sizeof (hostname)); ! 174: */ ! 175: reply(220, "%s FTP server (%s) ready.", ! 176: hostname, version); ! 177: for (;;) { ! 178: setjmp(errcatch); ! 179: yyparse(); ! 180: } ! 181: } ! 182: close(ctrl); ! 183: } ! 184: } ! 185: ! 186: reapchild() ! 187: { ! 188: union wait status; ! 189: ! 190: while (wait3(&status, WNOHANG, 0) > 0) ! 191: ; ! 192: } ! 193: ! 194: lostconn() ! 195: { ! 196: ! 197: if (debug) ! 198: fprintf(stderr, "Lost connection.\n"); ! 199: dologout(-1); ! 200: } ! 201: ! 202: pass(passwd) ! 203: char *passwd; ! 204: { ! 205: char *xpasswd, *savestr(); ! 206: static struct passwd save; ! 207: ! 208: if (logged_in || pw == NULL) { ! 209: reply(503, "Login with USER first."); ! 210: return; ! 211: } ! 212: if (!guest) { /* "ftp" is only account allowed no password */ ! 213: xpasswd = crypt(passwd, pw->pw_passwd); ! 214: if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) { ! 215: reply(530, "Login incorrect."); ! 216: pw = NULL; ! 217: return; ! 218: } ! 219: } ! 220: setegid(pw->pw_gid); ! 221: /* initgroups(pw->pw_name, pw->pw_gid); */ ! 222: if (chdir(pw->pw_dir)) { ! 223: reply(550, "User %s: can't change directory to $s.", ! 224: pw->pw_name, pw->pw_dir); ! 225: goto bad; ! 226: } ! 227: if (guest && chroot(pw->pw_dir) < 0) { ! 228: reply(550, "Can't set guest privileges."); ! 229: goto bad; ! 230: } ! 231: if (!guest) ! 232: reply(230, "User %s logged in.", pw->pw_name); ! 233: else ! 234: reply(230, "Guest login ok, access restrictions apply."); ! 235: logged_in = 1; ! 236: dologin(pw); ! 237: seteuid(pw->pw_uid); ! 238: /* ! 239: * Save everything so globbing doesn't ! 240: * clobber the fields. ! 241: */ ! 242: save = *pw; ! 243: save.pw_name = savestr(pw->pw_name); ! 244: save.pw_passwd = savestr(pw->pw_passwd); ! 245: save.pw_comment = savestr(pw->pw_comment); ! 246: save.pw_gecos = savestr(pw->pw_gecos, &save.pw_gecos); ! 247: save.pw_dir = savestr(pw->pw_dir); ! 248: save.pw_shell = savestr(pw->pw_shell); ! 249: pw = &save; ! 250: home = pw->pw_dir; /* home dir for globbing */ ! 251: return; ! 252: bad: ! 253: seteuid(0); ! 254: pw = NULL; ! 255: } ! 256: ! 257: char * ! 258: savestr(s) ! 259: char *s; ! 260: { ! 261: char *malloc(); ! 262: char *new = malloc(strlen(s) + 1); ! 263: ! 264: if (new != NULL) ! 265: strcpy(new, s); ! 266: return (new); ! 267: } ! 268: ! 269: retrieve(cmd, name) ! 270: char *cmd, *name; ! 271: { ! 272: FILE *fin, *dout; ! 273: struct stat st; ! 274: int (*closefunc)(); ! 275: ! 276: st.st_size = 0; ! 277: if (cmd == 0 && ! 278: (stat(name, &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) { ! 279: reply(550, "%s: not a plain file.", name); ! 280: goto done; ! 281: } ! 282: dout = dataconn(name, st.st_size, "w"); ! 283: if (dout == NULL) ! 284: goto done; ! 285: if (cmd == 0) { ! 286: #ifdef notdef ! 287: /* no remote command execution -- it's a security hole */ ! 288: if (*name == '|') ! 289: fin = popen(name + 1, "r"), closefunc = pclose; ! 290: else ! 291: #endif ! 292: fin = fopen(name, "r"), closefunc = fclose; ! 293: } else { ! 294: char line[BUFSIZ]; ! 295: ! 296: sprintf(line, cmd, name), name = line; ! 297: fin = popen(line, "r"), closefunc = pclose; ! 298: } ! 299: if (fin == NULL) { ! 300: if (errno != 0) ! 301: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 302: return; ! 303: } ! 304: if (send_data(fin, dout) || ferror(dout)) ! 305: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 306: else ! 307: reply(226, "Transfer complete."); ! 308: fclose(dout), data = -1; ! 309: done: ! 310: (*closefunc)(fin); ! 311: } ! 312: ! 313: store(name, mode) ! 314: char *name, *mode; ! 315: { ! 316: FILE *fout, *din; ! 317: int (*closefunc)(), dochown = 0; ! 318: ! 319: din = dataconn(name, (off_t)-1, "r"); ! 320: if (din == NULL) ! 321: goto done; ! 322: #ifdef notdef ! 323: /* no remote command execution -- it's a security hole */ ! 324: if (name[0] == '|') ! 325: fout = popen(&name[1], "w"), closefunc = pclose; ! 326: else ! 327: #endif ! 328: { ! 329: struct stat st; ! 330: ! 331: if (stat(name, &st) < 0) ! 332: dochown++; ! 333: fout = fopen(name, mode), closefunc = fclose; ! 334: } ! 335: if (fout == NULL) { ! 336: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 337: return; ! 338: } ! 339: if (receive_data(din, fout) || ferror(fout)) ! 340: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 341: else ! 342: reply(226, "Transfer complete."); ! 343: fclose(din), data = -1; ! 344: done: ! 345: if (dochown) ! 346: (void) chown(name, pw->pw_uid, -1); ! 347: (*closefunc)(fout); ! 348: } ! 349: ! 350: getdatasock(mode) ! 351: char *mode; ! 352: { ! 353: int s; ! 354: ! 355: if (data >= 0) ! 356: return (data); ! 357: data_source.saddr = ctrl_addr.saddr; ! 358: s = tcp_sock(); ! 359: if (s < 0) { ! 360: perror("ftpd: socket");; ! 361: return(NULL); ! 362: } ! 363: ! 364: seteuid(pw->pw_uid); ! 365: return (s); ! 366: } ! 367: ! 368: FILE * ! 369: dataconn(name, size, mode) ! 370: char *name; ! 371: off_t size; ! 372: char *mode; ! 373: { ! 374: char sizebuf[32]; ! 375: FILE *file; ! 376: int retry = 0; ! 377: ! 378: if (size >= 0) ! 379: sprintf (sizebuf, " (%ld bytes)", size); ! 380: else ! 381: (void) strcpy(sizebuf, ""); ! 382: if (data >= 0) { ! 383: reply(125, "Using existing data connection for %s%s.", ! 384: name, sizebuf); ! 385: usedefault = 1; ! 386: return (fdopen(data, mode)); ! 387: } ! 388: if (usedefault) ! 389: data_dest = his_addr; ! 390: usedefault = 1; ! 391: data = getdatasock(mode); ! 392: if (data < 0) { ! 393: reply(425, "Can't create data socket (%s,%d): %s.", ! 394: inet_ntoa(data_source.saddr), ! 395: ntohs(data_source.sport), ! 396: sys_errlist[errno]); ! 397: return (NULL); ! 398: } ! 399: reply(150, "Opening data connection for %s (%s,%d)%s.", ! 400: name, ! 401: inet_ntoa(data_dest.saddr), ! 402: data_dest.sport, sizebuf); ! 403: ! 404: while (tcp_connect(data, 0, data_dest.saddr, data_dest.sport) < 0) { ! 405: data = -1; ! 406: if (retry < swaitmax) { ! 407: data = getdatasock(mode); ! 408: sleep(swaitint); ! 409: retry += swaitint; ! 410: continue; ! 411: } ! 412: reply(425, "Can't build data connection: %s.", ! 413: sys_errlist[errno]); ! 414: (void)fclose(file); ! 415: return (NULL); ! 416: } ! 417: return (fdopen(data, mode)); ! 418: } ! 419: ! 420: /* ! 421: * Tranfer the contents of "instr" to ! 422: * "outstr" peer using the appropriate ! 423: * encapulation of the date subject ! 424: * to Mode, Structure, and Type. ! 425: * ! 426: * NB: Form isn't handled. ! 427: */ ! 428: send_data(instr, outstr) ! 429: FILE *instr, *outstr; ! 430: { ! 431: register int c; ! 432: int netfd, filefd, cnt; ! 433: char buf[BUFSIZ]; ! 434: ! 435: switch (type) { ! 436: ! 437: case TYPE_A: ! 438: while ((c = getc(instr)) != EOF) { ! 439: if (c == '\n') { ! 440: if (ferror (outstr)) ! 441: return (1); ! 442: putc('\r', outstr); ! 443: } ! 444: putc(c, outstr); ! 445: if (c == '\r') ! 446: putc ('\0', outstr); ! 447: } ! 448: if (ferror (instr) || ferror (outstr)) ! 449: return (1); ! 450: return (0); ! 451: ! 452: case TYPE_I: ! 453: case TYPE_L: ! 454: netfd = fileno(outstr); ! 455: filefd = fileno(instr); ! 456: ! 457: while ((cnt = read(filefd, buf, sizeof (buf))) > 0) ! 458: if (write(netfd, buf, cnt) < 0) ! 459: return (1); ! 460: return (cnt < 0); ! 461: } ! 462: reply(504,"Unimplemented TYPE %d in send_data", type); ! 463: return (1); ! 464: } ! 465: ! 466: /* ! 467: * Transfer data from peer to ! 468: * "outstr" using the appropriate ! 469: * encapulation of the data subject ! 470: * to Mode, Structure, and Type. ! 471: * ! 472: * N.B.: Form isn't handled. ! 473: */ ! 474: receive_data(instr, outstr) ! 475: FILE *instr, *outstr; ! 476: { ! 477: register int c; ! 478: int cnt; ! 479: char buf[BUFSIZ]; ! 480: ! 481: ! 482: switch (type) { ! 483: ! 484: case TYPE_I: ! 485: case TYPE_L: ! 486: while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) ! 487: if (write(fileno(outstr), buf, cnt) < 0) ! 488: return (1); ! 489: return (cnt < 0); ! 490: ! 491: case TYPE_E: ! 492: reply(504, "TYPE E not implemented."); ! 493: return (1); ! 494: ! 495: case TYPE_A: ! 496: while ((c = getc(instr)) != EOF) { ! 497: if (c == '\r') { ! 498: if (ferror (outstr)) ! 499: return (1); ! 500: if ((c = getc(instr)) != '\n') ! 501: putc ('\r', outstr); ! 502: if (c == '\0') ! 503: continue; ! 504: } ! 505: putc (c, outstr); ! 506: } ! 507: if (ferror (instr) || ferror (outstr)) ! 508: return (1); ! 509: return (0); ! 510: } ! 511: fatal("Unknown type in receive_data."); ! 512: /*NOTREACHED*/ ! 513: } ! 514: ! 515: fatal(s) ! 516: char *s; ! 517: { ! 518: reply(451, "Error in server: %s\n", s); ! 519: reply(221, "Closing connection due to server error."); ! 520: dologout(0); ! 521: } ! 522: ! 523: reply(n, s, args) ! 524: int n; ! 525: char *s; ! 526: { ! 527: ! 528: printf("%d ", n); ! 529: _doprnt(s, &args, stdout); ! 530: printf("\r\n"); ! 531: fflush(stdout); ! 532: if (debug) { ! 533: fprintf(stderr, "<--- %d ", n); ! 534: _doprnt(s, &args, stderr); ! 535: fprintf(stderr, "\n"); ! 536: fflush(stderr); ! 537: } ! 538: } ! 539: ! 540: lreply(n, s, args) ! 541: int n; ! 542: char *s; ! 543: { ! 544: printf("%d-", n); ! 545: _doprnt(s, &args, stdout); ! 546: printf("\r\n"); ! 547: fflush(stdout); ! 548: if (debug) { ! 549: fprintf(stderr, "<--- %d-", n); ! 550: _doprnt(s, &args, stderr); ! 551: fprintf(stderr, "\n"); ! 552: } ! 553: } ! 554: ! 555: replystr(s) ! 556: char *s; ! 557: { ! 558: printf("%s\r\n", s); ! 559: fflush(stdout); ! 560: if (debug) ! 561: fprintf(stderr, "<--- %s\n", s); ! 562: } ! 563: ! 564: ack(s) ! 565: char *s; ! 566: { ! 567: reply(200, "%s command okay.", s); ! 568: } ! 569: ! 570: nack(s) ! 571: char *s; ! 572: { ! 573: reply(502, "%s command not implemented.", s); ! 574: } ! 575: ! 576: yyerror() ! 577: { ! 578: reply(500, "Command not understood."); ! 579: } ! 580: ! 581: delete(name) ! 582: char *name; ! 583: { ! 584: struct stat st; ! 585: ! 586: if (stat(name, &st) < 0) { ! 587: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 588: return; ! 589: } ! 590: if ((st.st_mode&S_IFMT) == S_IFDIR) { ! 591: if (rmdir(name) < 0) { ! 592: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 593: return; ! 594: } ! 595: goto done; ! 596: } ! 597: if (unlink(name) < 0) { ! 598: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 599: return; ! 600: } ! 601: done: ! 602: ack("DELE"); ! 603: } ! 604: ! 605: cwd(path) ! 606: char *path; ! 607: { ! 608: ! 609: if (chdir(path) < 0) { ! 610: reply(550, "%s: %s.", path, sys_errlist[errno]); ! 611: return; ! 612: } ! 613: ack("CWD"); ! 614: } ! 615: ! 616: makedir(name) ! 617: char *name; ! 618: { ! 619: struct stat st; ! 620: int dochown = stat(name, &st) < 0; ! 621: ! 622: if (mkdir(name, 0777) < 0) { ! 623: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 624: return; ! 625: } ! 626: if (dochown) ! 627: (void) chown(name, pw->pw_uid, -1); ! 628: ack("MKDIR"); ! 629: } ! 630: ! 631: removedir(name) ! 632: char *name; ! 633: { ! 634: ! 635: if (rmdir(name) < 0) { ! 636: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 637: return; ! 638: } ! 639: ack("RMDIR"); ! 640: } ! 641: ! 642: #define MAXPATHLEN 256 ! 643: pwd() ! 644: { ! 645: char path[MAXPATHLEN + 1]; ! 646: ! 647: if (getwd(path) == NULL) { ! 648: reply(451, "%s.", path); ! 649: return; ! 650: } ! 651: reply(251, "\"%s\" is current directory.", path); ! 652: } ! 653: ! 654: char * ! 655: renamefrom(name) ! 656: char *name; ! 657: { ! 658: struct stat st; ! 659: ! 660: if (stat(name, &st) < 0) { ! 661: reply(550, "%s: %s.", name, sys_errlist[errno]); ! 662: return ((char *)0); ! 663: } ! 664: reply(350, "File exists, ready for destination name"); ! 665: return (name); ! 666: } ! 667: ! 668: renamecmd(from, to) ! 669: char *from, *to; ! 670: { ! 671: ! 672: if (rename(from, to) < 0) { ! 673: reply(550, "rename: %s.", sys_errlist[errno]); ! 674: return; ! 675: } ! 676: ack("RNTO"); ! 677: } ! 678: ! 679: dolog(addr) ! 680: register struct socket *addr; ! 681: { ! 682: char *h_name = (char *)in_host(addr->saddr); ! 683: time_t t; ! 684: ! 685: strncpy(remotehost, h_name, sizeof (remotehost)); ! 686: if (!logging) ! 687: return; ! 688: t = time(0); ! 689: fprintf(stderr,"FTPD: connection from %s at %s", remotehost, ctime(&t)); ! 690: fflush(stderr); ! 691: } ! 692: ! 693: #include <utmp.h> ! 694: ! 695: #define SCPYN(a, b) strncpy(a, b, sizeof (a)) ! 696: struct utmp utmp; ! 697: ! 698: /* ! 699: * Record login in wtmp file. ! 700: */ ! 701: ! 702: #define O_WRONLY 1 ! 703: #define O_APPEND 1 ! 704: dologin(pw) ! 705: struct passwd *pw; ! 706: { ! 707: int wtmp; ! 708: char line[32]; ! 709: ! 710: wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); ! 711: if (wtmp >= 0) { ! 712: /* hack, but must be unique and no tty line */ ! 713: sprintf(line, "ftp%d", getpid()); ! 714: SCPYN(utmp.ut_line, line); ! 715: SCPYN(utmp.ut_name, pw->pw_name); ! 716: utmp.ut_time = time(0); ! 717: (void) write(wtmp, (char *)&utmp, sizeof (utmp)); ! 718: (void) close(wtmp); ! 719: } ! 720: } ! 721: ! 722: /* ! 723: * Record logout in wtmp file ! 724: * and exit with supplied status. ! 725: */ ! 726: dologout(status) ! 727: int status; ! 728: { ! 729: int wtmp; ! 730: ! 731: if (!logged_in) ! 732: _exit(status); ! 733: seteuid(0); ! 734: wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); ! 735: if (wtmp >= 0) { ! 736: SCPYN(utmp.ut_name, ""); ! 737: utmp.ut_time = time(0); ! 738: (void) write(wtmp, (char *)&utmp, sizeof (utmp)); ! 739: (void) close(wtmp); ! 740: } ! 741: /* beware of flushing buffers after a SIGPIPE */ ! 742: _exit(status); ! 743: } ! 744: ! 745: /* ! 746: * Special version of popen which avoids ! 747: * call to shell. This insures noone may ! 748: * create a pipe to a hidden program as a side ! 749: * effect of a list or dir command. ! 750: */ ! 751: #define tst(a,b) (*mode == 'r'? (b) : (a)) ! 752: #define RDR 0 ! 753: #define WTR 1 ! 754: static int popen_pid[5]; ! 755: ! 756: static char * ! 757: nextarg(cpp) ! 758: char *cpp; ! 759: { ! 760: register char *cp = cpp; ! 761: ! 762: if (cp == 0) ! 763: return (cp); ! 764: while (*cp && *cp != ' ' && *cp != '\t') ! 765: cp++; ! 766: if (*cp == ' ' || *cp == '\t') { ! 767: *cp++ = '\0'; ! 768: while (*cp == ' ' || *cp == '\t') ! 769: cp++; ! 770: } ! 771: if (cp == cpp) ! 772: return ((char *)0); ! 773: return (cp); ! 774: } ! 775: ! 776: FILE * ! 777: popen(cmd, mode) ! 778: char *cmd, *mode; ! 779: { ! 780: int p[2], ac, gac; ! 781: register myside, hisside, pid; ! 782: char *av[20], *gav[512]; ! 783: register char *cp; ! 784: ! 785: if (pipe(p) < 0) ! 786: return (NULL); ! 787: cp = cmd, ac = 0; ! 788: /* break up string into pieces */ ! 789: do { ! 790: av[ac++] = cp; ! 791: cp = nextarg(cp); ! 792: } while (cp && *cp && ac < 20); ! 793: av[ac] = (char *)0; ! 794: gav[0] = av[0]; ! 795: /* glob each piece */ ! 796: for (gac = ac = 1; av[ac] != NULL; ac++) { ! 797: char **pop; ! 798: extern char **glob(); ! 799: ! 800: pop = glob(av[ac]); ! 801: if (pop) { ! 802: av[ac] = (char *)pop; /* save to free later */ ! 803: while (*pop && gac < 512) ! 804: gav[gac++] = *pop++; ! 805: } ! 806: } ! 807: gav[gac] = (char *)0; ! 808: myside = tst(p[WTR], p[RDR]); ! 809: hisside = tst(p[RDR], p[WTR]); ! 810: if ((pid = fork()) == 0) { ! 811: /* myside and hisside reverse roles in child */ ! 812: close(myside); ! 813: dup2(hisside, tst(0, 1)); ! 814: close(hisside); ! 815: execv(gav[0], gav); ! 816: _exit(1); ! 817: } ! 818: for (ac = 1; av[ac] != NULL; ac++) ! 819: blkfree((char **)av[ac]); ! 820: if (pid == -1) ! 821: return (NULL); ! 822: popen_pid[myside] = pid; ! 823: close(hisside); ! 824: return (fdopen(myside, mode)); ! 825: } ! 826: ! 827: pclose(ptr) ! 828: FILE *ptr; ! 829: { ! 830: register f, r, (*hstat)(), (*istat)(), (*qstat)(); ! 831: int status; ! 832: ! 833: f = fileno(ptr); ! 834: fclose(ptr); ! 835: istat = signal(SIGINT, SIG_IGN); ! 836: qstat = signal(SIGQUIT, SIG_IGN); ! 837: hstat = signal(SIGHUP, SIG_IGN); ! 838: while ((r = wait(&status)) != popen_pid[f] && r != -1) ! 839: ; ! 840: if (r == -1) ! 841: status = -1; ! 842: signal(SIGINT, istat); ! 843: signal(SIGQUIT, qstat); ! 844: signal(SIGHUP, hstat); ! 845: return (status); ! 846: } ! 847: ! 848: /* ! 849: * Check user requesting login priviledges. ! 850: * Disallow anyone mentioned in the file FTPUSERS ! 851: * to allow people such as uucp to be avoided. ! 852: */ ! 853: checkuser(name) ! 854: register char *name; ! 855: { ! 856: char line[BUFSIZ], *index(); ! 857: FILE *fd; ! 858: int found = 0; ! 859: ! 860: fd = fopen(FTPUSERS, "r"); ! 861: if (fd == NULL) ! 862: return (1); ! 863: while (fgets(line, sizeof (line), fd) != NULL) { ! 864: register char *cp = index(line, '\n'); ! 865: ! 866: if (cp) ! 867: *cp = '\0'; ! 868: if (strcmp(line, name) == 0) { ! 869: found++; ! 870: break; ! 871: } ! 872: } ! 873: fclose(fd); ! 874: return (!found); ! 875: } ! 876: seteuid(uid) ! 877: { ! 878: return(setuid(uid)); ! 879: } ! 880: setegid(gid) ! 881: { ! 882: return(setgid(gid)); ! 883: } ! 884: ! 885: rename(from, to) ! 886: { ! 887: if (-1 == link(from, to)) ! 888: return(-1); ! 889: return(unlink(from)); ! 890: } ! 891: inet_ntoa(addr) ! 892: long addr; ! 893: { ! 894: static char b[32]; ! 895: unsigned char *xp = (unsigned char *)&addr; ! 896: ! 897: sprintf(b, "%d.%d.%d.%d", xp[3], xp[2], xp[1], xp[0]); ! 898: return(b); ! 899: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.