summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorlukem <lukem@NetBSD.org>1999-12-07 05:30:53 +0000
committerlukem <lukem@NetBSD.org>1999-12-07 05:30:53 +0000
commit397e2cfc53e82f5d70cf4cebcb325c80bc596b52 (patch)
tree3c441bf365c1294ced6a73ba1499d73febf54a3b /libexec
parentc6dcc983e59f95d94e78c324bd2f65e6590a601a (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/Makefile6
-rw-r--r--libexec/ftpd/conf.c164
-rw-r--r--libexec/ftpd/extern.h10
-rw-r--r--libexec/ftpd/ftpcmd.y22
-rw-r--r--libexec/ftpd/ftpd.c59
-rw-r--r--libexec/ftpd/popen.c85
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);
}