diff options
| author | lukem <lukem@NetBSD.org> | 1999-12-07 05:30:53 +0000 |
|---|---|---|
| committer | lukem <lukem@NetBSD.org> | 1999-12-07 05:30:53 +0000 |
| commit | 397e2cfc53e82f5d70cf4cebcb325c80bc596b52 (patch) | |
| tree | 3c441bf365c1294ced6a73ba1499d73febf54a3b /libexec | |
| parent | c6dcc983e59f95d94e78c324bd2f65e6590a601a (diff) | |
* change ftpd_popen() to take char *argv[] instead of char *cmd.
the string tokenisation must be performed by the caller (which is
generally easy because it's almost always a static command).
* change do_conversion() to return a char *argv[] instead of char *cmd.
tokenisation of the command is done internally.
* change retrieve() to take char *argv[] instead of char *cmd.
(to take advantage of the above changes). fixes [bin/8173]
* use fparseln() instead of fgetln()
* store conversions in listed order (rather than reverse order)
* use stringlists instead of handrolling code to manage an argv.
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ftpd/Makefile | 6 | ||||
| -rw-r--r-- | libexec/ftpd/conf.c | 164 | ||||
| -rw-r--r-- | libexec/ftpd/extern.h | 10 | ||||
| -rw-r--r-- | libexec/ftpd/ftpcmd.y | 22 | ||||
| -rw-r--r-- | libexec/ftpd/ftpd.c | 59 | ||||
| -rw-r--r-- | libexec/ftpd/popen.c | 85 |
6 files changed, 170 insertions, 176 deletions
diff --git a/libexec/ftpd/Makefile b/libexec/ftpd/Makefile index 92a9ec1111b..6be37484251 100644 --- a/libexec/ftpd/Makefile +++ b/libexec/ftpd/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.35 1999/07/20 09:35:20 mrg Exp $ +# $NetBSD: Makefile,v 1.36 1999/12/07 05:30:53 lukem Exp $ # @(#)Makefile 8.2 (Berkeley) 4/4/94 SRCTOP= ../.. @@ -7,8 +7,8 @@ SRCTOP= ../.. PROG= ftpd SRCS= conf.c ftpd.c ftpcmd.y logwtmp.c popen.c CPPFLAGS+=-DHASSETPROCTITLE -DPADD+= ${LIBCRYPT} -LDADD+= -lcrypt +DPADD+= ${LIBCRYPT} ${LIBUTIL} +LDADD+= -lcrypt -lutil MAN= ftpd.8 MLINKS+=ftpd.8 ftpd.conf.5 diff --git a/libexec/ftpd/conf.c b/libexec/ftpd/conf.c index 56c2e59bc7c..4d5561b3b3a 100644 --- a/libexec/ftpd/conf.c +++ b/libexec/ftpd/conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: conf.c,v 1.22 1999/11/28 04:38:41 lukem Exp $ */ +/* $NetBSD: conf.c,v 1.23 1999/12/07 05:30:54 lukem Exp $ */ /*- * Copyright (c) 1997, 1999 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: conf.c,v 1.22 1999/11/28 04:38:41 lukem Exp $"); +__RCSID("$NetBSD: conf.c,v 1.23 1999/12/07 05:30:54 lukem Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -49,11 +49,12 @@ __RCSID("$NetBSD: conf.c,v 1.22 1999/11/28 04:38:41 lukem Exp $"); #include <glob.h> #include <stdio.h> #include <stdlib.h> -#include <time.h> -#include <unistd.h> #include <string.h> #include <stringlist.h> #include <syslog.h> +#include <time.h> +#include <unistd.h> +#include <util.h> #ifdef KERBEROS5 #include <krb5/krb5.h> @@ -83,16 +84,16 @@ parse_conf(findclass) char *endp; char *class, *word, *arg; const char *infile; - int line; + size_t line; unsigned int timeout; struct ftpconv *conv, *cnext; #define REASSIGN(X,Y) if (X) free(X); (X)=(Y) -#define NEXTWORD(W) while ((W = strsep(&buf, " \t")) != NULL && *W == '\0') +#define NEXTWORD(P, W) while ((W = strsep(&P, " \t")) != NULL && *W == '\0') #define EMPTYSTR(W) (W == NULL || *W == '\0') REASSIGN(curclass.classname, findclass); - for (conv = curclass.conversions; conv != NULL; conv=cnext) { + for (conv = curclass.conversions; conv != NULL; conv = cnext) { REASSIGN(conv->suffix, NULL); REASSIGN(conv->types, NULL); REASSIGN(conv->disable, NULL); @@ -120,25 +121,22 @@ parse_conf(findclass) return; line = 0; - while ((buf = fgetln(f, &len)) != NULL) { + for (; + (buf = fparseln(f, &len, &line, NULL, FPARSELN_UNESCCOMM | + FPARSELN_UNESCCONT | FPARSELN_UNESCESC)) != NULL; + free(buf)) { none = match = 0; - line++; + p = buf; if (len < 1) continue; - if (buf[len - 1] != '\n') { - syslog(LOG_WARNING, - "%s line %d is partially truncated?", infile, line); - continue; - } - buf[--len] = '\0'; - if ((p = strchr(buf, '#')) != NULL) - *p = '\0'; - if (EMPTYSTR(buf)) + if (p[len - 1] == '\n') + p[--len] = '\0'; + if (EMPTYSTR(p)) continue; - NEXTWORD(word); - NEXTWORD(class); - NEXTWORD(arg); + NEXTWORD(p, word); + NEXTWORD(p, class); + NEXTWORD(p, arg); if (EMPTYSTR(word) || EMPTYSTR(class)) continue; if (strcasecmp(class, "none") == 0) @@ -153,45 +151,31 @@ parse_conf(findclass) curclass.checkportcmd = 0; else curclass.checkportcmd = 1; + } else if (strcasecmp(word, "conversion") == 0) { char *suffix, *types, *disable, *convcmd; if (EMPTYSTR(arg)) { syslog(LOG_WARNING, "%s line %d: %s requires a suffix", - infile, line, word); + infile, (int)line, word); continue; /* need a suffix */ } - NEXTWORD(types); - NEXTWORD(disable); - convcmd = buf; + NEXTWORD(p, types); + NEXTWORD(p, disable); + convcmd = p; if (convcmd) convcmd += strspn(convcmd, " \t"); - suffix = strdup(arg); - if (suffix == NULL) { - syslog(LOG_WARNING, "can't strdup"); - continue; - } + suffix = xstrdup(arg); if (none || EMPTYSTR(types) || EMPTYSTR(disable) || EMPTYSTR(convcmd)) { types = NULL; disable = NULL; convcmd = NULL; } else { - types = strdup(types); - disable = strdup(disable); - convcmd = strdup(convcmd); - if (types == NULL || disable == NULL || - convcmd == NULL) { - syslog(LOG_WARNING, "can't strdup"); - if (types) - free(types); - if (disable) - free(disable); - if (convcmd) - free(convcmd); - continue; - } + types = xstrdup(types); + disable = xstrdup(disable); + convcmd = xstrdup(convcmd); } for (conv = curclass.conversions; conv != NULL; conv = conv->next) { @@ -205,19 +189,28 @@ parse_conf(findclass) syslog(LOG_WARNING, "can't malloc"); continue; } - conv->next = curclass.conversions; - curclass.conversions = conv; + conv->next = NULL; + for (cnext = curclass.conversions; + cnext != NULL; cnext = cnext->next) + if (cnext->next == NULL) + break; + if (cnext != NULL) + cnext->next = conv; + else + curclass.conversions = conv; } REASSIGN(conv->suffix, suffix); REASSIGN(conv->types, types); REASSIGN(conv->disable, disable); REASSIGN(conv->command, convcmd); + } else if (strcasecmp(word, "display") == 0) { if (none || EMPTYSTR(arg)) arg = NULL; else - arg = strdup(arg); + arg = xstrdup(arg); REASSIGN(curclass.display, arg); + } else if (strcasecmp(word, "maxtimeout") == 0) { if (none || EMPTYSTR(arg)) continue; @@ -225,40 +218,45 @@ parse_conf(findclass) if (*endp != 0) { syslog(LOG_WARNING, "%s line %d: invalid maxtimeout %s", - infile, line, arg); + infile, (int)line, arg); continue; } if (timeout < 30) { syslog(LOG_WARNING, "%s line %d: maxtimeout %d < 30 seconds", - infile, line, timeout); + infile, (int)line, timeout); continue; } if (timeout < curclass.timeout) { syslog(LOG_WARNING, "%s line %d: maxtimeout %d < timeout (%d)", - infile, line, timeout, curclass.timeout); + infile, (int)line, timeout, + curclass.timeout); continue; } curclass.maxtimeout = timeout; + } else if (strcasecmp(word, "modify") == 0) { if (none || (!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0)) curclass.modify = 0; else curclass.modify = 1; + } else if (strcasecmp(word, "notify") == 0) { if (none || EMPTYSTR(arg)) arg = NULL; else - arg = strdup(arg); + arg = xstrdup(arg); REASSIGN(curclass.notify, arg); + } else if (strcasecmp(word, "passive") == 0) { if (none || (!EMPTYSTR(arg) && strcasecmp(arg, "off") == 0)) curclass.passive = 0; else curclass.passive = 1; + } else if (strcasecmp(word, "timeout") == 0) { if (none || EMPTYSTR(arg)) continue; @@ -266,22 +264,24 @@ parse_conf(findclass) if (*endp != 0) { syslog(LOG_WARNING, "%s line %d: invalid timeout %s", - infile, line, arg); + infile, (int)line, arg); continue; } if (timeout < 30) { syslog(LOG_WARNING, "%s line %d: timeout %d < 30 seconds", - infile, line, timeout); + infile, (int)line, timeout); continue; } if (timeout > curclass.maxtimeout) { syslog(LOG_WARNING, "%s line %d: timeout %d > maxtimeout (%d)", - infile, line, timeout, curclass.maxtimeout); + infile, (int)line, timeout, + curclass.maxtimeout); continue; } curclass.timeout = timeout; + } else if (strcasecmp(word, "umask") == 0) { mode_t umask; @@ -291,20 +291,18 @@ parse_conf(findclass) if (*endp != 0 || umask > 0777) { syslog(LOG_WARNING, "%s line %d: invalid umask %s", - infile, line, arg); + infile, (int)line, arg); continue; } curclass.umask = umask; + } else { syslog(LOG_WARNING, "%s line %d: unknown directive '%s'", - infile, line, word); + infile, (int)line, word); continue; } } -#undef REASSIGN -#undef NEXTWORD -#undef EMPTYSTR fclose(f); } @@ -345,11 +343,7 @@ show_chdir_messages(code) if (sl_find(slist, cwd) != NULL) return; - cp = strdup(cwd); - if (cp == NULL) { - syslog(LOG_WARNING, "can't strdup"); - return; - } + cp = xstrdup(cwd); if (sl_add(slist, cp) == -1) syslog(LOG_WARNING, "can't add `%s' to stringlist", cp); @@ -394,7 +388,7 @@ show_chdir_messages(code) } /* - * Find s2 at the end of s1. If found, return a string up and up (but + * Find s2 at the end of s1. If found, return a string up to (but * not including) s2, otherwise returns NULL. */ static char * @@ -451,18 +445,20 @@ filetypematch(types, mode) * routine doesn't need to be re-entrant unless we start using a * multi-threaded ftpd, and that's not likely for a while... */ -char * +char ** do_conversion(fname) const char *fname; { - static char cmd[LINE_MAX]; - struct ftpconv *cp; struct stat st; int o_errno; char *base = NULL; + char *cmd, *p, *lp, **argv; + StringList *sl; o_errno = errno; + sl = NULL; + cmd = NULL; for (cp = curclass.conversions; cp != NULL; cp = cp->next) { if (cp->suffix == NULL) { syslog(LOG_WARNING, @@ -488,11 +484,33 @@ do_conversion(fname) } /* If we got through the list, no conversion */ - if (cp == NULL) { - errno = o_errno; - return(NULL); + if (cp == NULL) + goto cleanup_do_conv; + + /* Split up command into an argv */ + if ((sl = sl_init()) == NULL) + goto cleanup_do_conv; + cmd = xstrdup(cp->command); + p = cmd; + while (p) { + NEXTWORD(p, lp); + if (strcmp(lp, "%s") == 0) + lp = base; + if (sl_add(sl, xstrdup(lp)) == -1) + goto cleanup_do_conv; } - snprintf(cmd, LINE_MAX, cp->command, base); - return(cmd); + if (sl_add(sl, NULL) == -1) + goto cleanup_do_conv; + argv = sl->sl_str; + free(cmd); + free(sl); + return(argv); + + cleanup_do_conv: + if (sl) + sl_free(sl, 1); + free(cmd); + errno = o_errno; + return(NULL); } diff --git a/libexec/ftpd/extern.h b/libexec/ftpd/extern.h index a2594967165..5cbbd32a23a 100644 --- a/libexec/ftpd/extern.h +++ b/libexec/ftpd/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.19 1999/07/02 05:52:14 itojun Exp $ */ +/* $NetBSD: extern.h,v 1.20 1999/12/07 05:30:54 lukem Exp $ */ /* * Copyright (C) 1997 and 1998 WIDE Project. @@ -69,11 +69,11 @@ char *conffilename __P((const char *)); char **copyblk __P((char **)); void cwd __P((const char *)); void delete __P((const char *)); -char *do_conversion __P((const char *)); +char **do_conversion __P((const char *)); void dologout __P((int)); void fatal __P((const char *)); int ftpd_pclose __P((FILE *)); -FILE *ftpd_popen __P((char *, char *, int)); +FILE *ftpd_popen __P((char *[], const char *, int)); char *getline __P((char *, int, FILE *)); void logcmd __P((const char *, off_t, const char *, const char *, const struct timeval *, const char *)); @@ -90,7 +90,7 @@ void removedir __P((const char *)); void renamecmd __P((const char *, const char *)); char *renamefrom __P((char *)); void reply __P((int, const char *, ...)); -void retrieve __P((const char *, const char *)); +void retrieve __P((char *[], const char *)); void send_file_list __P((const char *)); void show_chdir_messages __P((int)); void statcmd __P((void)); @@ -118,7 +118,7 @@ struct ftpconv { struct ftpclass { int checkportcmd; /* Check PORT commands are valid */ char *classname; /* Current class */ - struct ftpconv *conversions; /* List of conversions */ + struct ftpconv *conversions; /* List of conversions */ char *display; /* Files to display upon chdir */ unsigned int maxtimeout; /* Maximum permitted timeout */ int modify; /* Allow dele, mkd, rmd, umask, chmod */ diff --git a/libexec/ftpd/ftpcmd.y b/libexec/ftpd/ftpcmd.y index 1a53620164b..e7f20989b5a 100644 --- a/libexec/ftpd/ftpcmd.y +++ b/libexec/ftpd/ftpcmd.y @@ -1,4 +1,4 @@ -/* $NetBSD: ftpcmd.y,v 1.39 1999/10/04 17:36:52 tron Exp $ */ +/* $NetBSD: ftpcmd.y,v 1.40 1999/12/07 05:30:54 lukem Exp $ */ /* * Copyright (c) 1985, 1988, 1993, 1994 @@ -47,7 +47,7 @@ #if 0 static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94"; #else -__RCSID("$NetBSD: ftpcmd.y,v 1.39 1999/10/04 17:36:52 tron Exp $"); +__RCSID("$NetBSD: ftpcmd.y,v 1.40 1999/12/07 05:30:54 lukem Exp $"); #endif #endif /* not lint */ @@ -321,11 +321,7 @@ cmd /*XXX checks for login */ - tmp = strdup($4); - if (!tmp) { - fatal("not enough core."); - /*NOTREACHED*/ - } + tmp = xstrdup($4); p = tmp; delim = p[0]; p++; @@ -619,14 +615,20 @@ cmd | LIST check_login CRLF { + char *argv[] = { INTERNAL_LS, "-lgA", NULL }; + if ($2) - retrieve("/bin/ls -lgA", ""); + retrieve(argv, ""); } | LIST check_login SP pathname CRLF { - if ($2 && $4 != NULL) - retrieve("/bin/ls -lgA %s", $4); + char *argv[] = { INTERNAL_LS, "-lgA", NULL, NULL }; + + if ($2 && $4 != NULL) { + argv[2] = $4; + retrieve(argv, $4); + } if ($4 != NULL) free($4); } diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index e070dfd7d07..776308ff540 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -1,4 +1,4 @@ -/* $NetBSD: ftpd.c,v 1.70 1999/09/30 18:12:34 tron Exp $ */ +/* $NetBSD: ftpd.c,v 1.71 1999/12/07 05:30:54 lukem Exp $ */ /* * Copyright (C) 1997 and 1998 WIDE Project. @@ -109,7 +109,7 @@ __COPYRIGHT( #if 0 static char sccsid[] = "@(#)ftpd.c 8.5 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: ftpd.c,v 1.70 1999/09/30 18:12:34 tron Exp $"); +__RCSID("$NetBSD: ftpd.c,v 1.71 1999/12/07 05:30:54 lukem Exp $"); #endif #endif /* not lint */ @@ -887,38 +887,38 @@ bad: } void -retrieve(cmd, name) - const char *cmd, *name; +retrieve(argv, name) + char *argv[]; + const char *name; { FILE *fin = NULL, *dout; struct stat st; int (*closefunc) __P((FILE *)) = NULL; int log, sendrv, closerv, stderrfd, isconversion, isdata, isls; struct timeval start, finish, td, *tdp; - char tline[BUFSIZ]; const char *dispname; sendrv = closerv = stderrfd = -1; isconversion = isdata = isls = log = 0; tdp = NULL; dispname = name; - if (cmd == NULL) { + if (argv == NULL) { log = 1; isdata = 1; fin = fopen(name, "r"); closefunc = fclose; if (fin == NULL) - cmd = do_conversion(name); - if (cmd != NULL) { + argv = do_conversion(name); + if (argv != NULL) { isconversion++; - syslog(LOG_INFO, "get command: '%s'", cmd); + syslog(LOG_INFO, "get command: '%s' on '%s'", + argv[0], name); } } - if (cmd != NULL) { + if (argv != NULL) { char temp[MAXPATHLEN + 1]; - if (strncmp(cmd, INTERNAL_LS, sizeof(INTERNAL_LS) - 1) == 0 && - strchr(" \t\n", cmd[sizeof(INTERNAL_LS) - 1]) != NULL) { + if (strcmp(argv[0], INTERNAL_LS) == 0) { isls = 1; stderrfd = -1; } else { @@ -927,9 +927,8 @@ retrieve(cmd, name) if (stderrfd != -1) (void)unlink(temp); } - (void)snprintf(tline, sizeof(tline), cmd, name); - dispname = tline; - fin = ftpd_popen(tline, "r", stderrfd); + dispname = argv[0]; + fin = ftpd_popen(argv, "r", stderrfd); closefunc = ftpd_pclose; st.st_size = -1; st.st_blksize = BUFSIZ; @@ -941,12 +940,10 @@ retrieve(cmd, name) logcmd("get", -1, name, NULL, NULL, strerror(errno)); } - if (stderrfd != -1) - (void)close(stderrfd); - return; + goto cleanupretrieve; } byte_count = -1; - if (cmd == NULL + if (argv == NULL && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { reply(550, "%s: not a plain file.", dispname); goto done; @@ -989,16 +986,16 @@ done: FILE *err; struct stat sb; - if (!isls && cmd != NULL && closerv != 0) { + if (!isls && argv != NULL && closerv != 0) { lreply(226, "Command returned an exit status of %d", closerv); if (isconversion) syslog(LOG_INFO, - "get command: '%s' returned %d", - cmd, closerv); + "retrieve command: '%s' returned %d", + argv[0], closerv); } - if (!isls && cmd != NULL && stderrfd != -1 && + if (!isls && argv != NULL && stderrfd != -1 && (fstat(stderrfd, &sb) == 0) && sb.st_size > 0 && ((err = fdopen(stderrfd, "r")) != NULL)) { char *cp, line[LINE_MAX]; @@ -1016,8 +1013,11 @@ done: } reply(226, "Transfer complete."); } + cleanupretrieve: if (stderrfd != -1) (void)close(stderrfd); + if (isconversion) + free(argv); } void @@ -1472,10 +1472,10 @@ statfilecmd(filename) { FILE *fin; int c; - char line[LINE_MAX]; + char *argv[] = { INTERNAL_LS, "-lgA", "", NULL }; - (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename); - fin = ftpd_popen(line, "r", STDOUT_FILENO); + argv[2] = (char *)filename; + fin = ftpd_popen(argv, "r", STDOUT_FILENO); lreply(211, "status of %s:", filename); while ((c = getc(fin)) != EOF) { if (c == '\n') { @@ -2254,9 +2254,13 @@ send_file_list(whichf) * If user typed "ls -l", etc, and the client * used NLST, do what the user meant. */ + /* XXX: nuke this support? */ if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) { - retrieve("/bin/ls %s", dirname); + char *argv[] = { INTERNAL_LS, "", NULL }; + + argv[1] = dirname; + retrieve(argv, dirname); goto out; } perror_reply(550, whichf); @@ -2307,6 +2311,7 @@ send_file_list(whichf) * We have to do a stat to ensure it's * not a directory or special file. */ + /* XXX: follow RFC959 and filter out non files ? */ if (simple || (stat(nbuf, &st) == 0 && S_ISREG(st.st_mode))) { char *p; diff --git a/libexec/ftpd/popen.c b/libexec/ftpd/popen.c index aeba8055909..787605e9cc5 100644 --- a/libexec/ftpd/popen.c +++ b/libexec/ftpd/popen.c @@ -1,4 +1,4 @@ -/* $NetBSD: popen.c,v 1.16 1999/08/25 20:07:33 christos Exp $ */ +/* $NetBSD: popen.c,v 1.17 1999/12/07 05:30:54 lukem Exp $ */ /* * Copyright (c) 1988, 1993, 1994 @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94"; #else -__RCSID("$NetBSD: popen.c,v 1.16 1999/08/25 20:07:33 christos Exp $"); +__RCSID("$NetBSD: popen.c,v 1.17 1999/12/07 05:30:54 lukem Exp $"); #endif #endif /* not lint */ @@ -55,6 +55,7 @@ __RCSID("$NetBSD: popen.c,v 1.16 1999/08/25 20:07:33 christos Exp $"); #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stringlist.h> #include <syslog.h> #include <unistd.h> @@ -78,24 +79,18 @@ static int fds; extern int ls_main __P((int, char *[])); FILE * -ftpd_popen(program, type, stderrfd) - char *program, *type; +ftpd_popen(argv, type, stderrfd) + char *argv[]; + const char *type; int stderrfd; { - char *cp; - FILE *iop = NULL; - int argc, gargc, pdes[2], pid, isls; - char **pop, **np; - char **argv = NULL, **gargv = NULL; - size_t nargc = 100, ngargc = 100; -#ifdef __GNUC__ - (void) &iop; - (void) &gargc; - (void) &gargv; - (void) &argv; -#endif - isls = 0; + FILE *iop; + int argc, pdes[2], pid, isls; + char **pop; + StringList *sl; + iop = NULL; + isls = 0; if ((*type != 'r' && *type != 'w') || type[1]) return (NULL); @@ -109,51 +104,31 @@ ftpd_popen(program, type, stderrfd) if (pipe(pdes) < 0) return (NULL); - if ((argv = malloc(nargc * sizeof(char *))) == NULL) - return NULL; - -#define CHECKMORE(c, v, n) \ - if (c >= n + 2) { \ - n += INCR; \ - if ((np = realloc(v, n * sizeof(char *))) == NULL) \ - goto pfree; \ - else \ - v = np; \ - } - - /* break up string into pieces */ - for (argc = 0, cp = program;; cp = NULL) { - CHECKMORE(argc, argv, nargc) - if (!(argv[argc++] = strtok(cp, " \t\n"))) - break; - } - - if ((gargv = malloc(ngargc * sizeof(char *))) == NULL) + if ((sl = sl_init()) == NULL) goto pfree; - /* glob each piece */ - gargv[0] = argv[0]; - for (gargc = argc = 1; argv[argc]; argc++) { + /* glob each piece */ + if (sl_add(sl, xstrdup(argv[0])) == -1) + goto pfree; + for (argc = 1; argv[argc]; argc++) { glob_t gl; int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; memset(&gl, 0, sizeof(gl)); if (glob(argv[argc], flags, NULL, &gl)) { - CHECKMORE(gargc, gargv, ngargc) - if ((gargv[gargc++] = strdup(argv[argc])) == NULL) + if (sl_add(sl, xstrdup(argv[argc])) == -1) goto pfree; - } - else + } else for (pop = gl.gl_pathv; *pop; pop++) { - CHECKMORE(gargc, gargv, ngargc) - if ((gargv[gargc++] = strdup(*pop)) == NULL) + if (sl_add(sl, xstrdup(*pop)) == -1) goto pfree; } globfree(&gl); } - gargv[gargc] = NULL; + if (sl_add(sl, NULL) == -1) + goto pfree; - isls = (strcmp(gargv[0], INTERNAL_LS) == 0); + isls = (strcmp(sl->sl_str[0], INTERNAL_LS) == 0); pid = isls ? fork() : vfork(); switch (pid) { @@ -183,9 +158,9 @@ ftpd_popen(program, type, stderrfd) if (isls) { /* use internal ls */ optreset = optind = optopt = 1; closelog(); - exit(ls_main(gargc, gargv)); + exit(ls_main(sl->sl_cur - 1, sl->sl_str)); } - execv(gargv[0], gargv); + execv(sl->sl_str[0], sl->sl_str); _exit(1); } /* parent; assume fdopen can't fail... */ @@ -198,14 +173,8 @@ ftpd_popen(program, type, stderrfd) } pids[fileno(iop)] = pid; -pfree: if (gargv) { - for (argc = 1; argc < gargc; argc++) - free(gargv[argc]); - free(gargv); - } - if (argv) - free(argv); - +pfree: if (sl) + sl_free(sl, 1); return (iop); } |
