diff options
author | ache <ache@FreeBSD.org> | 1994-09-22 23:45:37 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 1994-09-22 23:45:37 +0000 |
commit | 41cb9decc65e51e29f0eb6fe06bcb3594726bd6b (patch) | |
tree | 31cb31bfb69915fc791ce9c2ec7d345124bedebf /usr.bin/ncftp/cmds.c | |
download | FreeBSD-src-41cb9decc65e51e29f0eb6fe06bcb3594726bd6b.zip FreeBSD-src-41cb9decc65e51e29f0eb6fe06bcb3594726bd6b.tar.gz |
ncftp 1.8.5
Diffstat (limited to 'usr.bin/ncftp/cmds.c')
-rw-r--r-- | usr.bin/ncftp/cmds.c | 2214 |
1 files changed, 2214 insertions, 0 deletions
diff --git a/usr.bin/ncftp/cmds.c b/usr.bin/ncftp/cmds.c new file mode 100644 index 0000000..41394db --- /dev/null +++ b/usr.bin/ncftp/cmds.c @@ -0,0 +1,2214 @@ +/* cmds.c */ + +/* $RCSfile: cmds.c,v $ + * $Revision: 14020.14 $ + * $Date: 93/07/09 11:31:53 $ + */ + +#include "sys.h" + +#include <sys/wait.h> + +#include <sys/stat.h> +#include <arpa/ftp.h> +#include <setjmp.h> +#include <signal.h> +#include <errno.h> +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> + +#ifdef SYSLOG +# include <syslog.h> +#endif + +#include "util.h" +#include "cmds.h" +#include "main.h" +#include "ftp.h" +#include "ftprc.h" +#include "getpass.h" +#include "glob.h" +#include "open.h" +#include "set.h" +#include "defaults.h" +#include "copyright.h" + +/* cmds.c globals */ +#ifdef PASSIVEMODE +int passivemode = 1; +#endif +int curtype; /* file transfer type */ +char *typeabbrs = "abiet"; +str32 curtypename; /* name of file transfer type */ +int verbose; /* verbosity level of output */ +int mprompt; /* interactively prompt on m* cmds */ +int debug; /* debugging level */ +int options; /* used during socket creation */ +int macnum; /* number of defined macros */ +int paging = 0; +int creating = 0; +struct macel macros[MAXMACROS]; +char *macbuf; /* holds ALL macros */ +int doingInitMacro = 0; /* TRUE if executing "init" macro. */ +jmp_buf jabort; +char *mname; /* name of current m* command */ +int activemcmd; /* flag: if != 0, then active multi command */ +int warnNoLSFlagsWithWildcards = 0; + /* Tells whether the user has been + * warned about not being able to use + * flags with ls when using wildcards. + */ +longstring cwd; /* current remote directory */ +longstring lcwd; /* current local directory */ +Hostname lasthostname; /* name of last host w/ lookup(). */ +int logged_in = 0; /* TRUE if connected and user/pw OK. */ +int is_ls = 0; /* are we doing an ls? if so, then + read input into a line buffer + for re-use. */ +extern int buffer_only; +struct lslist *lshead = NULL; /* hold last output from host */ +struct lslist *lstail = NULL; + +/* cmds.c externs */ +extern char *globerr, *home, *reply_string; +extern int margc, connected, ansi_escapes; +extern int code, connected; +extern int toatty, fromatty; +extern int data, progress_meter, remote_is_unix; +extern int parsing_rc, keep_recent; +extern char *altarg, *line, *margv[]; +extern char *globchars; +extern Hostname hostname; +extern RemoteSiteInfo gRmtInfo; +extern string progname, pager, anon_password; +extern string prompt, version, indataline; +extern longstring logfname; +extern long logsize; +extern size_t xferbufsize; +extern struct servent serv; +extern struct cmd cmdtab[]; +extern struct userinfo uinfo; +extern FILE *cin, *cout, *logf; +extern int Optind; +extern char *Optarg; +extern int Optind; +extern char *Optarg; + +#ifdef STRICT_PROTOS +extern int gethostname(char *, int), getdomainname(char *, int); +#endif + + +struct types types[] = { + { "ascii", "A", TYPE_A, 0 }, + { "binary", "I", TYPE_I, 0 }, + { "image", "I", TYPE_I, 0 }, + { "ebcdic", "E", TYPE_E, 0 }, + { "tenex", "L", TYPE_L, "8" }, + { 0 } +}; + + + +long GetDateSizeFromLSLine(char *fName, unsigned long *mod_time) +{ + char *cp, *np; + string lsline; + long size = SIZE_UNKNOWN; + int n, v; + struct lslist *savedh, *savedt; + static int depth = 0; + + depth++; /* Try to prevent infinite recursion. */ + *mod_time = MDTM_UNKNOWN; + v = verbose; verbose = V_QUIET; + is_ls = 1; + buffer_only = 1; + savedh = lshead; + savedt = lstail; + lshead = NULL; + (void) recvrequest("LIST", "-", fName, "w"); + is_ls = 0; + buffer_only = 0; + verbose = v; + if (lshead == NULL) { + PurgeLineBuffer(); + lshead = savedh; + lstail = savedt; + goto aa; + } + (void) Strncpy(lsline, lshead->string); + PurgeLineBuffer(); + lshead = savedh; + lstail = savedt; + + if (code >= 400 && code < 500) + goto aa; + + /* See if this line looks like a unix-style ls line. + * If so, we can grab the date and size from it. + */ + if (strpbrk(lsline, "-dlsbcp") == lsline) { + /* See if it looks like a typical '-rwxrwxrwx' line. */ + cp = lsline + 1; + if (*cp != 'r' && *cp != '-') + goto aa; + ++cp; + if (*cp != 'w' && *cp != '-') + goto aa; + cp += 2; + if (*cp != 'r' && *cp != '-') + goto aa; + + /* skip mode, links, owner (and possibly group) */ + for (n = 0; n < 4; n++) { + np = cp; + while (*cp != '\0' && !isspace(*cp)) + cp++; + while (*cp != '\0' && isspace(*cp)) + cp++; + } + if (!isdigit(*cp)) + cp = np; /* back up (no group) */ + (void) sscanf(cp, "%ld%n", &size, &n); + + *mod_time = UnLSDate(cp + n + 1); + + if (size < 100) { + /* May be the size of a link to the file, instead of the file. */ + if ((cp = strstr(lsline, " -> ")) != NULL) { + /* Yes, it was a link. */ + size = (depth>4) ? SIZE_UNKNOWN : + GetDateAndSize(cp + 4, mod_time); + /* Try the file. */ + } + } + } +aa: + --depth; + return (size); +} /* GetDateSizeFromLSLine */ + + + + +/* The caller wanted to know the modification date and size of the remote + * file given to us. We try to get this information by using the SIZE + * and MDTM ftp commands, and if that didn't work we try sending the site + * a "ls -l <fName>" and try to get that information from the line it + * sends us back. It is possible that we won't be able to determine + * either of these, though. + */ +long GetDateAndSize(char *fName, unsigned long *mod_time) +{ + unsigned long mdtm, ls_mdtm; + long size, ls_size; + int have_mdtm, have_size; + string cmd; + + size = SIZE_UNKNOWN; + mdtm = MDTM_UNKNOWN; + if (fName != NULL) { + have_mdtm = have_size = 0; + if (gRmtInfo.hasSIZE) { + (void) Strncpy(cmd, "SIZE "); + (void) Strncat(cmd, fName); + if (quiet_command(cmd) == 2) { + if (sscanf(reply_string, "%*d %ld", &size) == 1) + have_size = 1; + } else if (strncmp(reply_string, "550", (size_t)3) != 0) + gRmtInfo.hasSIZE = 0; + } + +#ifndef NO_MKTIME + /* We'll need mktime() to un-mangle this. */ + if (gRmtInfo.hasMDTM) { + (void) Strncpy(cmd, "MDTM "); + (void) Strncat(cmd, fName); + if (quiet_command(cmd) == 2) { + /* Result should look like "213 19930602204445\n" */ + mdtm = UnMDTMDate(reply_string); + if (mdtm != MDTM_UNKNOWN) + have_mdtm = 1; + } else if (strncmp(reply_string, "550", (size_t)3) != 0) + gRmtInfo.hasMDTM = 0; + } +#endif /* NO_MKTIME */ + + if (!have_mdtm || !have_size) + ls_size = GetDateSizeFromLSLine(fName, &ls_mdtm); + + /* Try to use the information from the real SIZE/MDTM commands if + * we could, since some maverick ftp server may be using a non-standard + * ls command, and we could parse it wrong. + */ + + if (!have_mdtm) + mdtm = ls_mdtm; + if (!have_size) + size = ls_size; + + dbprintf("Used SIZE: %s; Used MDTM: %s\n", + have_size ? "yes" : "no", + have_mdtm ? "yes" : "no" + ); + + if (debug > 0) { + if (size != SIZE_UNKNOWN) + dbprintf("Size: %ld\n", size); + if (mdtm != MDTM_UNKNOWN) + dbprintf("Mdtm: %s\n", ctime((time_t *) &mdtm)); + } + } + *mod_time = mdtm; + return size; +} /* GetDateAndSize */ + + + + + +int _settype(char *typename) +{ + register struct types *p; + int comret, c; + string cmd; + char *cp; + + c = isupper(*typename) ? tolower(*typename) : (*typename); + if ((cp = index(typeabbrs, c)) != NULL) + p = &types[(int) (cp - typeabbrs)]; + else { + (void) printf("%s: unknown type\n", typename); + return USAGE; + } + if (c == 't') + (void) strcpy(cmd, "TYPE L 8"); + else + (void) sprintf(cmd, "TYPE %s", p->t_mode); + comret = command(cmd); + if (comret == COMPLETE) { + (void) Strncpy(curtypename, p->t_name); + curtype = p->t_type; + } + return NOERR; +} /* _settype */ + + + + +int SetTypeByNumber(int i) +{ + char tstr[4], *tp = tstr, c; + + tp[1] = c = 0; + switch (i) { + case TYPE_A: c = 'a'; break; + case TYPE_I: c = 'b'; break; + case TYPE_E: c = 'e'; break; + case TYPE_L: c = 't'; + } + *tp = c; + return (c == 0 ? -1 : _settype(tp)); +} /* SetTypeByNumber */ + + + + +/* + * Set transfer type. + */ +int settype(int argc, char **argv) +{ + int result = NOERR; + + if (argc > 2) { + result = USAGE; + } else { + if (argc < 2) + goto xx; + result = _settype(argv[1]); + if (IS_VVERBOSE) +xx: (void) printf("Using %s mode to transfer files.\n", curtypename); + } + return result; +} /* settype */ + + + + +/*ARGSUSED*/ +int setbinary(int argc, char **argv) { return (_settype("binary")); } +/*ARGSUSED*/ +int setascii(int argc, char **argv) { return (_settype("ascii")); } + + + +/* + * Send a single file. + */ +int put(int argc, char **argv) +{ + char *cmd; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + } + if (argc < 2) + argv = re_makeargv("(local-file) ", &argc); + if (argc < 2) { +usage: + return USAGE; + } + if (argc < 3) + argv = re_makeargv("(remote-file) ", &argc); + if (argc < 3) + goto usage; + cmd = (argv[0][0] == 'a') ? "APPE" : "STOR"; + (void) sendrequest(cmd, argv[1], argv[2]); + return NOERR; +} /* put */ + + + + +/* + * Send multiple files. + */ +int mput(int argc, char **argv) +{ + register int i; + Sig_t oldintr; + char *tp; + + if (argc < 2) + argv = re_makeargv("(local-files) ", &argc); + if (argc < 2) { + return USAGE; + } + mname = argv[0]; + activemcmd = 1; + oldintr = Signal(SIGINT, mabort); + (void) setjmp(jabort); + for (i = 1; i < argc; i++) { + register char **cpp, **gargs; + char *icopy; + + /* Make a copy of the argument, because glob() will just copy + * the pointer you give it to the glob-arg vector, and blkfree() + * will want to free each element of the glob-arg vector + * later. + */ + if ((icopy = NewString(argv[i])) == NULL) + break; + gargs = glob(icopy); + if (globerr != NULL) { + (void) printf("%s\n", globerr); + if (gargs) { + blkfree(gargs); + Free(gargs); + } + continue; + } + for (cpp = gargs; cpp && *cpp != NULL; cpp++) { + if (activemcmd && confirm(argv[0], *cpp)) { + tp = *cpp; + (void) sendrequest("STOR", *cpp, tp); + if (!activemcmd && fromatty) { + if (confirm("Continue with","mput")) { + activemcmd++; + } + } + } + } + if (gargs != NULL) { + blkfree(gargs); + Free(gargs); + } + } + (void) Signal(SIGINT, oldintr); + activemcmd = 0; + return NOERR; +} /* mput */ + + + + +int rem_glob_one(char *pattern) +{ + int oldverbose, result = 0; + char *cp; + string str, tname; + FILE *ftemp; + + /* Check for wildcard characters. */ + if (*pattern == '|' || strpbrk(pattern, globchars) == NULL) + return 0; + + (void) tmp_name(tname); + oldverbose = verbose; + verbose = V_QUIET; + (void) recvrequest ("NLST", tname, pattern, "w"); + verbose = oldverbose; + ftemp = fopen(tname, "r"); + (void) chmod(tname, 0600); + if (ftemp == NULL || FGets(str, ftemp) == NULL) { + if (NOT_VQUIET) + (void) printf("%s: no match.\n", pattern); + result = -1; + goto done; + } + if ((cp = index(str, '\n')) != NULL) + *cp = '\0'; + (void) strcpy(pattern, str); + cp = FGets(str, ftemp); + /* It is an error if the pattern matched more than one file. */ + if (cp != NULL) { + if (NOT_VQUIET) + (void) printf("?Ambiguous remote file name.\n"); + result = -2; + } +done: + if (ftemp != NULL) + (void) fclose(ftemp); + (void) unlink(tname); + return (result); +} /* rem_glob_one */ + + + + +/* + * Receive (and maybe page) one file. + */ +int get(int argc, char **argv) +{ + string local_file; + char remote_file[256]; + char *cp; + int oldtype = curtype, try_zcat; + size_t len; + + /* paging mode is set if the command name is 'page' or 'more.' */ + paging = (**argv != 'g'); + + if (argc < 2) + argv = re_makeargv("(remote-file) ", &argc); + + if (argc < 2) { + return USAGE; + } + cp = Strncpy(remote_file, argv[1]); + argv[1] = cp; + if (rem_glob_one(argv[1]) < 0) + return CMDERR; + + if (paging) { + try_zcat = 0; + len = strlen(remote_file); + + if (len > (size_t) 2) { + if (remote_file[len-2] == '.') { + /* Check for .Z files. */ + if (remote_file[len-1] == 'Z') + try_zcat = 1; +#ifdef GZCAT + /* Check for .z (gzip) files. */ + if (remote_file[len-1] == 'z') + try_zcat = 1; +#endif /* GZCAT */ + } + } + +#ifdef GZCAT + if (len > (size_t) 3) { + /* Check for ".gz" (gzip) files. */ + if (strcmp(remote_file + len - 3, ".gz") == 0) + try_zcat = 1; + } +#endif /* GZCAT */ + + /* Run compressed remote files through zcat, then the pager. + * If GZCAT was defined, we also try paging gzipped files. + * Note that ZCAT is defined to be GZCAT if you defined + * GZCAT. + */ + + if (try_zcat) { + (void) _settype("b"); + (void) sprintf(local_file, "|%s ", ZCAT); + argv[2] = Strncat(local_file, pager); + } else { + /* Try to use text mode for paging, so newlines get converted. */ + (void) _settype("a"); + argv[2] = pager; + } + } else { + /* normal get */ + if (argc == 2) { + (void) Strncpy(local_file, argv[1]); + argv[2] = local_file; + } else { + if (argc < 3) + argv = re_makeargv("(local-file) ", &argc); + if (argc < 3) + return USAGE; + (void) LocalDotPath(argv[2]); + } + } + (void) recvrequest("RETR", argv[2], argv[1], "w"); + if (paging) { + (void) SetTypeByNumber(oldtype); /* Restore it to what it was. */ + paging = 0; + } + return NOERR; +} /* get */ + + + +/*ARGSUSED*/ +void mabort SIG_PARAMS +{ + (void) printf("\n"); + (void) fflush(stdout); + if (activemcmd && fromatty) { + if (confirm("Continue with", mname)) { + longjmp(jabort,0); + } + } + activemcmd = 0; + longjmp(jabort,0); +} /* mabort */ + + + + +/* + * Get multiple files. + */ +int mget(int argc, char **argv) +{ + char *cp; + longstring local; + Sig_t oldintr; + + if (argc < 2) + argv = re_makeargv("(remote-files) ", &argc); + if (argc < 2) { + return USAGE; + } + mname = argv[0]; + activemcmd = 1; + oldintr = Signal(SIGINT, mabort); + (void) setjmp(jabort); + while ((cp = remglob(argv)) != NULL) { + if (*cp == '\0') { + activemcmd = 0; + continue; + } + if (activemcmd && confirm(argv[0], cp)) { + (void) Strncpy(local, cp); + (void) recvrequest("RETR", local, cp, "w"); + if (!activemcmd && fromatty) { + if (confirm("Continue with","mget")) { + activemcmd++; + } + } + } + } + (void) Signal(SIGINT,oldintr); + activemcmd = 0; + return NOERR; +} /* mget */ + + + + +char *remglob(char *argv[]) +{ + static FILE *ftemp = NULL; + int oldverbose, i; + char *cp, *mode; + static string tmpname, str; + int result, errs; + + if (!activemcmd) { +xx: + if (ftemp) { + (void) fclose(ftemp); + ftemp = NULL; + (void) unlink(tmpname); + } + return(NULL); + } + if (ftemp == NULL) { + (void) tmp_name(tmpname); + oldverbose = verbose, verbose = V_QUIET; + errs = 0; + for (mode = "w", i=1; argv[i] != NULL; i++, mode = "a") { + result = recvrequest ("NLST", tmpname, argv[i], mode); + if (i == 1) + (void) chmod(tmpname, 0600); + if (result < 0) { + fprintf(stderr, "%s: %s.\n", + argv[i], + (strpbrk(argv[i], globchars) != NULL) ? "No match" : + "No such file" + ); + errs++; + } + } + verbose = oldverbose; + if (errs == (i - 1)) { + /* Every pattern was in error, so we can't try anything. */ + (void) unlink(tmpname); /* Shouldn't be there anyway. */ + return NULL; + } + ftemp = fopen(tmpname, "r"); + if (ftemp == NULL) { + PERROR("remglob", tmpname); + return (NULL); + } + } + if (FGets(str, ftemp) == NULL) + goto xx; + if ((cp = index(str, '\n')) != NULL) + *cp = '\0'; + return (str); +} /* remglob */ + + +/* + * Turn on/off printing of server echo's, messages, and statistics. + */ +int setverbose(int argc, char **argv) +{ + if (argc > 1) + set_verbose(argv[1], 0); + else set_verbose(argv[1], -1); + return NOERR; +} /* setverbose */ + + + +/* + * Toggle interactive prompting + * during mget, mput, and mdelete. + */ +int setprompt(int argc, char **argv) +{ + if (argc > 1) + mprompt = StrToBool(argv[1]); + else mprompt = !mprompt; + if (IS_VVERBOSE) + (void) printf("Interactive prompting for m* commmands %s.\n", onoff(mprompt)); + return NOERR; +} /* setprompt */ + + + + +void fix_options(void) +{ + if (debug) + options |= SO_DEBUG; + else + options &= ~SO_DEBUG; +} /* fix_options */ + + +/* + * Set debugging mode on/off and/or + * set level of debugging. + */ +int setdebug(int argc, char **argv) +{ + int val; + + if (argc > 1) { + val = StrToBool(argv[1]); + if (val < 0) { + (void) printf("%s: bad debugging value.\n", argv[1]); + return USAGE; + } + } else + val = !debug; + debug = val; + fix_options(); + if (IS_VVERBOSE) + (void) printf("Debugging %s (debug=%d).\n", onoff(debug), debug); + return NOERR; +} /* debug */ + + + +/* + * Set current working directory + * on remote machine. + */ +int cd(int argc, char **argv) +{ + if (argc < 2) + argv = re_makeargv("(remote-directory) ", &argc); + if (argc < 2) { + return USAGE; + } + (void) _cd(argv[1]); + return NOERR; +} /* cd */ + + + + +int implicit_cd(char *dir) +{ + int i, j = 0; + + if (connected) { + i = verbose; + /* Special verbosity level that ignores errors and prints other stuff, + * so you will get just the unknown command message and not an error + * message from cd. + */ + verbose = V_IMPLICITCD; + j = _cd(dir); + verbose = i; + } + return j; +} /* implicit_cd */ + + + + +int _cd(char *dir) +{ + register char *cp; + int result = 0; + string str; + + if (dir == NULL) + goto getrwd; + /* Won't work because glob really is a ls, so 'cd pu*' will match + * pub/README, pub/file2, etc. + * if (result = rem_glob_one(dir) < 0) + * return result; + */ + if (strncmp(dir, "CDUP", (size_t) 4) == 0) + (void) Strncpy(str, dir); + else + (void) sprintf(str, "CWD %s", dir); + if (command(str) != 5) { +getrwd: + (void) quiet_command("PWD"); + cp = rindex(reply_string, '\"'); + if (cp != NULL) { + result = 1; + *cp = '\0'; + cp = index(reply_string, '\"'); + if (cp != NULL) + (void) Strncpy(cwd, ++cp); + } + } + dbprintf("Current remote directory is \"%s\"\n", cwd); + return (result); +} /* _cd */ + + + + +/* + * Set current working directory + * on local machine. + */ +int lcd(int argc, char **argv) +{ + longstring ldir; + + if (argc < 2) + argc++, argv[1] = home; + if (argc != 2) { + return USAGE; + } + (void) Strncpy(ldir, argv[1]); + if (chdir(LocalDotPath(ldir)) < 0) { + PERROR("lcd", ldir); + return CMDERR; + } + (void) get_cwd(lcwd, (int) sizeof(lcwd)); + if (NOT_VQUIET) + (void) printf("Local directory now %s\n", lcwd); + return NOERR; +} /* lcd */ + + + + +/* + * Delete a single file. + */ +int do_delete(int argc, char **argv) +{ + string str; + + if (argc < 2) + argv = re_makeargv("(remote file to delete) ", &argc); + if (argc < 2) { + return USAGE; + } + if (rem_glob_one(argv[1]) == 0) { + (void) sprintf(str, "DELE %s", argv[1]); + (void) command(str); + } + return NOERR; +} /* do_delete */ + + + + +/* + * Delete multiple files. + */ +int mdelete(int argc, char **argv) +{ + char *cp; + Sig_t oldintr; + string str; + + if (argc < 2) + argv = re_makeargv("(remote-files) ", &argc); + if (argc < 2) { + return USAGE; + } + mname = argv[0]; + activemcmd = 1; + oldintr = Signal(SIGINT, mabort); + (void) setjmp(jabort); + while ((cp = remglob(argv)) != NULL) { + if (*cp == '\0') { + activemcmd = 0; + continue; + } + if (activemcmd && confirm(argv[0], cp)) { + (void) sprintf(str, "DELE %s", cp); + (void) command(str); + if (!activemcmd && fromatty) { + if (confirm("Continue with", "mdelete")) { + activemcmd++; + } + } + } + } + (void) Signal(SIGINT, oldintr); + activemcmd = 0; + return NOERR; +} /* mdelete */ + + + + +/* + * Rename a remote file. + */ +int renamefile(int argc, char **argv) +{ + string str; + + if (argc < 2) + argv = re_makeargv("(from-name) ", &argc); + if (argc < 2) { +usage: + return USAGE; + } + if (argc < 3) + argv = re_makeargv("(to-name) ", &argc); + if (argc < 3) + goto usage; + if (rem_glob_one(argv[1]) < 0) + return CMDERR; + (void) sprintf(str, "RNFR %s", argv[1]); + if (command(str) == CONTINUE) { + (void) sprintf(str, "RNTO %s", argv[2]); + (void) command(str); + } + return NOERR; +} /* renamefile */ + + + +/* + * Get a directory listing + * of remote files. + */ +int ls(int argc, char **argv) +{ + char *whichcmd, *cp; + str32 lsflags; + string remote, local, str; + int listmode, pagemode, i; + + PurgeLineBuffer(); + pagemode = 0; + switch (**argv) { + case 'p': /* pls, pdir, pnlist */ + pagemode = 1; + listmode = argv[0][1] == 'd'; + break; + case 'd': /* dir */ + listmode = 1; + break; + default: /* ls, nlist */ + listmode = 0; + } + whichcmd = listmode ? "LIST" : "NLST"; + + (void) strncpy(local, (pagemode ? pager : "-"), sizeof(local)); + remote[0] = lsflags[0] = 0; + + /* Possible scenarios: + * 1. ls + * 2. ls -flags + * 3. ls directory + * 4. ls -flags >outfile + * 5. ls directory >outfile + * 6. ls -flags directory + * 7. ls -flags directory >outfile + * + * Note that using a wildcard will choke with flags. I.e., don't do + * "ls -CF *.tar," but instead do "ls *.tar." + */ + + for (i=1; i<argc; i++) { + switch (argv[i][0]) { + case '-': + /* + * If you give more than one set of flags, concat the each + * additional set to the first one (without the dash). + */ + (void) strncat(lsflags, (argv[i] + (lsflags[0] == '-')), sizeof(lsflags)); + break; + case '|': + (void) Strncpy(local, argv[i]); + LocalDotPath(local + 1); + break; + case '>': + /* We don't want the '>'. */ + (void) Strncpy(local, argv[i] + 1); + LocalDotPath(local); + break; + default: + cp = argv[i]; + /* + * In case you want to get a remote file called '--README--' + * or '>README,' you can use '\--README--' and '\>README.' + */ + if ((cp[1] != 0) && (*cp == '\\')) + ++cp; + if (remote[0] != 0) { + (void) Strncat(remote, " "); + (void) Strncat(remote, cp); + } else { + (void) Strncpy(remote, cp); + } + } /* end switch */ + } /* end loop */ + + /* + * If we are given an ls with some flags, make sure we use + * columnized output (-C) unless one column output (-1) is + * specified. + */ + if (!listmode) { + if (lsflags[0] != 0) { + (void) Strncpy(str, lsflags); + for (cp = str + 1; *cp; cp++) + if (*cp == '1') + goto aa; + (void) sprintf(lsflags, "-FC%s", str + 1); + } else { + if (remote_is_unix) + (void) strcpy(lsflags, "-FC"); + } + /* As noted above, we can't use -flags if the user gave a + * wildcard expr. + */ + if (remote_is_unix && (strpbrk(remote, globchars) != NULL)) { + lsflags[0] = 0; + /* Warn the user what's going on. */ + if ((warnNoLSFlagsWithWildcards == 0) && NOT_VQUIET) { + (void) fprintf(stderr, "Warning: ls flags disabled with wildcard expressions.\n"); + warnNoLSFlagsWithWildcards++; + } + } + } + +aa: + is_ls = 1; /* tells getreply() to start saving input to a buffer. */ + (void) Strncpy(str, remote); + if (lsflags[0] && remote[0]) + (void) sprintf(remote, "%s%c%s", lsflags, LS_FLAGS_AND_FILE, str); + else + (void) strncpy(remote, lsflags[0] ? lsflags : str, sizeof(remote)); + (void) recvrequest(whichcmd, local, (remote[0] == 0 ? NULL : remote), "w"); + is_ls=0; + return NOERR; +} /* ls */ + + + +/* + * Do a shell escape + */ +/*ARGSUSED*/ +int shell(int argc, char **argv) +{ + int pid; + Sig_t old1, old2; + char *theShell, *namep; +#ifndef U_WAIT + int Status; +#else + union wait Status; +#endif + string str; + + old1 = signal (SIGINT, SIG_IGN); + old2 = signal (SIGQUIT, SIG_IGN); + /* This will prevent <defunct> zombie processes. */ + /* (void) signal(SIGCHLD, SIG_IGN); */ + + if ((pid = fork()) == 0) { + for (pid = 3; pid < 20; pid++) + (void) close(pid); + (void) Signal(SIGINT, SIG_DFL); + (void) Signal(SIGQUIT, SIG_DFL); + if ((theShell = getenv("SHELL")) == NULL) + theShell = uinfo.shell; + if (theShell == NULL) + theShell = "/bin/sh"; + namep = rindex(theShell, '/'); + if (namep == NULL) + namep = theShell; + (void) strcpy(str, "-"); + (void) strcat(str, ++namep); + if (strcmp(namep, "sh") != 0) + str[0] = '+'; + dbprintf ("%s\n", theShell); +#if defined(BSD) || defined(_POSIX_SOURCE) + setreuid(-1,getuid()); + setregid(-1,getgid()); +#endif + if (argc > 1) + (void) execl(theShell, str, "-c", altarg, (char *)0); + else + (void) execl(theShell, str, (char *)0); + PERROR("shell", theShell); + exit(1); + } + if (pid > 0) + while (wait((void *) &Status) != pid) + ; + (void) Signal(SIGINT, old1); + (void) Signal(SIGQUIT, old2); + if (pid == -1) { + PERROR("shell", "Try again later"); + } + return NOERR; +} /* shell */ + + + + +/* + * Send new user information (re-login) + */ +int do_user(int argc, char **argv) +{ + char acct[80]; + int n, aflag = 0; + string str; + + if (argc < 2) + argv = re_makeargv("(username) ", &argc); + if (argc > 4) { + return USAGE; + } + (void) sprintf(str, "USER %s", argv[1]); + n = command(str); + if (n == CONTINUE) { + if (argc < 3 ) + argv[2] = Getpass("Password: "), argc++; + (void) sprintf(str, "PASS %s", argv[2]); + n = command(str); + } + if (n == CONTINUE) { + if (argc < 4) { + (void) printf("Account: "); (void) fflush(stdout); + (void) FGets(acct, stdin); + acct[strlen(acct) - 1] = '\0'; + argv[3] = acct; argc++; + } + (void) sprintf(str, "ACCT %s", argv[3]); + n = command(str); + aflag++; + } + if (n != COMPLETE) { + (void) fprintf(stdout, "Login failed.\n"); + logged_in = 0; + return (0); + } + if (!aflag && argc == 4) { + (void) sprintf(str, "ACCT %s", argv[3]); + (void) command(str); + } + logged_in = 1; + CheckRemoteSystemType(0); + return NOERR; +} /* do_user */ + + + + +/* + * Print working directory. + */ +/*ARGSUSED*/ +int pwd(int argc, char **argv) +{ + (void) verbose_command("PWD"); + return NOERR; +} /* pwd */ + + + + +/* + * Make a directory. + */ +int makedir(int argc, char **argv) +{ + string str; + + if (argc < 2) + argv = re_makeargv("(directory-name) ", &argc); + if (argc < 2) { + return USAGE; + } + (void) sprintf(str, "MKD %s", argv[1]); + (void) command(str); + return NOERR; +} /* makedir */ + + + + +/* + * Remove a directory. + */ +int removedir(int argc, char **argv) +{ + string str; + if (argc < 2) + argv = re_makeargv("(directory-name) ", &argc); + if (argc < 2) { + return USAGE; + } + if (rem_glob_one(argv[1]) == 0) { + (void) sprintf(str, "RMD %s", argv[1]); + (void) command(str); + } + return NOERR; +} /* removedir */ + + + + +/* + * Send a line, verbatim, to the remote machine. + */ +int quote(int argc, char **argv) +{ + int i, tmpverbose; + string str; + + if (argc < 2) + argv = re_makeargv("(command line to send) ", &argc); + if (argc < 2) { + return USAGE; + } + str[0] = 0; + if (*argv[0] == 's') /* Command was 'site' instead of 'quote.' */ + (void) Strncpy(str, "site "); + (void) Strncat(str, argv[1]); + for (i = 2; i < argc; i++) { + (void) Strncat(str, " "); + (void) Strncat(str, argv[i]); + } + tmpverbose = verbose; + verbose = V_VERBOSE; + if (command(str) == PRELIM) { + while (getreply(0) == PRELIM); + } + verbose = tmpverbose; + return NOERR; +} /* quote */ + + + + +/* + * Ask the other side for help. + */ +int rmthelp(int argc, char **argv) +{ + string str; + + if (argc == 1) (void) verbose_command("HELP"); + else { + (void) sprintf(str, "HELP %s", argv[1]); + (void) verbose_command(str); + } + return NOERR; +} /* rmthelp */ + + + + +/* + * Terminate session and exit. + */ +/*ARGSUSED*/ +int quit(int argc, char **argv) +{ + close_up_shop(); + trim_log(); + exit(0); +} /* quit */ + + + +void close_streams(int wantShutDown) +{ + if (cout != NULL) { + if (wantShutDown) + (void) shutdown(fileno(cout), 1+1); + (void) fclose(cout); + cout = NULL; + } + if (cin != NULL) { + if (wantShutDown) + (void) shutdown(fileno(cin), 1+1); + (void) fclose(cin); + cin = NULL; + } +} /* close_streams */ + + + + +/* + * Terminate session, but don't exit. + */ +/*ARGSUSED*/ +int disconnect(int argc, char **argv) +{ +#ifdef SYSLOG + syslog (LOG_INFO, "%s disconnected from %s.", uinfo.username, hostname); +#endif + + (void) command("QUIT"); + close_streams(0); + if (logged_in) + UpdateRecentSitesList(hostname, cwd); + hostname[0] = cwd[0] = 0; + logged_in = connected = 0; + data = -1; + macnum = 0; + return NOERR; +} /* disconnect */ + + + +void +close_up_shop(void) +{ + static int only_once = 0; + if (only_once++ > 0) + return; + if (connected) + (void) disconnect(0, NULL); + WriteRecentSitesFile(); + if (logf != NULL) { + (void) fclose(logf); + logf = NULL; + } +} /* close_up_shop */ + + + + +/* + * Glob a local file name specification with + * the expectation of a single return value. + * Can't control multiple values being expanded + * from the expression, we return only the first. + */ +int globulize(char **cpp) +{ + char **globbed; + + (void) LocalPath(*cpp); + globbed = glob(*cpp); + if (globerr != NULL) { + (void) printf("%s: %s\n", *cpp, globerr); + if (globbed) { + blkfree(globbed); + Free(globbed); + } + return (0); + } + if (globbed) { + *cpp = *globbed++; + /* don't waste too much memory */ + if (*globbed) { + blkfree(globbed); + Free(globbed); + } + } + return (1); +} /* globulize */ + + + +/* change directory to perent directory */ +/*ARGSUSED*/ +int cdup(int argc, char **argv) +{ + (void) _cd("CDUP"); + return NOERR; +} /* cdup */ + + +/* show remote system type */ +/*ARGSUSED*/ +int syst(int argc, char **argv) +{ + (void) verbose_command("SYST"); + return NOERR; +} /* syst */ + + + + +int make_macro(char *name, FILE *fp) +{ + char *tmp; + char *cp; + string str; + size_t len; + int i; + + if (macnum == MAXMACROS) { + (void) fprintf(stderr, "Limit of %d macros have already been defined.\n", MAXMACROS); + return -1; + } + + /* Make sure macros have unique names. If 'init' was attempted to be + * redefined, just return, since it was probably cmdOpen() in a redial + * mode which tried to define it again. + */ + for (i = 0; i<macnum; i++) { + if (strncmp(name, macros[i].mac_name, (size_t)8) == 0) { + if (parsing_rc) { + /* Just shut up and read in the macro, but don't save it, + * because we already have it. + */ + while ((cp = FGets(str, fp)) != NULL) { + /* See if we have a 'blank' line: just whitespace. */ + while (*cp && isspace(*cp)) ++cp; + if (!*cp) + break; + } + } else + (void) fprintf(stderr, + "There is already a macro named '%s.'\n", name); + return -1; + } + } + (void) strncpy(macros[macnum].mac_name, name, (size_t)8); + if (macnum == 0) + macros[macnum].mac_start = macbuf; + else + macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; + tmp = macros[macnum].mac_start; + while (1) { + cp = FGets(str, fp); + if (cp == NULL) { + /* + * If we had started a macro, we will say it is + * okay to skip the blank line delimiter if we + * are at the EOF. + */ + if (tmp > macros[macnum].mac_start) + goto endmac; + (void) fprintf(stderr, "No text supplied for macro \"%s.\"\n", name); + } + /* see if we have a 'blank' line: just whitespace. */ + while (*cp && isspace(*cp)) ++cp; + if (*cp == '\0') { + /* Blank line; end this macro. */ +endmac: + macros[macnum++].mac_end = tmp; + return 0; + } + /* Add the text of this line to the macro. */ + len = strlen(cp) + 1; /* we need the \0 too. */ + if (tmp + len >= macbuf + MACBUFLEN) { + (void) fprintf(stderr, "Macro \"%s\" not defined -- %d byte buffer exceeded.\n", name, MACBUFLEN); + return -1; + } + (void) strcpy(tmp, cp); + tmp += len; + } +} /* make_macro */ + + + + +int macdef(int argc, char **argv) +{ + if (argc < 2) + argv = re_makeargv("(macro name) ", &argc); + if (argc != 2) { + (void) domacro(0, NULL); + return USAGE; + } + (void) printf("Enter macro line by line, terminating it with a blank line\n"); + (void) make_macro(argv[1], stdin); + return NOERR; +} /* macdef */ + + + + +int domacro(int argc, char **argv) +{ + register int i, j; + register char *cp1, *cp2; + int count = 2, loopflg = 0; + string str; + struct cmd *c; + + if (argc < 2) { + /* print macros. */ + if (macnum == 0) + (void) printf("No macros defined.\n"); + else { + (void) printf("Current macro definitions:\n"); + for (i = 0; i < macnum; ++i) { + (void) printf("%s:\n", macros[i].mac_name); + cp1 = macros[i].mac_start; + cp2 = macros[i].mac_end; + while (cp1 < cp2) { + (void) printf(" > "); + while (cp1 < cp2 && *cp1) + putchar(*cp1++); + ++cp1; + } + } + } + if (argc == 0) return (NOERR); /* called from macdef(), above. */ + argv = re_makeargv("(macro to run) ", &argc); + } + if (argc < 2) { + return USAGE; + } + for (i = 0; i < macnum; ++i) { + if (!strncmp(argv[1], macros[i].mac_name, (size_t) 9)) { + break; + } + } + if (i == macnum) { + (void) printf("'%s' macro not found.\n", argv[1]); + return USAGE; + } + doingInitMacro = (strcmp(macros[i].mac_name, "init") == 0); + (void) Strncpy(str, line); +TOP: + cp1 = macros[i].mac_start; + while (cp1 != macros[i].mac_end) { + while (isspace(*cp1)) { + cp1++; + } + cp2 = line; + while (*cp1 != '\0') { + switch(*cp1) { + case '\\': + *cp2++ = *++cp1; + break; + case '$': + if (isdigit(*(cp1+1))) { + j = 0; + while (isdigit(*++cp1)) { + j = 10*j + *cp1 - '0'; + } + cp1--; + if (argc - 2 >= j) { + (void) strcpy(cp2, argv[j+1]); + cp2 += strlen(argv[j+1]); + } + break; + } + if (*(cp1+1) == 'i') { + loopflg = 1; + cp1++; + if (count < argc) { + (void) strcpy(cp2, argv[count]); + cp2 += strlen(argv[count]); + } + break; + } + /* intentional drop through */ + default: + *cp2++ = *cp1; + break; + } + if (*cp1 != '\0') { + cp1++; + } + } + *cp2 = '\0'; + makeargv(); + c = getcmd(margv[0]); + if ((c == (struct cmd *) -1) && !parsing_rc) { + (void) printf("?Ambiguous command\n"); + } else if (c == NULL && !parsing_rc) { + (void) printf("?Invalid command\n"); + } else if (c->c_conn && !connected) { + (void) printf("Not connected.\n"); + } else { + if (IS_VVERBOSE) + (void) printf("%s\n",line); + if ((*c->c_handler)(margc, margv) == USAGE) + cmd_usage(c); + (void) strcpy(line, str); + makeargv(); + argc = margc; + argv = margv; + } + if (cp1 != macros[i].mac_end) { + cp1++; + } + } + if (loopflg && ++count < argc) { + goto TOP; + } + doingInitMacro = 0; + return NOERR; +} /* domacro */ + + + +/* + * get size of file on remote machine + */ +int sizecmd(int argc, char **argv) +{ + string str; + + if (argc < 2) + argv = re_makeargv("(remote-file) ", &argc); + if (argc < 2) { + return USAGE; + } + if (rem_glob_one(argv[1]) == 0) { + (void) sprintf(str, "SIZE %s", argv[1]); + (void) verbose_command(str); + } + return NOERR; +} /* sizecmd */ + + + + +/* + * get last modification time of file on remote machine + */ +int modtime(int argc, char **argv) +{ + int overbose; + string str; + + if (argc < 2) + argv = re_makeargv("(remote-file) ", &argc); + if (argc < 2) { + return USAGE; + } + if (rem_glob_one(argv[1]) == 0) { + overbose = verbose; + if (debug == 0) + verbose = V_QUIET; + (void) sprintf(str, "MDTM %s", argv[1]); + if (command(str) == COMPLETE) { + int yy, mo, day, hour, min, sec; + (void) sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec); + /* might want to print this in local time */ + (void) printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], + mo, day, yy, hour, min, sec); + } else + (void) fputs(reply_string, stdout); + verbose = overbose; + } + return NOERR; +} /* modtime */ + + + +int lookup(int argc, char **argv) +{ + int i, j, by_name, result = NOERR; + struct hostent *host; /* structure returned by gethostbyaddr() */ + extern int h_errno; +#ifdef BAD_INETADDR + struct in_addr addr; /* address in host order */ +# define ADDR addr.s_addr +#else + unsigned long addr; /* address in host order */ +# define ADDR addr +#endif + + if (argc < 2) + argv = re_makeargv("(sitename) ", &argc); + if (argc < 2) { + return USAGE; + } + + lasthostname[0] = 0; + for (i=1; i<argc; i++) { + /* does the argument look like an address? */ + if (4 == sscanf (argv[i], "%d.%d.%d.%d", &j, &j, &j, &j)) { + /* ip */ + addr = inet_addr (argv[i]); + if (ADDR == 0xffffffff) { + (void) fprintf(stderr, "## could not convert \"%s\" into a valid IP address.\n", argv[i]); + continue; + } + host = gethostbyaddr ((char *) &ADDR, 4, AF_INET); + by_name = 0; + } else { + /* name */ + host = gethostbyname (argv[i]); + by_name = 1; + } + if (host == NULL) { + if (NOT_VQUIET) { + /* gethostxxx error */ + if (h_errno == HOST_NOT_FOUND) { + (void) printf("%s: lookup error (%d).\n", + argv[i], h_errno); + result = h_errno; + } else { + (void) printf("%s \"%s\"\n", + (by_name==0 ? "unknown address" : "unknown host"), + argv[i]); + result = + h_errno != 0 ? h_errno : + -1; + } + } + } else { + if (*host->h_name) + (void) Strncpy(lasthostname, host->h_name); + for (j=0; host->h_aliases[j] != NULL; j++) { + if (strlen(host->h_aliases[j]) > + strlen(host->h_name) && + strstr(host->h_aliases[j],host->h_name) != NULL) + (void) Strncpy(lasthostname,host->h_aliases[j]); + } + if (NOT_VQUIET) { + (void) printf("%-32s ", *host->h_name ? host->h_name : "???"); + if (*host->h_addr_list) { + unsigned long horder; + + horder = ntohl (*(unsigned long *) *(char **)host->h_addr_list); + (void) printf ("%lu.%lu.%lu.%lu\n", + (horder >> 24), + (horder >> 16) & 0xff, + (horder >> 8) & 0xff, + horder & 0xff); + } + else (void) printf("???\n"); + } + } + } /* loop thru all sites */ + return result; +} /* lookup */ + + + + +int getlocalhostname(char *host, size_t size) +{ + int oldv, r; + char *argv[2]; + char domain[64]; + +#ifdef HOSTNAME + (void) strncpy(host, HOSTNAME, size); + return NOERR; +#else + host[0] = '\0'; + if ((r = gethostname(host, size)) == 0) { + if (host[0] == '\0') { + (void) fprintf(stderr, +"Could not determine the hostname. Re-compile with HOSTNAME defined\n\ +to be the full name of your hostname.\n"); + exit(1); + } + oldv = verbose; + verbose = V_QUIET; + argv[0] = "lookup"; + (void) sprintf(line, "lookup %s", host); + (void) makeargv(); + if (lookup(margc, margv) == 0 && lasthostname[0]) { + (void) _Strncpy(host, lasthostname, size); + domain[0] = '\0'; +#ifdef HAS_DOMAINNAME + /* getdomainname() returns just the domain name, without a + * preceding period. For example, on "cse.unl.edu", it would + * return "unl.edu". + * + * SunOS note: getdomainname will return an empty string if + * this machine isn't on NIS. + */ + (void) getdomainname(domain, sizeof(domain) - 1); +#endif +#ifdef DOMAIN_NAME + (void) Strncpy(domain, DOMAIN_NAME); +#endif + if (index(host, '.') == NULL) { + /* If the hostname has periods we'll assume that the + * it includes the domain name already. Some gethostname()s + * return the whole host name, others just the machine name. + * If we have just the machine name and we successfully + * found out the domain name (from above), we'll append + * the domain to the machine to get a full hostname. + */ + if (domain[0]) { + (void) _Strncat(host, ".", size); + (void) _Strncat(host, domain, size); + } else { + fprintf(stderr, +"WARNING: could not determine full host name (have: '%s').\n\ +The program should be re-compiled with DOMAIN_NAME defined to be the\n\ +domain name, i.e. -DDOMAIN_NAME=\\\"unl.edu\\\"\n\n", + host); + } + } + } + verbose = oldv; + } + return r; +#endif +} /* getlocalhostname */ + + + + +/* + * show status on remote machine + */ +int rmtstatus(int argc, char **argv) +{ + string str; + + if (argc > 1) { + (void) sprintf(str, "STAT %s" , argv[1]); + (void) verbose_command(str); + } else (void) verbose_command("STAT"); + return NOERR; +} /* rmtstatus */ + + + + +/* + * create an empty file on remote machine. + */ +int create(int argc, char **argv) +{ + string str; + FILE *ftemp; + + if (argc < 2) + argv = re_makeargv("(remote-file) ", &argc); + if (argc < 2) { + return USAGE; + } + (void) tmp_name(str); + ftemp = fopen(str, "w"); + /* (void) fputc('x', ftemp); */ + (void) fclose(ftemp); + creating = 1; + (void) sendrequest("STOR", str, argv[1]); + creating = 0; + (void) unlink(str); + return NOERR; +} /* create */ + + + + +/* show version info */ +/*ARGSUSED*/ +int show_version(int argc, char **argv) +{ + char *DStrs[80]; + int nDStrs = 0, i, j; + + (void) printf("%-30s %s\n", "NcFTP Version:", version); + (void) printf("%-30s %s\n", "Author:", + "Mike Gleason, NCEMRSoft (mgleason@cse.unl.edu)."); + +/* Now entering CPP hell... */ +#ifdef __DATE__ + (void) printf("%-30s %s\n", "Compile Date:", __DATE__); +#endif + (void) printf("%-30s %s (%s)\n", "Operating System:", +#ifdef System + System, +#else +# ifdef unix + "UNIX", +# else + "??", +# endif +#endif +#ifdef SYSV + "SYSV"); +#else +# ifdef BSD + "BSD"); +# else + "neither BSD nor SYSV?"); +# endif +#endif + + /* Show which CPP symbols were used in compilation. */ +#ifdef __GNUC__ + DStrs[nDStrs++] = "__GNUC__"; +#endif +#ifdef RINDEX + DStrs[nDStrs++] = "RINDEX"; +#endif +#ifdef CURSES + DStrs[nDStrs++] = "CURSES"; +#endif +#ifdef NO_CURSES_H + DStrs[nDStrs++] = "NO_CURSES_H"; +#endif +#ifdef HERROR + DStrs[nDStrs++] = "HERROR"; +#endif +#ifdef U_WAIT + DStrs[nDStrs++] = "U_WAIT"; +#endif +#if defined(NO_CONST) || defined(const) + DStrs[nDStrs++] = "NO_CONST"; +#endif +#ifdef NO_FORMATTING + DStrs[nDStrs++] = "NO_FORMATTING"; +#endif +#ifdef DONT_TIMESTAMP + DStrs[nDStrs++] = "DONT_TIMESTAMP"; +#endif +#ifdef GETPASS + DStrs[nDStrs++] = "GETPASS"; +#endif +#ifdef HAS_GETCWD + DStrs[nDStrs++] = "HAS_GETCWD"; +#endif +#ifdef GETCWDSIZET + DStrs[nDStrs++] = "GETCWDSIZET"; +#endif +#ifdef HAS_DOMAINNAME + DStrs[nDStrs++] = "HAS_DOMAINNAME"; +#endif +#ifdef DOMAIN_NAME + DStrs[nDStrs++] = "DOMAIN_NAME"; +#endif +#ifdef Solaris + DStrs[nDStrs++] = "Solaris"; +#endif +#ifdef USE_GETPWUID + DStrs[nDStrs++] = "USE_GETPWUID"; +#endif +#ifdef HOSTNAME + DStrs[nDStrs++] = "HOSTNAME"; +#endif +#ifdef SYSDIRH + DStrs[nDStrs++] = "SYSDIRH"; +#endif +#ifdef SYSSELECTH + DStrs[nDStrs++] = "SYSSELECTH"; +#endif +#ifdef TERMH + DStrs[nDStrs++] = "TERMH"; +#endif +#ifdef NO_UNISTDH + DStrs[nDStrs++] = "NO_UNISTDH"; +#endif +#ifdef NO_STDLIBH + DStrs[nDStrs++] = "NO_STDLIBH"; +#endif +#ifdef SYSLOG + DStrs[nDStrs++] = "SYSLOG"; +#endif +#ifdef BAD_INETADDR + DStrs[nDStrs++] = "BAD_INETADDR"; +#endif +#ifdef SGTTYB + DStrs[nDStrs++] = "SGTTYB"; +#endif +#ifdef TERMIOS + DStrs[nDStrs++] = "TERMIOS"; +#endif +#ifdef STRICT_PROTOS + DStrs[nDStrs++] = "STRICT_PROTOS"; +#endif +#ifdef dFTP_PORT + DStrs[nDStrs++] = "dFTP_PORT"; +#endif +#ifdef BROKEN_MEMCPY + DStrs[nDStrs++] = "BROKEN_MEMCPY"; +#endif +#ifdef READLINE + DStrs[nDStrs++] = "READLINE"; +#endif +#ifdef GETLINE + DStrs[nDStrs++] = "GETLINE"; +#endif +#ifdef _POSIX_SOURCE + DStrs[nDStrs++] = "_POSIX_SOURCE"; +#endif +#ifdef _XOPEN_SOURCE + DStrs[nDStrs++] = "_XOPEN_SOURCE"; +#endif +#ifdef NO_TIPS + DStrs[nDStrs++] = "NO_TIPS"; +#endif +#ifdef GZCAT + DStrs[nDStrs++] = "GZCAT"; +#endif +#ifdef LINGER + DStrs[nDStrs++] = "LINGER"; +#endif +#ifdef TRY_NOREPLY + DStrs[nDStrs++] = "TRY_NOREPLY"; +#endif +#ifdef NO_UTIMEH + DStrs[nDStrs++] = "NO_UTIMEH"; +#endif +#ifdef DB_ERRS + DStrs[nDStrs++] = "DB_ERRS"; +#endif +#ifdef NO_VARARGS + DStrs[nDStrs++] = "NO_VARARGS"; +#endif +#ifdef NO_STDARGH + DStrs[nDStrs++] = "NO_STDARGH"; +#endif +#ifdef NO_MKTIME + DStrs[nDStrs++] = "NO_MKTIME"; +#endif +#ifdef NO_STRSTR + DStrs[nDStrs++] = "NO_STRSTR"; +#endif +#ifdef NO_STRFTIME + DStrs[nDStrs++] = "NO_STRFTIME"; +#endif +#ifdef NO_RENAME + DStrs[nDStrs++] = "NO_RENAME"; +#endif +#ifdef TRY_ABOR + DStrs[nDStrs++] = "TRY_ABOR"; +#endif +#ifdef GATEWAY + DStrs[nDStrs++] = "GATEWAY"; +#endif +#ifdef SOCKS + DStrs[nDStrs++] = "SOCKS"; +#endif +#ifdef NET_ERRNO_H + DStrs[nDStrs++] = "NET_ERRNO_H"; +#endif +#ifdef PASSIVEMODE + DStrs[nDStrs++] = "PASSIVEMODE"; +#endif + + +/* DONE with #ifdefs for now! */ + + (void) printf ("\nCompile Options:\n"); + for (i=j=0; i<nDStrs; i++) { + if (j == 0) + (void) printf(" "); + (void) printf("%-15s", DStrs[i]); + if (++j == 4) { + j = 0; + (void) putchar('\n'); + } + } + if (j != 0) + (void) putchar('\n'); + +#ifdef MK + (void) printf("\nMK: %s\n", MK); +#endif /* MK */ + + (void) printf("\nDefaults:\n"); + (void) printf("\ + Xfer Buf Size: %8d Debug: %d MPrompt: %d Verbosity: %d\n\ + Prompt: %s Pager: %s ZCat: %s\n\ + Logname: %s Logging: %d Type: %s Cmd Len: %d\n\ + Recv Line Len: %d #Macros: %d Macbuf: %d Auto-Binary: %d\n\ + Recent File: %s Recent On: %d nRecents: %d\n\ + Redial Delay: %d Anon Open: %d New Mail Message: \"%s\"\n", + MAX_XFER_BUFSIZE, dDEBUG, dMPROMPT, dVERBOSE, + dPROMPT, dPAGER, ZCAT, + dLOGNAME, dLOGGING, dTYPESTR, CMDLINELEN, + RECEIVEDLINELEN, MAXMACROS, MACBUFLEN, dAUTOBINARY, + dRECENTF, dRECENT_ON, dMAXRECENTS, + dREDIALDELAY, dANONOPEN, NEWMAILMESSAGE + ); +#ifdef GATEWAY + (void) printf("\ + Gateway Login: %s\n", dGATEWAY_LOGIN); +#endif + return NOERR; +} /* show_version */ + + + +void PurgeLineBuffer(void) +{ + register struct lslist *a, *b; + + for (a = lshead; a != NULL; ) { + b = a->next; + if (a->string) + free(a->string); /* free string */ + Free(a); /* free node */ + a = b; + } + lshead = lstail = NULL; +} /* PurgeLineBuffer */ + + + + +/*ARGSUSED*/ +int ShowLineBuffer(int argc, char **argv) +{ + register struct lslist *a = lshead; + int pagemode; + FILE *fp; + Sig_t oldintp; + + if (a == NULL) + return CMDERR; + pagemode= (**argv) == 'p' && pager[0] == '|'; + if (pagemode) { + fp = popen(pager + 1, "w"); + if (!fp) { + PERROR("ShowLineBuffer", pager + 1); + return CMDERR; + } + } else + fp = stdout; + oldintp = Signal(SIGPIPE, SIG_IGN); + while (a) { + if (a->string) + (void) fprintf(fp, "%s\n", a->string); + a = a->next; + } + if (pagemode) + (void) pclose(fp); + if (oldintp) + (void) Signal(SIGPIPE, oldintp); + return NOERR; +} /* ShowLineBuffer */ + + + + +#if LIBMALLOC != LIBC_MALLOC +/*ARGSUSED*/ +int MallocStatusCmd(int argc, char **argv) +{ +#if (LIBMALLOC == FAST_MALLOC) + struct mallinfo mi; + + mi = mallinfo(); + printf("\ +total space in arena: %d\n\ +number of ordinary blocks: %d\n\ +number of small blocks: %d\n\ +number of holding blocks: %d\n\ +space in holding block headers: %d\n\ +space in small blocks in use: %d\n\ +space in free small blocks: %d\n\ +space in ordinary blocks in use: %d\n\ +space in free ordinary blocks: %d\n\ +cost of enabling keep option: %d\n", + mi.arena, + mi.ordblks, + mi.smblks, + mi.hblks, + mi.hblkhd, + mi.usmblks, + mi.fsmblks, + mi.uordblks, + mi.fordblks, + mi.keepcost + ); +#else +#if (LIBMALLOC == DEBUG_MALLOC) + printf("malloc_chain_check: %d\n\n", malloc_chain_check(0)); + if (argc > 1) + malloc_dump(1); + printf("malloc_inuse: %lu\n", malloc_inuse(NULL)); +#else + printf("Nothing to report.\n"); +#endif /* (LIBMALLOC == DEBUG_MALLOC) */ +#endif /* (LIBMALLOC == FAST_MALLOC) */ + + return (0); +} /* MallocStatusCmd */ +#endif /* LIBMALLOC */ + + + + +/*ARGSUSED*/ +int unimpl(int argc, char **argv) +{ + if (!parsing_rc) + (void) printf("%s: command not supported. (and probably won't ever be).\n", argv[0]); + return (NOERR); +} /* unimpl */ + +#ifdef PASSIVEMODE +int setpassive(int argc, char **argv) +{ + passivemode = !passivemode; + printf( "Passive mode %s.\n", (passivemode ? "ON" : "OFF") ); + return NOERR; +} +#endif + + +/* eof cmds.c */ |