From 94ae9fcacb9cd5e70c293a55d838de48cda0d985 Mon Sep 17 00:00:00 2001 From: Jan-Simon Pendry Date: Mon, 4 Apr 1994 19:36:06 -0800 Subject: [PATCH] eliminate local version of glob (cf ftp) clean up yacc grammar. prettiness police. SCCS-vsn: libexec/ftpd/Makefile 8.2 SCCS-vsn: libexec/ftpd/popen.c 8.2 SCCS-vsn: libexec/ftpd/ftpd.c 8.2 SCCS-vsn: libexec/ftpd/ftpcmd.y 8.2 SCCS-vsn: libexec/ftpd/extern.h 8.2 --- usr/src/libexec/ftpd/Makefile | 7 +- usr/src/libexec/ftpd/extern.h | 63 ++-- usr/src/libexec/ftpd/ftpcmd.y | 642 ++++++++++++++++++---------------- usr/src/libexec/ftpd/ftpd.c | 231 ++++++------ usr/src/libexec/ftpd/popen.c | 77 ++-- 5 files changed, 533 insertions(+), 487 deletions(-) diff --git a/usr/src/libexec/ftpd/Makefile b/usr/src/libexec/ftpd/Makefile index 82d701e0b7..75c960e52d 100644 --- a/usr/src/libexec/ftpd/Makefile +++ b/usr/src/libexec/ftpd/Makefile @@ -1,10 +1,9 @@ -# @(#)Makefile 8.1 (Berkeley) %G% +# @(#)Makefile 8.2 (Berkeley) %G% PROG= ftpd -CFLAGS+=-I${.CURDIR}/../../usr.bin/ftp -DSETPROCTITLE -SRCS= ftpd.c ftpcmd.c glob.c logwtmp.c popen.c vers.c +CFLAGS+=-DSETPROCTITLE +SRCS= ftpd.c ftpcmd.c logwtmp.c popen.c MAN8= ftpd.0 CLEANFILES+=ftpcmd.c y.tab.h -.PATH: ${.CURDIR}/../../usr.bin/ftp .include diff --git a/usr/src/libexec/ftpd/extern.h b/usr/src/libexec/ftpd/extern.h index 94f74eb544..6f0a818118 100644 --- a/usr/src/libexec/ftpd/extern.h +++ b/usr/src/libexec/ftpd/extern.h @@ -4,37 +4,36 @@ * * %sccs.include.redist.c% * - * @(#)extern.h 8.1 (Berkeley) %G% + * @(#)extern.h 8.2 (Berkeley) %G% */ -void blkfree __P((char **)); -char **copyblk __P((char **)); -void cwd __P((char *)); -void delete __P((char *)); -void dologout __P((int)); -void fatal __P((char *)); -int ftpd_pclose __P((FILE *)); -FILE *ftpd_popen __P((char *, char *)); -char **ftpglob __P((char *)); -char *getline __P((char *, int, FILE *)); -void logwtmp __P((char *, char *, char *)); -void lreply __P((int, const char *, ...)); -void makedir __P((char *)); -void nack __P((char *)); -void pass __P((char *)); -void passive __P((void)); -void perror_reply __P((int, char *)); -void pwd __P((void)); -void removedir __P((char *)); -void renamecmd __P((char *, char *)); -char *renamefrom __P((char *)); -void reply __P((int, const char *, ...)); -void retrieve __P((char *, char *)); -void send_file_list __P((char *)); -void setproctitle __P((const char *, ...)); -void statcmd __P((void)); -void statfilecmd __P((char *)); -void store __P((char *, char *, int)); -void upper __P((char *)); -void user __P((char *)); -char *yyerror __P((char *)); +void blkfree __P((char **)); +char **copyblk __P((char **)); +void cwd __P((char *)); +void delete __P((char *)); +void dologout __P((int)); +void fatal __P((char *)); +int ftpd_pclose __P((FILE *)); +FILE *ftpd_popen __P((char *, char *)); +char *getline __P((char *, int, FILE *)); +void logwtmp __P((char *, char *, char *)); +void lreply __P((int, const char *, ...)); +void makedir __P((char *)); +void nack __P((char *)); +void pass __P((char *)); +void passive __P((void)); +void perror_reply __P((int, char *)); +void pwd __P((void)); +void removedir __P((char *)); +void renamecmd __P((char *, char *)); +char *renamefrom __P((char *)); +void reply __P((int, const char *, ...)); +void retrieve __P((char *, char *)); +void send_file_list __P((char *)); +void setproctitle __P((const char *, ...)); +void statcmd __P((void)); +void statfilecmd __P((char *)); +void store __P((char *, char *, int)); +void upper __P((char *)); +void user __P((char *)); +void yyerror __P((char *)); diff --git a/usr/src/libexec/ftpd/ftpcmd.y b/usr/src/libexec/ftpd/ftpcmd.y index 3e546d888b..437e7c6ed5 100644 --- a/usr/src/libexec/ftpd/ftpcmd.y +++ b/usr/src/libexec/ftpd/ftpcmd.y @@ -1,10 +1,10 @@ /* - * Copyright (c) 1985, 1988, 1993 + * Copyright (c) 1985, 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * * %sccs.include.redist.c% * - * @(#)ftpcmd.y 8.1 (Berkeley) %G% + * @(#)ftpcmd.y 8.2 (Berkeley) %G% */ /* @@ -15,7 +15,7 @@ %{ #ifndef lint -static char sccsid[] = "@(#)ftpcmd.y 8.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)ftpcmd.y 8.2 (Berkeley) %G%"; #endif /* not lint */ #include @@ -25,17 +25,19 @@ static char sccsid[] = "@(#)ftpcmd.y 8.1 (Berkeley) %G%"; #include #include -#include -#include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include #include -#include #include #include +#include +#include +#include + #include "extern.h" extern struct sockaddr_in data_dest; @@ -51,7 +53,6 @@ extern int maxtimeout; extern int pdata; extern char hostname[], remotehost[]; extern char proctitle[]; -extern char *globerr; extern int usedefault; extern int transflag; extern char tmpline[]; @@ -64,11 +65,16 @@ char *fromname; %} +%union { + int i; + char *s; +} + %token A B C E F I L N P R S T - SP CRLF COMMA STRING NUMBER + SP CRLF COMMA USER PASS ACCT REIN QUIT PORT PASV TYPE STRU MODE RETR STOR @@ -82,30 +88,39 @@ char *fromname; LEXERR +%token STRING +%token NUMBER + +%type check_login octal_number byte_size +%type struct_code mode_code type_code form_code +%type pathstring pathname password username + %start cmd_list %% -cmd_list: /* empty */ - | cmd_list cmd - = { +cmd_list + : /* empty */ + | cmd_list cmd + { fromname = (char *) 0; } - | cmd_list rcmd + | cmd_list rcmd ; -cmd: USER SP username CRLF - = { - user((char *) $3); - free((char *) $3); +cmd + : USER SP username CRLF + { + user($3); + free($3); } - | PASS SP password CRLF - = { - pass((char *) $3); - free((char *) $3); + | PASS SP password CRLF + { + pass($3); + free($3); } - | PORT SP host_port CRLF - = { + | PORT SP host_port CRLF + { usedefault = 0; if (pdata >= 0) { (void) close(pdata); @@ -113,12 +128,12 @@ cmd: USER SP username CRLF } reply(200, "PORT command successful."); } - | PASV CRLF - = { + | PASV CRLF + { passive(); } - | TYPE SP type_code CRLF - = { + | TYPE SP type_code CRLF + { switch (cmd_type) { case TYPE_A: @@ -152,8 +167,8 @@ cmd: USER SP username CRLF #endif /* NBBY == 8 */ } } - | STRU SP struct_code CRLF - = { + | STRU SP struct_code CRLF + { switch ($3) { case STRU_F: @@ -164,8 +179,8 @@ cmd: USER SP username CRLF reply(504, "Unimplemented STRU type."); } } - | MODE SP mode_code CRLF - = { + | MODE SP mode_code CRLF + { switch ($3) { case MODE_S: @@ -176,114 +191,114 @@ cmd: USER SP username CRLF reply(502, "Unimplemented MODE type."); } } - | ALLO SP NUMBER CRLF - = { + | ALLO SP NUMBER CRLF + { reply(202, "ALLO command ignored."); } - | ALLO SP NUMBER SP R SP NUMBER CRLF - = { + | ALLO SP NUMBER SP R SP NUMBER CRLF + { reply(202, "ALLO command ignored."); } - | RETR check_login SP pathname CRLF - = { + | RETR check_login SP pathname CRLF + { if ($2 && $4 != NULL) - retrieve((char *) 0, (char *) $4); + retrieve((char *) 0, $4); if ($4 != NULL) - free((char *) $4); + free($4); } - | STOR check_login SP pathname CRLF - = { + | STOR check_login SP pathname CRLF + { if ($2 && $4 != NULL) - store((char *) $4, "w", 0); + store($4, "w", 0); if ($4 != NULL) - free((char *) $4); + free($4); } - | APPE check_login SP pathname CRLF - = { + | APPE check_login SP pathname CRLF + { if ($2 && $4 != NULL) - store((char *) $4, "a", 0); + store($4, "a", 0); if ($4 != NULL) - free((char *) $4); + free($4); } - | NLST check_login CRLF - = { + | NLST check_login CRLF + { if ($2) send_file_list("."); } - | NLST check_login SP STRING CRLF - = { + | NLST check_login SP STRING CRLF + { if ($2 && $4 != NULL) - send_file_list((char *) $4); + send_file_list($4); if ($4 != NULL) - free((char *) $4); + free($4); } - | LIST check_login CRLF - = { + | LIST check_login CRLF + { if ($2) retrieve("/bin/ls -lgA", ""); } - | LIST check_login SP pathname CRLF - = { + | LIST check_login SP pathname CRLF + { if ($2 && $4 != NULL) - retrieve("/bin/ls -lgA %s", (char *) $4); + retrieve("/bin/ls -lgA %s", $4); if ($4 != NULL) - free((char *) $4); + free($4); } - | STAT check_login SP pathname CRLF - = { + | STAT check_login SP pathname CRLF + { if ($2 && $4 != NULL) - statfilecmd((char *) $4); + statfilecmd($4); if ($4 != NULL) - free((char *) $4); + free($4); } - | STAT CRLF - = { + | STAT CRLF + { statcmd(); } - | DELE check_login SP pathname CRLF - = { + | DELE check_login SP pathname CRLF + { if ($2 && $4 != NULL) - delete((char *) $4); + delete($4); if ($4 != NULL) - free((char *) $4); + free($4); } - | RNTO SP pathname CRLF - = { + | RNTO SP pathname CRLF + { if (fromname) { - renamecmd(fromname, (char *) $3); + renamecmd(fromname, $3); free(fromname); fromname = (char *) 0; } else { reply(503, "Bad sequence of commands."); } - free((char *) $3); + free($3); } - | ABOR CRLF - = { + | ABOR CRLF + { reply(225, "ABOR command successful."); } - | CWD check_login CRLF - = { + | CWD check_login CRLF + { if ($2) cwd(pw->pw_dir); } - | CWD check_login SP pathname CRLF - = { + | CWD check_login SP pathname CRLF + { if ($2 && $4 != NULL) - cwd((char *) $4); + cwd($4); if ($4 != NULL) - free((char *) $4); + free($4); } - | HELP CRLF - = { + | HELP CRLF + { help(cmdtab, (char *) 0); } - | HELP SP STRING CRLF - = { - register char *cp = (char *)$3; + | HELP SP STRING CRLF + { + char *cp = $3; if (strncasecmp(cp, "SITE", 4) == 0) { - cp = (char *)$3 + 4; + cp = $3 + 4; if (*cp == ' ') cp++; if (*cp) @@ -291,46 +306,46 @@ cmd: USER SP username CRLF else help(sitetab, (char *) 0); } else - help(cmdtab, (char *) $3); + help(cmdtab, $3); } - | NOOP CRLF - = { + | NOOP CRLF + { reply(200, "NOOP command successful."); } - | MKD check_login SP pathname CRLF - = { + | MKD check_login SP pathname CRLF + { if ($2 && $4 != NULL) - makedir((char *) $4); + makedir($4); if ($4 != NULL) - free((char *) $4); + free($4); } - | RMD check_login SP pathname CRLF - = { + | RMD check_login SP pathname CRLF + { if ($2 && $4 != NULL) - removedir((char *) $4); + removedir($4); if ($4 != NULL) - free((char *) $4); + free($4); } - | PWD check_login CRLF - = { + | PWD check_login CRLF + { if ($2) pwd(); } - | CDUP check_login CRLF - = { + | CDUP check_login CRLF + { if ($2) cwd(".."); } - | SITE SP HELP CRLF - = { + | SITE SP HELP CRLF + { help(sitetab, (char *) 0); } - | SITE SP HELP SP STRING CRLF - = { - help(sitetab, (char *) $5); + | SITE SP HELP SP STRING CRLF + { + help(sitetab, $5); } - | SITE SP UMASK check_login CRLF - = { + | SITE SP UMASK check_login CRLF + { int oldmask; if ($4) { @@ -339,8 +354,8 @@ cmd: USER SP username CRLF reply(200, "Current UMASK is %03o", oldmask); } } - | SITE SP UMASK check_login SP octal_number CRLF - = { + | SITE SP UMASK check_login SP octal_number CRLF + { int oldmask; if ($4) { @@ -354,28 +369,28 @@ cmd: USER SP username CRLF } } } - | SITE SP CHMOD check_login SP octal_number SP pathname CRLF - = { + | SITE SP CHMOD check_login SP octal_number SP pathname CRLF + { if ($4 && ($8 != NULL)) { if ($6 > 0777) reply(501, "CHMOD: Mode value must be between 0 and 0777"); - else if (chmod((char *) $8, $6) < 0) - perror_reply(550, (char *) $8); + else if (chmod($8, $6) < 0) + perror_reply(550, $8); else reply(200, "CHMOD command successful."); } if ($8 != NULL) - free((char *) $8); + free($8); } - | SITE SP IDLE CRLF - = { + | SITE SP IDLE CRLF + { reply(200, "Current IDLE time limit is %d seconds; max %d", timeout, maxtimeout); } - | SITE SP IDLE SP NUMBER CRLF - = { + | SITE SP IDLE SP NUMBER CRLF + { if ($5 < 30 || $5 > maxtimeout) { reply(501, "Maximum IDLE time must be between 30 and %d seconds", @@ -388,15 +403,15 @@ cmd: USER SP username CRLF timeout); } } - | STOU check_login SP pathname CRLF - = { + | STOU check_login SP pathname CRLF + { if ($2 && $4 != NULL) - store((char *) $4, "w", 1); + store($4, "w", 1); if ($4 != NULL) - free((char *) $4); + free($4); } - | SYST CRLF - = { + | SYST CRLF + { #ifdef unix #ifdef BSD reply(215, "UNIX Type: L%d Version: BSD-%d", @@ -416,12 +431,12 @@ cmd: USER SP username CRLF * Return size of file in a format suitable for * using with RESTART (we just count bytes). */ - | SIZE check_login SP pathname CRLF - = { + | SIZE check_login SP pathname CRLF + { if ($2 && $4 != NULL) - sizecmd((char *) $4); + sizecmd($4); if ($4 != NULL) - free((char *) $4); + free($4); } /* @@ -433,18 +448,17 @@ cmd: USER SP username CRLF * where xxx is the fractional second (of any precision, * not necessarily 3 digits) */ - | MDTM check_login SP pathname CRLF - = { + | MDTM check_login SP pathname CRLF + { if ($2 && $4 != NULL) { struct stat stbuf; - if (stat((char *) $4, &stbuf) < 0) + if (stat($4, &stbuf) < 0) reply(550, "%s: %s", - (char *)$4, strerror(errno)); - else if ((stbuf.st_mode&S_IFMT) != S_IFREG) { - reply(550, "%s: not a plain file.", - (char *) $4); + $4, strerror(errno)); + else if (!S_ISREG(stbuf.st_mode)) { + reply(550, "%s: not a plain file.", $4); } else { - register struct tm *t; + struct tm *t; t = gmtime(&stbuf.st_mtime); reply(213, "19%02d%02d%02d%02d%02d%02d", @@ -453,48 +467,53 @@ cmd: USER SP username CRLF } } if ($4 != NULL) - free((char *) $4); + free($4); } - | QUIT CRLF - = { + | QUIT CRLF + { reply(221, "Goodbye."); dologout(0); } - | error CRLF - = { + | error CRLF + { yyerrok; } ; -rcmd: RNFR check_login SP pathname CRLF - = { +rcmd + : RNFR check_login SP pathname CRLF + { char *renamefrom(); if ($2 && $4) { - fromname = renamefrom((char *) $4); + fromname = renamefrom($4); if (fromname == (char *) 0 && $4) { - free((char *) $4); + free($4); } } } ; -username: STRING +username + : STRING ; -password: /* empty */ - = { - *(char **)&($$) = (char *)calloc(1, sizeof(char)); +password + : /* empty */ + { + $$ = (char *)calloc(1, sizeof(char)); } - | STRING + | STRING ; -byte_size: NUMBER +byte_size + : NUMBER ; -host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA +host_port + : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER - = { - register char *a, *p; + { + char *a, *p; a = (char *)&data_dest.sin_addr; a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; @@ -504,146 +523,161 @@ host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA } ; -form_code: N - = { - $$ = FORM_N; - } - | T - = { - $$ = FORM_T; - } - | C - = { - $$ = FORM_C; - } +form_code + : N + { + $$ = FORM_N; + } + | T + { + $$ = FORM_T; + } + | C + { + $$ = FORM_C; + } ; -type_code: A - = { - cmd_type = TYPE_A; - cmd_form = FORM_N; - } - | A SP form_code - = { - cmd_type = TYPE_A; - cmd_form = $3; - } - | E - = { - cmd_type = TYPE_E; - cmd_form = FORM_N; - } - | E SP form_code - = { - cmd_type = TYPE_E; - cmd_form = $3; - } - | I - = { - cmd_type = TYPE_I; - } - | L - = { - cmd_type = TYPE_L; - cmd_bytesz = NBBY; - } - | L SP byte_size - = { - cmd_type = TYPE_L; - cmd_bytesz = $3; - } - /* this is for a bug in the BBN ftp */ - | L byte_size - = { - cmd_type = TYPE_L; - cmd_bytesz = $2; - } +type_code + : A + { + cmd_type = TYPE_A; + cmd_form = FORM_N; + } + | A SP form_code + { + cmd_type = TYPE_A; + cmd_form = $3; + } + | E + { + cmd_type = TYPE_E; + cmd_form = FORM_N; + } + | E SP form_code + { + cmd_type = TYPE_E; + cmd_form = $3; + } + | I + { + cmd_type = TYPE_I; + } + | L + { + cmd_type = TYPE_L; + cmd_bytesz = NBBY; + } + | L SP byte_size + { + cmd_type = TYPE_L; + cmd_bytesz = $3; + } + /* this is for a bug in the BBN ftp */ + | L byte_size + { + cmd_type = TYPE_L; + cmd_bytesz = $2; + } ; -struct_code: F - = { - $$ = STRU_F; - } - | R - = { - $$ = STRU_R; - } - | P - = { - $$ = STRU_P; - } +struct_code + : F + { + $$ = STRU_F; + } + | R + { + $$ = STRU_R; + } + | P + { + $$ = STRU_P; + } ; -mode_code: S - = { - $$ = MODE_S; - } - | B - = { - $$ = MODE_B; - } - | C - = { - $$ = MODE_C; - } +mode_code + : S + { + $$ = MODE_S; + } + | B + { + $$ = MODE_B; + } + | C + { + $$ = MODE_C; + } ; -pathname: pathstring - = { - /* - * Problem: this production is used for all pathname - * processing, but only gives a 550 error reply. - * This is a valid reply in some cases but not in others. - */ - if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) { - *(char **)&($$) = *ftpglob((char *) $1); - if (globerr != NULL) { - reply(550, globerr); - $$ = NULL; - } - free((char *) $1); - } else - $$ = $1; - } +pathname + : pathstring + { + /* + * Problem: this production is used for all pathname + * processing, but only gives a 550 error reply. + * This is a valid reply in some cases but not in others. + */ + if (logged_in && $1 && *$1 == '~') { + glob_t gl; + int flags = GLOB_BRACE|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (glob($1, flags, NULL, &gl)) { + reply(550, "not found"); + $$ = NULL; + } else { + $$ = strdup(gl.gl_pathv[0]); + } + globfree(&gl); + free($1); + } else + $$ = $1; + } ; -pathstring: STRING +pathstring + : STRING ; -octal_number: NUMBER - = { - register int ret, dec, multby, digit; +octal_number + : NUMBER + { + int ret, dec, multby, digit; - /* - * Convert a number that was read as decimal number - * to what it would be if it had been read as octal. - */ - dec = $1; - multby = 1; - ret = 0; - while (dec) { - digit = dec%10; - if (digit > 7) { - ret = -1; - break; + /* + * Convert a number that was read as decimal number + * to what it would be if it had been read as octal. + */ + dec = $1; + multby = 1; + ret = 0; + while (dec) { + digit = dec%10; + if (digit > 7) { + ret = -1; + break; + } + ret += digit * multby; + multby *= 8; + dec /= 10; } - ret += digit * multby; - multby *= 8; - dec /= 10; + $$ = ret; } - $$ = ret; - } ; -check_login: /* empty */ - = { - if (logged_in) - $$ = 1; - else { - reply(530, "Please login with USER and PASS."); - $$ = 0; + +check_login + : /* empty */ + { + if (logged_in) + $$ = 1; + else { + reply(530, "Please login with USER and PASS."); + $$ = 0; + } } - } ; %% @@ -737,7 +771,7 @@ static int yylex __P((void)); static struct tab * lookup(p, cmd) - register struct tab *p; + struct tab *p; char *cmd; { @@ -756,9 +790,9 @@ char * getline(s, n, iop) char *s; int n; - register FILE *iop; + FILE *iop; { - register c; + int c; register char *cs; cs = s; @@ -845,8 +879,8 @@ static int yylex() { static int cpos, state; - register char *cp, *cp2; - register struct tab *p; + char *cp, *cp2; + struct tab *p; int n; char c; @@ -885,7 +919,7 @@ yylex() /* NOTREACHED */ } state = p->state; - *(char **)&yylval = p->name; + yylval.s = p->name; return (p->token); } break; @@ -911,7 +945,7 @@ yylex() /* NOTREACHED */ } state = p->state; - *(char **)&yylval = p->name; + yylval.s = p->name; return (p->token); } state = CMD; @@ -950,7 +984,7 @@ yylex() */ if (n > 1 && cbuf[cpos] == '\n') { cbuf[cpos] = '\0'; - *(char **)&yylval = copy(cp); + yylval.s = copy(cp); cbuf[cpos] = '\n'; state = ARGS; return (STRING); @@ -968,7 +1002,7 @@ yylex() ; c = cbuf[cpos]; cbuf[cpos] = '\0'; - yylval = atoi(cp); + yylval.i = atoi(cp); cbuf[cpos] = c; state = STR1; return (NUMBER); @@ -983,7 +1017,7 @@ yylex() ; c = cbuf[cpos]; cbuf[cpos] = '\0'; - yylval = atoi(cp); + yylval.i = atoi(cp); cbuf[cpos] = c; return (NUMBER); } @@ -1061,7 +1095,7 @@ yylex() void upper(s) - register char *s; + char *s; { while (*s != '\0') { if (islower(*s)) @@ -1088,8 +1122,8 @@ help(ctab, s) struct tab *ctab; char *s; { - register struct tab *c; - register int width, NCMDS; + struct tab *c; + int width, NCMDS; char *type; if (ctab == sitetab) @@ -1106,7 +1140,7 @@ help(ctab, s) } width = (width + 8) &~ 7; if (s == 0) { - register int i, j, w; + int i, j, w; int columns, lines; lreply(214, "The following %scommands are recognized %s.", @@ -1156,24 +1190,22 @@ sizecmd(filename) case TYPE_L: case TYPE_I: { struct stat stbuf; - if (stat(filename, &stbuf) < 0 || - (stbuf.st_mode&S_IFMT) != S_IFREG) + if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) reply(550, "%s: not a plain file.", filename); else - reply(213, "%lu", stbuf.st_size); - break;} + reply(213, "%qu", stbuf.st_size); + break; } case TYPE_A: { FILE *fin; - register int c; - register long count; + int c; + off_t count; struct stat stbuf; fin = fopen(filename, "r"); if (fin == NULL) { perror_reply(550, filename); return; } - if (fstat(fileno(fin), &stbuf) < 0 || - (stbuf.st_mode&S_IFMT) != S_IFREG) { + if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) { reply(550, "%s: not a plain file.", filename); (void) fclose(fin); return; @@ -1187,8 +1219,8 @@ sizecmd(filename) } (void) fclose(fin); - reply(213, "%ld", count); - break;} + reply(213, "%qd", count); + break; } default: reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); } diff --git a/usr/src/libexec/ftpd/ftpd.c b/usr/src/libexec/ftpd/ftpd.c index 7aaec859c1..09dc72d955 100644 --- a/usr/src/libexec/ftpd/ftpd.c +++ b/usr/src/libexec/ftpd/ftpd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1985, 1988, 1990, 1992, 1993 + * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * %sccs.include.redist.c% @@ -7,12 +7,12 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993\n\ +"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)ftpd.c 8.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)ftpd.c 8.2 (Berkeley) %G%"; #endif /* not lint */ /* @@ -33,20 +33,24 @@ static char sccsid[] = "@(#)ftpd.c 8.1 (Berkeley) %G%"; #include #include -#include +#include #include +#include +#include #include -#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include #include -#include #include #include +#include +#include +#include + #include "pathnames.h" #include "extern.h" @@ -56,8 +60,9 @@ static char sccsid[] = "@(#)ftpd.c 8.1 (Berkeley) %G%"; #include #endif +static char version[] = "Version 6.00"; + extern off_t restart_point; -extern char *home; /* pointer to home directory for glob */ extern char cbuf[]; struct sockaddr_in ctrl_addr; @@ -81,7 +86,7 @@ int stru; /* avoid C keyword */ int mode; int usedefault = 1; /* for data transfers */ int pdata = -1; /* for passive mode */ -int transflag; +sig_atomic_t transflag; off_t file_size; off_t byte_count; #if !defined(CMASK) || CMASK == 0 @@ -107,11 +112,9 @@ int swaitint = SWAITINT; #ifdef SETPROCTITLE char **Argv = NULL; /* pointer to argument vector */ char *LastArgv = NULL; /* end of argv */ -char proctitle[BUFSIZ]; /* initial part of title */ +char proctitle[LINE_MAX]; /* initial part of title */ #endif /* SETPROCTITLE */ -#define MAXLINE 256 - #define LOGCMD(cmd, file) \ if (logging > 1) \ syslog(LOG_INFO,"%s %s%s", cmd, \ @@ -166,8 +169,8 @@ main(argc, argv, envp) char *argv[]; char **envp; { - int addrlen, on = 1, tos; - char *cp, line[MAXLINE]; + int addrlen, ch, on = 1, tos; + char *cp, line[LINE_MAX]; FILE *fd; /* @@ -175,12 +178,12 @@ main(argc, argv, envp) * necessary for anonymous ftp's that chroot and can't do it later. */ openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); - addrlen = sizeof (his_addr); + addrlen = sizeof(his_addr); if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); exit(1); } - addrlen = sizeof (ctrl_addr); + addrlen = sizeof(ctrl_addr); if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); exit(1); @@ -202,14 +205,8 @@ main(argc, argv, envp) LastArgv = envp[-1] + strlen(envp[-1]); #endif /* SETPROCTITLE */ - argc--, argv++; - while (argc > 0 && *argv[0] == '-') { - for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { - - case 'v': - debug = 1; - break; - + while ((ch = getopt(argc, argv, "dlt:T:u:v")) != EOF) { + switch (ch) { case 'd': debug = 1; break; @@ -219,37 +216,37 @@ main(argc, argv, envp) break; case 't': - timeout = atoi(++cp); + timeout = atoi(optarg); if (maxtimeout < timeout) maxtimeout = timeout; - goto nextopt; + break; case 'T': - maxtimeout = atoi(++cp); + maxtimeout = atoi(optarg); if (timeout > maxtimeout) timeout = maxtimeout; - goto nextopt; + break; case 'u': { - int val = 0; + long val = 0; - while (*++cp && *cp >= '0' && *cp <= '9') - val = val*8 + *cp - '0'; - if (*cp) - fprintf(stderr, "ftpd: Bad value for -u\n"); + val = strtol(optarg, &optarg, 8); + if (*optarg != '\0' || val < 0) + warnx("bad value for -u"); else defumask = val; - goto nextopt; + break; } + case 'v': + debug = 1; + break; + default: - fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n", - *cp); + warnx("unknown flag -%c ignored", optopt); break; } -nextopt: - argc--, argv++; } (void) freopen(_PATH_DEVNULL, "w", stderr); (void) signal(SIGPIPE, lostconn); @@ -280,7 +277,7 @@ nextopt: /* If logins are disabled, print out the message. */ if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { - while (fgets(line, sizeof (line), fd) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; lreply(530, "%s", line); @@ -291,7 +288,7 @@ nextopt: exit(0); } if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { - while (fgets(line, sizeof (line), fd) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; lreply(220, "%s", line); @@ -300,7 +297,7 @@ nextopt: (void) fclose(fd); /* reply(220,) must follow */ } - (void) gethostname(hostname, sizeof (hostname)); + (void) gethostname(hostname, sizeof(hostname)); reply(220, "%s FTP server (%s) ready.", hostname, version); (void) setjmp(errcatch); for (;;) @@ -312,6 +309,7 @@ static void lostconn(signo) int signo; { + if (debug) syslog(LOG_DEBUG, "lost connection"); dologout(-1); @@ -347,8 +345,7 @@ sgetpwnam(name) char *name; { static struct passwd save; - register struct passwd *p; - char *sgetsave(); + struct passwd *p; if ((p = getpwnam(name)) == NULL) return (p); @@ -387,8 +384,7 @@ void user(name) char *name; { - register char *cp; - char *shell; + char *cp, *shell; if (logged_in) { if (guest) { @@ -451,10 +447,9 @@ static int checkuser(name) char *name; { - register FILE *fd; - register char *p; - char line[BUFSIZ]; + FILE *fd; int found = 0; + char *p, line[BUFSIZ]; if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) { while (fgets(line, sizeof(line), fd) != NULL) @@ -492,7 +487,7 @@ void pass(passwd) char *passwd; { - char *xpasswd, *salt; + char *salt, *xpasswd; FILE *fd; if (logged_in || askpasswd == 0) { @@ -563,9 +558,9 @@ pass(passwd) * N.B. reply(230,) must follow the message. */ if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { - char *cp, line[MAXLINE]; + char *cp, line[LINE_MAX]; - while (fgets(line, sizeof (line), fd) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; lreply(230, "%s", line); @@ -576,7 +571,8 @@ pass(passwd) if (guest) { reply(230, "Guest login ok, access restrictions apply."); #ifdef SETPROCTITLE - sprintf(proctitle, "%s: anonymous/%.*s", remotehost, + snprintf(proctitle, sizeof(proctitle), + "%s: anonymous/%.*s", remotehost, sizeof(proctitle) - sizeof(remotehost) - sizeof(": anonymous/"), passwd); setproctitle(proctitle); @@ -584,17 +580,16 @@ pass(passwd) if (logging) syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", remotehost, passwd); - home = "/"; /* guest home dir for globbing */ } else { reply(230, "User %s logged in.", pw->pw_name); #ifdef SETPROCTITLE - sprintf(proctitle, "%s: %s", remotehost, pw->pw_name); + snprintf(proctitle, sizeof(proctitle), + "%s: %s", remotehost, pw->pw_name); setproctitle(proctitle); #endif /* SETPROCTITLE */ if (logging) syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", remotehost, pw->pw_name); - home = pw->pw_dir; /* home dir for globbing */ } (void) umask(defumask); return; @@ -609,7 +604,7 @@ retrieve(cmd, name) { FILE *fin, *dout; struct stat st; - int (*closefunc)(); + int (*closefunc) __P((FILE *)); if (cmd == 0) { fin = fopen(name, "r"), closefunc = fclose; @@ -632,8 +627,7 @@ retrieve(cmd, name) return; } byte_count = -1; - if (cmd == 0 && - (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) { + if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { reply(550, "%s: not a plain file.", name); goto done; } @@ -657,7 +651,7 @@ store(name, mode, unique) { FILE *fout, *din; struct stat st; - int (*closefunc)(); + int (*closefunc) __P((FILE *)); if (unique && stat(name, &st) == 0 && (name = gunique(name)) == NULL) { @@ -694,8 +688,7 @@ static FILE * getdatasock(mode) char *mode; { - int s, on = 1, tries; - int t; + int on = 1, s, t, tries; if (data >= 0) return (fdopen(data, mode)); @@ -704,14 +697,14 @@ getdatasock(mode) if (s < 0) goto bad; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (char *) &on, sizeof (on)) < 0) + (char *) &on, sizeof(on)) < 0) goto bad; /* anchor socket to avoid multi-homing problems */ data_source.sin_family = AF_INET; data_source.sin_addr = ctrl_addr.sin_addr; for (tries = 1; ; tries++) { if (bind(s, (struct sockaddr *)&data_source, - sizeof (data_source)) >= 0) + sizeof(data_source)) >= 0) break; if (errno != EADDRINUSE || tries > 10) goto bad; @@ -746,7 +739,7 @@ dataconn(name, size, mode) file_size = size; byte_count = 0; if (size != (off_t) -1) - (void) sprintf (sizebuf, " (%qd bytes)", size); + (void) sprintf(sizebuf, " (%qd bytes)", size); else (void) strcpy(sizebuf, ""); if (pdata >= 0) { @@ -758,7 +751,7 @@ dataconn(name, size, mode) reply(425, "Can't open data connection."); (void) close(pdata); pdata = -1; - return(NULL); + return (NULL); } (void) close(pdata); pdata = s; @@ -769,7 +762,7 @@ dataconn(name, size, mode) #endif reply(150, "Opening %s mode data connection for '%s'%s.", type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); - return(fdopen(pdata, mode)); + return (fdopen(pdata, mode)); } if (data >= 0) { reply(125, "Using existing data connection for '%s'%s.", @@ -789,7 +782,7 @@ dataconn(name, size, mode) } data = fileno(file); while (connect(data, (struct sockaddr *)&data_dest, - sizeof (data_dest)) < 0) { + sizeof(data_dest)) < 0) { if (errno == EADDRINUSE && retry < swaitmax) { sleep((unsigned) swaitint); retry += swaitint; @@ -816,9 +809,8 @@ send_data(instr, outstr, blksize) FILE *instr, *outstr; off_t blksize; { - register int c, cnt; - register char *buf; - int netfd, filefd; + int c, cnt, filefd, netfd; + char *buf; transflag++; if (setjmp(urgcatch)) { @@ -893,7 +885,7 @@ static int receive_data(instr, outstr) FILE *instr, *outstr; { - register int c; + int c; int cnt, bare_lfs = 0; char buf[BUFSIZ]; @@ -906,7 +898,7 @@ receive_data(instr, outstr) case TYPE_I: case TYPE_L: - while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) { + while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { if (write(fileno(outstr), buf, cnt) != cnt) goto file_err; byte_count += cnt; @@ -970,9 +962,9 @@ void statfilecmd(filename) char *filename; { - char line[BUFSIZ]; FILE *fin; int c; + char line[LINE_MAX]; (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename); fin = ftpd_popen(line, "r"); @@ -1055,6 +1047,7 @@ void fatal(s) char *s; { + reply(451, "Error in server: %s\n", s); reply(221, "Closing connection due to server error."); dologout(0); @@ -1117,6 +1110,7 @@ static void ack(s) char *s; { + reply(250, "%s command successful.", s); } @@ -1124,11 +1118,12 @@ void nack(s) char *s; { + reply(502, "%s command not implemented.", s); } /* ARGSUSED */ -char * +void yyerror(s) char *s; { @@ -1169,6 +1164,7 @@ void cwd(path) char *path; { + if (chdir(path) < 0) perror_reply(550, path); else @@ -1179,6 +1175,7 @@ void makedir(name) char *name; { + LOGCMD("mkdir", name); if (mkdir(name, 0777) < 0) perror_reply(550, name); @@ -1190,6 +1187,7 @@ void removedir(name) char *name; { + LOGCMD("rmdir", name); if (rmdir(name) < 0) perror_reply(550, name); @@ -1226,6 +1224,7 @@ void renamecmd(from, to) char *from, *to; { + LOGCMD2("rename", from, to); if (rename(from, to) < 0) perror_reply(550, "rename"); @@ -1238,15 +1237,15 @@ dolog(sin) struct sockaddr_in *sin; { struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, - sizeof (struct in_addr), AF_INET); + sizeof(struct in_addr), AF_INET); if (hp) - (void) strncpy(remotehost, hp->h_name, sizeof (remotehost)); + (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)); else (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), - sizeof (remotehost)); + sizeof(remotehost)); #ifdef SETPROCTITLE - sprintf(proctitle, "%s: connected", remotehost); + snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost); setproctitle(proctitle); #endif /* SETPROCTITLE */ @@ -1262,6 +1261,7 @@ void dologout(status) int status; { + if (logged_in) { (void) seteuid((uid_t)0); logwtmp(ttyline, "", ""); @@ -1310,7 +1310,7 @@ void passive() { int len; - register char *p, *a; + char *p, *a; pdata = socket(AF_INET, SOCK_STREAM, 0); if (pdata < 0) { @@ -1365,7 +1365,7 @@ gunique(local) *cp = '\0'; if (stat(cp ? local : ".", &st) < 0) { perror_reply(553, cp ? local : "."); - return((char *) 0); + return ((char *) 0); } if (cp) *cp = '/'; @@ -1375,10 +1375,10 @@ gunique(local) for (count = 1; count < 100; count++) { (void)sprintf(cp, "%d", count); if (stat(new, &st) < 0) - return(new); + return (new); } reply(452, "Unique file name cannot be created."); - return(NULL); + return (NULL); } /* @@ -1389,6 +1389,7 @@ perror_reply(code, string) int code; char *string; { + reply(code, "%s: %s.", string, strerror(errno)); } @@ -1398,38 +1399,40 @@ static char *onefile[] = { }; void -send_file_list(whichfiles) - char *whichfiles; +send_file_list(whichf) + char *whichf; { struct stat st; DIR *dirp = NULL; struct dirent *dir; FILE *dout = NULL; - register char **dirlist, *dirname; + char **dirlist, *dirname; int simple = 0; + int freeglob = 0; + glob_t gl; - if (strpbrk(whichfiles, "~{[*?") != NULL) { - extern char *globerr; + if (strpbrk(whichf, "~{[*?") != NULL) { - globerr = NULL; - dirlist = ftpglob(whichfiles); - if (globerr != NULL) { - reply(550, globerr); - return; - } else if (dirlist == NULL) { + memset(&gl, 0, sizeof(gl)); + freeglob = 1; + if (glob(whichf, GLOB_BRACE|GLOB_QUOTE|GLOB_TILDE, 0, &gl)) { + reply(550, "not found"); + goto out; + } else if (gl.gl_pathc == 0) { errno = ENOENT; - perror_reply(550, whichfiles); - return; + perror_reply(550, whichf); + goto out; } + dirlist = gl.gl_pathv; } else { - onefile[0] = whichfiles; + onefile[0] = whichf; dirlist = onefile; simple = 1; } if (setjmp(urgcatch)) { transflag = 0; - return; + goto out; } while (dirname = *dirlist++) { if (stat(dirname, &st) < 0) { @@ -1440,30 +1443,30 @@ send_file_list(whichfiles) if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) { retrieve("/bin/ls %s", dirname); - return; + goto out; } - perror_reply(550, whichfiles); + perror_reply(550, whichf); if (dout != NULL) { (void) fclose(dout); transflag = 0; data = -1; pdata = -1; } - return; + goto out; } - if ((st.st_mode&S_IFMT) == S_IFREG) { + if (S_ISREG(st.st_mode)) { if (dout == NULL) { dout = dataconn("file list", (off_t)-1, "w"); if (dout == NULL) - return; + goto out; transflag++; } fprintf(dout, "%s%s\n", dirname, type == TYPE_A ? "\r" : ""); byte_count += strlen(dirname) + 1; continue; - } else if ((st.st_mode&S_IFMT) != S_IFDIR) + } else if (!S_ISDIR(st.st_mode)) continue; if ((dirp = opendir(dirname)) == NULL) @@ -1485,12 +1488,12 @@ send_file_list(whichfiles) * not a directory or special file. */ if (simple || (stat(nbuf, &st) == 0 && - (st.st_mode&S_IFMT) == S_IFREG)) { + S_ISREG(st.st_mode))) { if (dout == NULL) { dout = dataconn("file list", (off_t)-1, "w"); if (dout == NULL) - return; + goto out; transflag++; } if (nbuf[0] == '.' && nbuf[1] == '/') @@ -1517,6 +1520,11 @@ send_file_list(whichfiles) (void) fclose(dout); data = -1; pdata = -1; +out: + if (freeglob) { + freeglob = 0; + globfree(&gl); + } } #ifdef SETPROCTITLE @@ -1534,10 +1542,11 @@ setproctitle(fmt, va_alist) va_dcl #endif { - register char *p, *bp, ch; - register int i; + int i; va_list ap; - char buf[BUFSIZ]; + char *p, *bp, ch; + char buf[LINE_MAX]; + #if __STDC__ va_start(ap, fmt); #else diff --git a/usr/src/libexec/ftpd/popen.c b/usr/src/libexec/ftpd/popen.c index 3fec3b65ec..1f5a0bc135 100644 --- a/usr/src/libexec/ftpd/popen.c +++ b/usr/src/libexec/ftpd/popen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1988, 1993 + * Copyright (c) 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software written by Ken Arnold and @@ -10,21 +10,24 @@ */ #ifndef lint -static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)popen.c 8.2 (Berkeley) %G%"; #endif /* not lint */ #include #include +#include +#include #include -#include #include #include #include +#include + #include "extern.h" /* - * Special version of popen which avoids call to shell. This insures noone + * Special version of popen which avoids call to shell. This ensures noone * may create a pipe to a hidden program as a side effect of a list or dir * command. */ @@ -35,23 +38,23 @@ FILE * ftpd_popen(program, type) char *program, *type; { - register char *cp; + char *cp; FILE *iop; int argc, gargc, pdes[2], pid; - char **pop, *argv[100], *gargv[1000], *vv[2]; + char **pop, *argv[100], *gargv[1000]; if (*type != 'r' && *type != 'w' || type[1]) - return(NULL); + return (NULL); if (!pids) { if ((fds = getdtablesize()) <= 0) - return(NULL); + return (NULL); if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL) - return(NULL); + return (NULL); memset(pids, 0, fds * sizeof(int)); } if (pipe(pdes) < 0) - return(NULL); + return (NULL); /* break up string into pieces */ for (argc = 0, cp = program;; cp = NULL) @@ -61,14 +64,16 @@ ftpd_popen(program, type) /* glob each piece */ gargv[0] = argv[0]; for (gargc = argc = 1; argv[argc]; argc++) { - if (!(pop = ftpglob(argv[argc]))) { /* globbing failed */ - vv[0] = argv[argc]; - vv[1] = NULL; - pop = copyblk(vv); - } - argv[argc] = (char *)pop; /* save to free later */ - while (*pop && gargc < 1000) - gargv[gargc++] = *pop++; + glob_t gl; + int flags = GLOB_BRACE|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (glob(argv[argc], flags, NULL, &gl)) + gargv[gargc++] = strdup(argv[argc]); + else + for (pop = gl.gl_pathv; *pop; pop++) + gargv[gargc++] = strdup(*pop); + globfree(&gl); } gargv[gargc] = NULL; @@ -81,15 +86,15 @@ ftpd_popen(program, type) /* NOTREACHED */ case 0: /* child */ if (*type == 'r') { - if (pdes[1] != 1) { - dup2(pdes[1], 1); - dup2(pdes[1], 2); /* stderr, too! */ + if (pdes[1] != STDOUT_FILENO) { + dup2(pdes[1], STDOUT_FILENO); (void)close(pdes[1]); } + dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */ (void)close(pdes[0]); } else { - if (pdes[0] != 0) { - dup2(pdes[0], 0); + if (pdes[0] != STDIN_FILENO) { + dup2(pdes[0], STDIN_FILENO); (void)close(pdes[0]); } (void)close(pdes[1]); @@ -107,32 +112,34 @@ ftpd_popen(program, type) } pids[fileno(iop)] = pid; -pfree: for (argc = 1; argv[argc] != NULL; argc++) { - blkfree((char **)argv[argc]); - free((char *)argv[argc]); - } - return(iop); +pfree: for (argc = 1; gargv[argc] != NULL; argc++) + free(gargv[argc]); + + return (iop); } int ftpd_pclose(iop) FILE *iop; { - register int fdes; - int omask; - union wait stat_loc; - int pid; + int fdes, omask, status; + pid_t pid; /* * pclose returns -1 if stream is not associated with a * `popened' command, or, if already `pclosed'. */ if (pids == 0 || pids[fdes = fileno(iop)] == 0) - return(-1); + return (-1); (void)fclose(iop); omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); - while ((pid = wait((int *)&stat_loc)) != pids[fdes] && pid != -1); + while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR) + continue; (void)sigsetmask(omask); pids[fdes] = 0; - return(pid == -1 ? -1 : stat_loc.w_status); + if (pid < 0) + return (pid); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + return (1); } -- 2.20.1