home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-07 | 54.1 KB | 2,492 lines |
- Newsgroups: comp.sources.misc
- From: mgleason@cse.unl.edu (Mike Gleason)
- Subject: v34i014: ncftp - Alternative User Interface for FTP, Part01/03
- Message-ID: <csm-v34i014=ncftp.150928@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 9ee3036605bd11603fa19c3d17f5fe55
- Date: Mon, 7 Dec 1992 21:10:05 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: mgleason@cse.unl.edu (Mike Gleason)
- Posting-number: Volume 34, Issue 14
- Archive-name: ncftp/part01
- Environment: UNIX, ANSI-C, getopt
-
- ncftp - Alternative user interface for FTP
- version 1.0 by Mike Gleason, NCEMRSoft.
-
- ncftp was created out of disgust with using the regular 'ftp'
- command found on many brands of Unix. People who spend a lot
- of time in ftp will want to install ncftp.
-
- Features:
-
- * No more typing 'anonymous' and your email address every time
- you want to ftp anonymously. You don't need to have the
- site in your .netrc.
-
- * No more typing complete site names. Sites in your .netrc
- can be abbreviated. Type 'o wuar' to call wuarchive.wustl.edu.
-
- * Use your pager (like 'more') to read remote files (and also
- compressed files).
-
- * Use your pager to view remote directory listings.
-
- * Transfers feature a progress meter.
-
- * Implicit cd.
-
- * Fancy prompts.
-
- * You can keep a log of your actions. See what the path was of
- that file you downloaded yesterday so you don't have to
- look for it today.
-
- * Built-in mini-nslookup.
-
- * The 'ls' command is ls -CF. Some ftp's ls was identical to 'dir.'
-
- * You can 'redial' a remote host until you connect.
-
- * Don't need to 'close' a site, just open a new one.
-
- * Don't feel like typing a long filename? Use a wildcard in single
- file commands like get and page.
-
- * You can create empty remote files.
-
- * Supports 'colon mode', so you can type 'ncftp cse.unl.edu:/pub/foo',
- to copy foo into your current directory.
-
- * You can re-display the last directory listing without getting it
- across the network.
-
- * Detects when new mail arrives.
-
- * ncftp is quieter by default -- who cares if the PORT command was
- successful (if you do, turn verbose on :-).
- ------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: cmds.c ftpdefs.h sys.h
- # Wrapped by kent@sparky on Mon Dec 7 15:06:54 1992
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 3)."'
- if test -f 'cmds.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cmds.c'\"
- else
- echo shar: Extracting \"'cmds.c'\" \(44217 characters\)
- sed "s/^X//" >'cmds.c' <<'END_OF_FILE'
- X/* cmds.c */
- X
- X#include "sys.h"
- X#include <sys/types.h>
- X#include <sys/param.h>
- X
- X#ifdef SCO324
- X# include <net/sys/wait.h>
- X#else
- X# include <sys/wait.h>
- X#endif /* SCO324 */
- X
- X#include <sys/stat.h>
- X#include <sys/socket.h>
- X#include <arpa/ftp.h>
- X#include <setjmp.h>
- X#include <signal.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <stdlib.h>
- X#include <errno.h>
- X#include <netdb.h>
- X#include <netinet/in.h>
- X#include <ctype.h>
- X#include <sys/time.h>
- X#include <time.h>
- X#include <unistd.h>
- X#include <termio.h>
- X/* #include <sys/ioctl.h> */
- X#include "ftpdefs.h"
- X#include "defaults.h"
- X#include "cmds.h"
- X#include "main.h"
- X#include "ftp.h"
- X#include "ftprc.h"
- X#include "glob.h"
- X#include "copyright.h"
- X
- X/* cmds.c globals */
- Xint curtype; /* file transfer type */
- Xstr32 curtypename; /* name of file transfer type */
- Xint verbose; /* print messages coming back from server */
- Xint mprompt; /* interactively prompt on m* cmds */
- Xint debug; /* debugging level */
- Xint options; /* used during socket creation */
- Xint macnum; /* number of defined macros */
- Xint paging = 0;
- Xint creating = 0;
- Xstruct macel macros[16];
- Xchar *macbuf; /* holds ALL macros */
- Xjmp_buf jabort;
- Xchar *mname; /* name of current m* command */
- Xint activemcmd; /* flag: if != 0, then active multi command */
- Xstring cwd; /* current remote directory */
- Xstring lcwd; /* current local directory */
- Xchar lasthostname[64]; /* name of last host w/ lookup(). */
- Xint remote_is_unix; /* TRUE if remote host is unix. */
- Xint auto_binary = dAUTOBINARY; /* If TRUE, set binary each connection. */
- X
- X#ifdef REDIR
- Xint is_ls = 0; /* are we doing an ls? if so, then buffer */
- Xstruct lslist *lshead = NULL; /* hold last output from host */
- Xstruct lslist *lstail = NULL;
- X#endif
- X
- X/* cmds.c externs */
- Xextern char *globerr, *home, *reply_string;
- Xextern int code, margc, connected, ansi_escapes;
- Xextern int connected, fromatty, data, want_progress;
- Xextern char *altarg, *line, *margv[];
- Xextern char *globchars;
- Xextern string hostname, progname, pager, anon_password;
- Xextern string prompt, logfname, version;
- Xextern long logsize, eventnumber;
- Xextern size_t xferbufsize;
- Xextern struct servent *sp;
- Xextern struct cmd cmdtab[];
- Xextern struct userinfo uinfo;
- Xextern FILE *cin, *cout, *logf;
- Xextern int optind;
- Xextern char *optarg;
- X
- Xstruct var vars[] = {
- X { "anon-password", STR, 0, anon_password, (setvarproc) 0 },
- X { "ansi-escapes", INT, 0, &ansi_escapes, (setvarproc) 0 },
- X { "auto-binary", INT, 0, &auto_binary, (setvarproc) 0 },
- X { "debug", INT, 0, &debug, (setvarproc) 0 },
- X { "local-dir", STR, 0, lcwd, set_ldir },
- X { "logfile", STR, 0, logfname, set_log },
- X { "logsize", LONG, 0, &logsize, (setvarproc) 0 },
- X { "mprompt", INT, 0, &mprompt, (setvarproc) 0 },
- X { "pager", STR, 0, pager + 1, set_pager },
- X { "prompt", STR, 0, prompt, set_prompt },
- X { "progress-reports", INT, 0, &want_progress, (setvarproc) 0 },
- X { "remote-is-unix", INT, 1, &remote_is_unix,(setvarproc) 0 },
- X { "type", STR, 1, curtypename, set_type },
- X { "verbose", INT, 0, &verbose, (setvarproc) 0 }
- X};
- X
- Xstruct types types[] = {
- X { "ascii", "A", TYPE_A, 0 },
- X { "binary", "I", TYPE_I, 0 },
- X { "image", "I", TYPE_I, 0 },
- X { "ebcdic", "E", TYPE_E, 0 },
- X { "tenex", "L", TYPE_L, "8" },
- X 0
- X};
- X
- X
- Xchar **re_makeargv(char *promptstr, int *argc)
- X{
- X (void) strcat(line, " ");
- X (void) printf(promptstr);
- X (void) gets(&line[strlen(line)]);
- X (void) makeargv();
- X *argc = margc;
- X return (margv);
- X} /* re_makeargv */
- X
- X
- X
- Xchar *get_cwd(char *buf, int size)
- X{
- X#ifdef SYSV
- X extern char *getcwd(char *, int);
- X return (getcwd(buf, size - 1));
- X#else
- X extern char *getwd(char *);
- X return (getwd(buf));
- X#endif
- X} /* get_cwd */
- X
- X/*
- X * Connect to peer server and
- X * auto-login, if possible.
- X */
- X
- Xint setpeer(int argc, char **argv)
- X{
- X char *path;
- X unsigned int port;
- X time_t now;
- X int openmode = 1, tmpverbose, opt, hErr;
- X int redial_delay = dREDIALDELAY;
- X int ignore_rc = 0, dials, max_dials = 1;
- X string pathname, newhost;
- X char *cmdname = argv[0];
- X
- X port = sp->s_port;
- X optind = 1;
- X while ((opt = getopt(argc, argv, "aiup:rd:g:")) >= 0) {
- X switch (opt) {
- X case 'a': openmode = OPEN_A; break;
- X case 'u': openmode = OPEN_U; break;
- X case 'i': ignore_rc = 1; break;
- X case 'p':
- X port = atoi(optarg);
- X if (port <= 0) {
- X (void) printf("%s: bad port number (%s).\n", cmdname, optarg);
- X goto usage;
- X }
- X port = htons(port);
- X break;
- X case 'd': redial_delay = atoi(optarg); break;
- X case 'g': max_dials = atoi(optarg); break;
- X case 'r': max_dials = -1; break;
- X default:
- X usage:
- X (void) printf("usage: %s [-a | -u] [-i] [-p N] [-r [-d N] [-g N]] hostname[:pathname]\n\
- X -a : Open anonymously (this is the default).\n\
- X -u : Open, specify user/password.\n\
- X -i : Ignore machine entry in your .netrc.\n\
- X -p N : Use port #N for connection.\n\
- X -r : \"Redial\" until connected.\n\
- X -d N : Redial, pausing N seconds between tries.\n\
- X -g N : Redial, giving up after N tries.\n\
- X :path : Open site, then retrieve file \"path.\"\n", cmdname);
- X code = -1;
- X return;
- X }
- X }
- X
- X if (argv[optind] == NULL)
- X goto usage;
- X (void) Strncpy(newhost, argv[optind]);
- X if (connected) {
- X if (NOT_VQUIET && hostname != NULL)
- X (void) printf("Closing %s...\n", hostname);
- X (void) disconnect(0, NULL);
- X }
- X
- X /*
- X * If we are given something like wuarchive.wustl.edu:/pub/foo,
- X * try to connect to the site then first try to cd to /pub/foo,
- X * or if that fails, assume it is a file then try to fetch
- X * /pub/foo and write foo in the current local directory.
- X */
- X if ((path = index(newhost, ':')) != NULL) {
- X *path++ = 0;
- X (void) Strncpy(pathname, path);
- X }
- X
- X GetFullSiteName(newhost);
- X for (dials = 0; max_dials < 0 || dials < max_dials; dials++) {
- X if (dials > 0) {
- X (void) sleep(redial_delay);
- X (void) fprintf(stderr, "Retry Number: %d\n", dials + 1);
- X }
- X hErr = hookup(newhost, port);
- X if (hErr == -2) /* Recoverable, so we can try again. */
- X continue;
- X else if (hErr == 0) {
- X connected = 1;
- X tmpverbose = verbose;
- X if (debug == 0)
- X verbose = V_QUIET;
- X remote_is_unix = 1;
- X if (command("SYST") == COMPLETE) {
- X if (tmpverbose) {
- X register char *cp, c;
- X cp = index(reply_string+4, ' ');
- X if (cp == NULL)
- X cp = index(reply_string+4, '\r');
- X if (cp) {
- X if (cp[-1] == '.')
- X cp--;
- X c = *cp;
- X *cp = '\0';
- X }
- X
- X (void) printf("Remote system type is %s.\n",
- X reply_string+4);
- X if (cp)
- X *cp = c;
- X }
- X remote_is_unix = !strncmp(reply_string + 4, "UNIX", (size_t) 4);
- X }
- X
- X if (auto_binary || path || !strncmp(reply_string, "215 UNIX Type: L8", (size_t) 17)) {
- X _settype("binary");
- X if (tmpverbose > V_TERSE)
- X (void) printf("Using %s mode to transfer files.\n", curtypename);
- X }
- X if (tmpverbose >= V_ERRS &&
- X !strncmp(reply_string, "215 TOPS20", (size_t) 10)) {
- X (void) printf(
- X "Remember to set tenex mode when transfering _binary_ files from this machine.\n");
- X }
- X verbose = tmpverbose;
- X
- X if (!login(newhost, openmode, ignore_rc) || cout == NULL)
- X goto nextdial; /* error! */
- X if (logf != NULL) {
- X (void) time(&now);
- X (void) fprintf(logf, "%s opened at %s",
- X hostname,
- X ctime(&now));
- X }
- X
- X /* Freshen 'cwd' variable for the prompt. */
- X (void) _cd(NULL);
- X if (path != NULL) {
- X if (! _cd(pathname)) {
- X /* Couldn't cd to this path, must be a file then. */
- X (void) sprintf(line, "get %s", pathname);
- X makeargv();
- X (void) get(margc, margv);
- X /* If we were invoked from the command line, quit
- X * after we got this file.
- X */
- X if (eventnumber == 0L) {
- X (void) quit(0, NULL);
- X }
- X }
- X }
- X break;
- X /* end if we are connected */
- X } else {
- X /* Irrecoverable error, so don't bother redialing. */
- X break;
- X }
- Xnextdial: continue;
- X }
- X} /* setpeer */
- X
- X
- X/*
- X * Set transfer type.
- X */
- Xint settype(int argc, char **argv)
- X{
- X if (argc > 2) {
- X (void) printf("usage: %s [ ascii | binary | ebcdic | image | tenex ]\n", argv[0]);
- X code = -1;
- X return;
- X }
- X code = 0;
- X if (argc < 2) {
- Xxx: (void) printf("Using %s mode to transfer files.\n", curtypename);
- X return;
- X }
- X _settype(argv[1]);
- X if (IS_VVERBOSE)
- X goto xx;
- X} /* settype */
- X
- X
- X
- X
- Xvoid _settype(char *typename)
- X{
- X register struct types *p;
- X int comret, i;
- X string cmd;
- X
- X switch (tolower(*typename)) {
- X case 'a': i = 0; break;
- X case 'b': i = 1; break;
- X case 'i': i = 2; break;
- X case 'e': i = 3; break;
- X case 't': i = 4;
- X (void) strcpy(cmd, "TYPE L 8");
- X goto xx;
- X default:
- X (void) printf("%s: unknown type\n", typename);
- X code = -1;
- X return;
- X }
- X p = &types[i];
- X (void) sprintf(cmd, "TYPE %s", p->t_mode);
- Xxx: comret = command(cmd);
- X if (comret == COMPLETE) {
- X (void) Strncpy(curtypename, p->t_name);
- X curtype = p->t_type;
- X }
- X} /* _settype */
- X
- X
- X
- X
- X/*ARGSUSED*/
- Xint setbinary(int argc, char **argv) { _settype("binary"); }
- X/*ARGSUSED*/
- Xint setascii(int argc, char **argv) { _settype("ascii"); }
- X
- X
- X
- Xvoid set_prompt(char *new, int unset)
- X{
- X (void) Strncpy(prompt, (unset || !new || !*new) ? dPROMPT : new);
- X init_prompt();
- X} /* set_prompt */
- X
- X
- X
- X
- Xvoid set_log(char *fname, int unset)
- X{
- X if (logf) {
- X (void) fclose(logf);
- X logf = NULL;
- X }
- X if (!unset && fname && *fname) {
- X (void) Strncpy(logfname, fname);
- X logf = fopen (logfname, "a");
- X }
- X} /* set_log */
- X
- X
- X
- X
- Xvoid set_pager(char *new, int unset)
- X{
- X if (unset)
- X (void) strcpy(pager, "-");
- X else {
- X if (!new)
- X new = dPAGER;
- X if (!*new)
- X (void) strcpy(pager, "-");
- X else if (*new != '-')
- X (void) sprintf(pager, "|%s", (*new == '|' ? new + 1 : new));
- X }
- X} /* set_pager */
- X
- X
- X
- X
- Xvoid set_type(char *newtype, int unset)
- X{
- X int t = verbose;
- X verbose = V_QUIET;
- X if (!connected && t > V_QUIET)
- X (void) printf("Not connected.\n");
- X else
- X _settype(newtype && !unset ? newtype : "image");
- X verbose = t;
- X} /* set_type */
- X
- X
- X
- X
- Xvoid set_ldir(char *ldir, int unset)
- X{
- X int t = verbose;
- X char *argv[2];
- X
- X if (ldir && !unset) {
- X verbose = V_QUIET;
- X argv[1] = ldir;
- X lcd(2, argv);
- X verbose = t;
- X }
- X} /* set_ldir */
- X
- X
- X
- X
- Xint set(int argc, char **argv)
- X{
- X int unset, i, c;
- X struct var *v;
- X char *var, *val = NULL;
- X
- X if (argc < 2) {
- X /* Show all variables. */
- X for (i=0; i<sizeof(vars)/sizeof(struct var); i++) {
- X (void) printf("%-20s= ", vars[i].name);
- X c = vars[i].type;
- X if (c < 0) c = -c;
- X if (vars[i].conn_required && !connected)
- X (void) printf("(not connected)\n");
- X else switch (c) {
- X case INT:
- X (void) printf("%d\n", *(int *)vars[i].var); break;
- X case LONG:
- X (void) printf("%ld\n", *(long *)vars[i].var); break;
- X case STR:
- X (void) printf("%s\n", (char *) vars[i].var); break;
- X }
- X }
- X } else {
- X unset = argv[0][0] == 'u';
- X var = argv[1];
- X if (argc == 2)
- X val = NULL;
- X else if (argc > 2) {
- X /* could be =, value or just value. */
- X if (*argv[2] == '=') {
- X if (argc > 3)
- X val = argv[3];
- X else return; /* can't do 'set var =' */
- X } else
- X val = argv[2];
- X }
- X for (i=0, v=NULL; i<sizeof(vars)/sizeof(struct var); i++) {
- X if (strncmp(vars[i].name, var, sizeof(vars[i].name)) == 0) {
- X v = &vars[i];
- X break;
- X }
- X }
- X if (v == NULL)
- X (void) fprintf(stderr, "%s: unknown variable.\n", var);
- X else {
- X if (v->conn_required && !connected)
- X (void) fprintf(stderr, "%s: must be connected.\n", var);
- X else if (v->type < 0)
- X (void) fprintf(stderr, "%s: read-only variable.\n", var);
- X else if (v->proc != (setvarproc) 0)
- X (*v->proc)(val, unset); /* a custom set proc. */
- X else if (unset) switch(v->type) {
- X case INT:
- X *(int *) v->var = 0; break;
- X case LONG:
- X *(long *) v->var = 0; break;
- X case STR:
- X *(char *) v->var = 0; break;
- X } else {
- X if (val == NULL) switch(v->type) {
- X /* User just said "set varname" */
- X case INT:
- X *(int *) v->var = 1; break;
- X case LONG:
- X *(long *) v->var = 1; break;
- X case STR:
- X *(char *) v->var = 0; break;
- X } else {
- X /* User said "set varname = value" */
- X switch (v->type) {
- X case INT:
- X (void) sscanf(val, "%d", (int *) v->var); break;
- X case LONG:
- X (void) sscanf(val, "%ld", (long *) v->var); break;
- X case STR:
- X (void) strcpy(v->var, val); break;
- X }
- X }
- X }
- X }
- X }
- X} /* set */
- X
- X
- X
- X
- X/*
- X * Send a single file.
- X */
- Xint put(int argc, char **argv)
- X{
- X char *cmd;
- X char *oldargv1;
- X
- X if (argc == 2) {
- X argc++;
- X argv[2] = argv[1];
- X }
- X if (argc < 2)
- X argv = re_makeargv("(local-file) ", &argc);
- X if (argc < 2) {
- Xusage:
- X (void) printf("usage:%s local-file remote-file\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (argc < 3)
- X argv = re_makeargv("(remote-file) ", &argc);
- X if (argc < 3)
- X goto usage;
- X oldargv1 = argv[1];
- X if (!globulize(&argv[1])) {
- X code = -1;
- X return;
- X }
- X /*
- X * If "globulize" modifies argv[1], and argv[2] is a copy of
- X * the old argv[1], make it a copy of the new argv[1].
- X */
- X if (argv[1] != oldargv1 && argv[2] == oldargv1) {
- X argv[2] = argv[1];
- X }
- X cmd = (argv[0][0] == 'a') ? "APPE" : "STOR";
- X sendrequest(cmd, argv[1], argv[2]);
- X} /* put */
- X
- X
- X
- X
- X/*
- X * Send multiple files.
- X */
- Xint mput(int argc, char **argv)
- X{
- X register int i;
- X void (*oldintr)(int);
- X char *tp;
- X
- X if (argc < 2)
- X argv = re_makeargv("(local-files) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s local-files\n", argv[0]);
- X code = -1;
- X return;
- X }
- X mname = argv[0];
- X activemcmd = 1;
- X oldintr = signal(SIGINT, (void (*)(int)) mabort);
- X (void) setjmp(jabort);
- X for (i = 1; i < argc; i++) {
- X register char **cpp, **gargs;
- X
- X gargs = glob(argv[i]);
- X if (globerr != NULL) {
- X (void) printf("%s\n", globerr);
- X if (gargs) {
- X blkfree(gargs);
- X free(gargs);
- X }
- X continue;
- X }
- X for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
- X if (activemcmd && confirm(argv[0], *cpp)) {
- X tp = *cpp;
- X sendrequest("STOR", *cpp, tp);
- X if (!activemcmd && fromatty) {
- X if (confirm("Continue with","mput")) {
- X activemcmd++;
- X }
- X }
- X }
- X }
- X if (gargs != NULL) {
- X blkfree(gargs);
- X free(gargs);
- X }
- X }
- X (void) signal(SIGINT, oldintr);
- X activemcmd = 0;
- X} /* mput */
- X
- X
- X
- Xint tmp_name(char *str)
- X{
- X (void) strcpy(str, "/tmp/ncftpXXXXXX");
- X return (mktemp(str) == NULL);
- X} /* tmp_name */
- X
- X
- X
- X
- Xint rem_glob_one(char *pattern)
- X{
- X int oldverbose, result = 0;
- X char *cp;
- X string str, tname;
- X FILE *ftemp;
- X
- X /* Check for wildcard characters. */
- X if (*pattern == '|' || strpbrk(pattern, globchars) == NULL)
- X return 0;
- X
- X (void) tmp_name(tname);
- X oldverbose = verbose;
- X verbose = V_QUIET;
- X recvrequest ("NLST", tname, pattern, "w");
- X verbose = oldverbose;
- X ftemp = fopen(tname, "r");
- X if (ftemp == NULL || FGets(str, ftemp) == NULL) {
- X if (NOT_VQUIET)
- X (void) printf("%s: no match.\n", pattern);
- X result = -1;
- X goto done;
- X }
- X if ((cp = index(str, '\n')) != NULL)
- X *cp = '\0';
- X (void) strcpy(pattern, str);
- X cp = FGets(str, ftemp);
- X /* It is an error if the pattern matched more than one file. */
- X if (cp != NULL) {
- X if (NOT_VQUIET)
- X (void) printf("?Ambiguous remote file name.\n");
- X result = -2;
- X }
- Xdone:
- X if (ftemp != NULL)
- X (void) fclose(ftemp);
- X (void) unlink(tname);
- X return (result);
- X} /* rem_glob_one */
- X
- X
- X
- X
- X/*
- X * Receive (and maybe page) one file.
- X */
- Xint get(int argc, char **argv)
- X{
- X string local_file;
- X string remote_file;
- X
- X /* paging mode is set if the command name is 'page' or 'more.' */
- X paging = (**argv != 'g');
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-file) ", &argc);
- X
- X if (argc < 2) {
- X if (paging)
- X (void) printf("usage: %s remote-file\n", argv[0]);
- X else {
- Xgetusage:
- X (void) printf("usage: %s remote-file [local-file]\n", argv[0]);
- X }
- X return;
- X }
- X argv[1] = Strncpy(remote_file, argv[1]);
- X if (rem_glob_one(argv[1]) < 0)
- X return;
- X
- X if (paging) {
- X size_t len = strlen(remote_file);
- X
- X /* Run compressed remote files through zcat, then the pager. */
- X if (remote_file[len - 1] == 'Z' && remote_file[len - 2] == '.') {
- X _settype("b");
- X (void) sprintf(local_file, "|%s", ZCAT);
- X argv[2] = Strncat(local_file, pager);
- X } else
- X argv[2] = pager;
- X } else {
- X /* normal get */
- X if (argc == 2) {
- X (void) Strncpy(local_file, argv[1]);
- X argv[2] = local_file;
- X } else {
- X if (argc < 3)
- X argv = re_makeargv("(local-file) ", &argc);
- X if (argc < 3)
- X goto getusage;
- X if (!globulize(&argv[2])) {
- X code = -1;
- X return;
- X }
- X }
- X }
- X recvrequest("RETR", argv[2], argv[1], "w");
- X paging = 0;
- X} /* get */
- X
- X
- X
- X/*ARGSUSED*/
- Xvoid mabort(int unused)
- X{
- X (void) printf("\n");
- X (void) fflush(stdout);
- X if (activemcmd && fromatty) {
- X if (confirm("Continue with", mname)) {
- X longjmp(jabort,0);
- X }
- X }
- X activemcmd = 0;
- X longjmp(jabort,0);
- X} /* mabort */
- X
- X
- X
- X
- X/*
- X * Get multiple files.
- X */
- Xint mget(int argc, char **argv)
- X{
- X char *cp, *tp;
- X void (*oldintr)(int);
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-files) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s remote-files\n", argv[0]);
- X code = -1;
- X return;
- X }
- X mname = argv[0];
- X activemcmd = 1;
- X oldintr = signal(SIGINT,mabort);
- X (void) setjmp(jabort);
- X while ((cp = remglob(argv)) != NULL) {
- X if (*cp == '\0') {
- X activemcmd = 0;
- X continue;
- X }
- X if (activemcmd && confirm(argv[0], cp)) {
- X tp = cp;
- X recvrequest("RETR", tp, cp, "w");
- X if (!activemcmd && fromatty) {
- X if (confirm("Continue with","mget")) {
- X activemcmd++;
- X }
- X }
- X }
- X }
- X (void) signal(SIGINT,oldintr);
- X activemcmd = 0;
- X} /* mget */
- X
- X
- X
- X
- Xchar *remglob(char *argv[])
- X{
- X static FILE *ftemp = NULL;
- X int oldverbose;
- X char *cp, *mode;
- X static string tmpname, str;
- X
- X if (!activemcmd) {
- Xxx:
- X if (ftemp) {
- X (void) fclose(ftemp);
- X ftemp = NULL;
- X (void) unlink(tmpname);
- X }
- X return(NULL);
- X }
- X if (ftemp == NULL) {
- X (void) tmp_name(tmpname);
- X oldverbose = verbose, verbose = V_QUIET;
- X for (mode = "w"; *++argv != NULL; mode = "a")
- X recvrequest ("NLST", tmpname, *argv, mode);
- X verbose = oldverbose;
- X ftemp = fopen(tmpname, "r");
- X if (ftemp == NULL) {
- X (void) printf("Can't find list of remote files (%s), oops.\n", tmpname);
- X return (NULL);
- X }
- X }
- X if (FGets(str, ftemp) == NULL)
- X goto xx;
- X if ((cp = index(str, '\n')) != NULL)
- X *cp = '\0';
- X return (str);
- X} /* remglob */
- X
- X
- X
- X
- Xchar *
- Xonoff(int bool)
- X{
- X return (bool ? "on" : "off");
- X} /* onoff */
- X
- X
- X
- X
- Xint
- XStrToBool(char *s)
- X{
- X register char c;
- X
- X c = *s | 32; /* lcase(*value) */
- X switch (c) {
- X case 'f': /* false */
- X return (0);
- X case 'o': /* test for "off" and "on" */
- X c = s[1] | 32;
- X return(c == 'f' ? 0 : 1);
- X case 't': /* true */
- X return (1);
- X default: /* 1, 0, -1, other number? */
- X return (atoi(s));
- X }
- X} /* StrToBool */
- X
- X
- X/*
- X * Turn on/off printing of server echo's, messages, and statistics.
- X */
- Xint setverbose(int argc, char **argv)
- X{
- X if (argc > 1)
- X verbose = StrToBool(argv[1]);
- X else verbose = !verbose;
- X /* if (verbose > 0) */
- X (void) printf("Verbose mode %s.\n", onoff(verbose));
- X code = verbose;
- X} /* setverbose */
- X
- X
- X
- X/*
- X * Toggle interactive prompting
- X * during mget, mput, and mdelete.
- X */
- Xint setprompt(int argc, char **argv)
- X{
- X if (argc > 1)
- X mprompt = StrToBool(argv[1]);
- X else mprompt = !mprompt;
- X if (IS_VVERBOSE)
- X (void) printf("Interactive prompting for m* commmands %s.\n", onoff(mprompt));
- X code = mprompt;
- X} /* setprompt */
- X
- X
- X/*
- X * Set debugging mode on/off and/or
- X * set level of debugging.
- X */
- Xint setdebug(int argc, char **argv)
- X{
- X int val;
- X
- X if (argc > 1) {
- X val = StrToBool(argv[1]);
- X if (val < 0) {
- X (void) printf("%s: bad debugging value.\n", argv[1]);
- X code = -1;
- X return;
- X }
- X } else
- X val = !debug;
- X debug = val;
- X fix_options();
- X if (IS_VVERBOSE)
- X (void) printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
- X code = debug > 0;
- X} /* debug */
- X
- X
- X
- Xvoid fix_options(void)
- X{
- X if (debug)
- X options |= SO_DEBUG;
- X else
- X options &= ~SO_DEBUG;
- X} /* fix_options */
- X
- X
- X
- X/*
- X * Set current working directory
- X * on remote machine.
- X */
- Xint cd(int argc, char **argv)
- X{
- X if (argc < 2)
- X argv = re_makeargv("(remote-directory) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s remote-directory\n", argv[0]);
- X code = -1;
- X return;
- X }
- X (void) _cd(argv[1]);
- X} /* cd */
- X
- X
- X
- X
- Xint implicit_cd(char *dir)
- X{
- X int i, j = 0;
- X
- X if (connected) {
- X i = verbose;
- X verbose = V_QUIET;
- X j = _cd(dir);
- X verbose = i;
- X }
- X return j;
- X} /* implicit_cd */
- X
- X
- X
- X
- Xint _cd(char *dir)
- X{
- X register char *cp;
- X int result = 0, tmpverbose;
- X string str;
- X
- X if (dir == NULL)
- X goto getrwd;
- X if (result = rem_glob_one(dir) < 0)
- X return result;
- X if (strncmp(dir, "CDUP", (size_t) 4) == 0)
- X (void) Strncpy(str, dir);
- X else
- X (void) sprintf(str, "CWD %s", dir);
- X if (command(str) != 5) {
- Xgetrwd:
- X /* (void) Strncpy(cwd, dir); */
- X tmpverbose = verbose; verbose = V_QUIET;
- X (void) command("PWD");
- X verbose = tmpverbose;
- X cp = rindex(reply_string, '\"');
- X if (cp != NULL) {
- X result = 1;
- X *cp = '\0';
- X cp = index(reply_string, '\"');
- X if (cp != NULL)
- X (void) Strncpy(cwd, ++cp);
- X }
- X }
- X if (debug > 0)
- X (void) printf("---> Current remote directory is \"%s\"\n", cwd);
- X return (result);
- X} /* _cd */
- X
- X
- X
- X
- X/*
- X * Set current working directory
- X * on local machine.
- X */
- Xint lcd(int argc, char **argv)
- X{
- X if (argc < 2)
- X argc++, argv[1] = home;
- X if (argc != 2) {
- X (void) printf("usage:%s local-directory\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (!globulize(&argv[1])) {
- X code = -1;
- X return;
- X }
- X if (chdir(argv[1]) < 0) {
- X Perror(argv[1]);
- X code = -1;
- X return;
- X }
- X (void) get_cwd(lcwd, (int) sizeof(lcwd));
- X if (IS_VVERBOSE)
- X (void) printf("Local directory now %s\n", lcwd);
- X code = 0;
- X} /* lcd */
- X
- X
- X
- X
- X/*
- X * Delete a single file.
- X */
- Xint do_delete(int argc, char **argv)
- X{
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote file to delete) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s remote-file\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (rem_glob_one(argv[1]) == 0) {
- X (void) sprintf(str, "DELE %s", argv[1]);
- X (void) command(str);
- X }
- X} /* do_delete */
- X
- X
- X
- X
- X/*
- X * Delete multiple files.
- X */
- Xint mdelete(int argc, char **argv)
- X{
- X char *cp;
- X void (*oldintr)(int);
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-files) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s remote-files\n", argv[0]);
- X code = -1;
- X return;
- X }
- X mname = argv[0];
- X activemcmd = 1;
- X oldintr = signal(SIGINT, mabort);
- X (void) setjmp(jabort);
- X while ((cp = remglob(argv)) != NULL) {
- X if (*cp == '\0') {
- X activemcmd = 0;
- X continue;
- X }
- X if (activemcmd && confirm(argv[0], cp)) {
- X (void) sprintf(str, "DELE %s", cp);
- X (void) command(str);
- X if (!activemcmd && fromatty) {
- X if (confirm("Continue with", "mdelete")) {
- X activemcmd++;
- X }
- X }
- X }
- X }
- X (void) signal(SIGINT, oldintr);
- X activemcmd = 0;
- X} /* mdelete */
- X
- X
- X
- X
- X/*
- X * Rename a remote file.
- X */
- Xint renamefile(int argc, char **argv)
- X{
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(from-name) ", &argc);
- X if (argc < 2) {
- Xusage:
- X (void) printf("%s from-name to-name\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (argc < 3)
- X argv = re_makeargv("(to-name) ", &argc);
- X if (argc < 3)
- X goto usage;
- X if (rem_glob_one(argv[1]) < 0)
- X return;
- X (void) sprintf(str, "RNFR %s", argv[1]);
- X if (command(str) == CONTINUE) {
- X (void) sprintf(str, "RNTO %s", argv[1]);
- X (void) command(str);
- X }
- X} /* renamefile */
- X
- X
- X
- X/*
- X * Get a directory listing
- X * of remote files.
- X */
- Xint ls(int argc, char **argv)
- X{
- X char *whichcmd, *remote, *local, *cp;
- X str32 lsflags;
- X string zpager;
- X int listmode, pagemode, defltFlags;
- X
- X#ifdef REDIR
- X register struct lslist *a, *b;
- X for (a = lshead; a != NULL; ) {
- X b = a->next;
- X if (a->string)
- X free(a->string); /* free string */
- X free(a); /* free node */
- X a = b;
- X }
- X lshead = lstail = NULL;
- X#endif
- X
- X pagemode = 0;
- X switch (**argv) {
- X case 'p': /* pls, pdir, pnlist */
- X pagemode = 1;
- X listmode = argv[0][1] == 'd';
- X break;
- X case 'd': /* dir */
- X listmode = 1;
- X break;
- X default: /* ls, nlist */
- X listmode = 0;
- X }
- X remote = NULL;
- X if (listmode) { /* dir */
- X whichcmd = "LIST";
- X } else { /* ls or nlist */
- X whichcmd = "NLST";
- X if (remote_is_unix) {
- X remote = "-CF";
- X defltFlags = 1;
- X } else {
- X defltFlags = 0;
- X }
- X }
- X
- X if (pagemode) {
- X size_t len = strlen(remote);
- X if (remote[len - 1] == 'Z' && remote[len - 2] == '.') {
- X /* run uncompress first, then pipe through pager. */
- X (void) Strncpy(zpager, "|uncompress ");
- X (void) Strncat(zpager, pager);
- X local = zpager;
- X } else
- X local = pager;
- X } else
- X local = "-";
- X
- X /* Possible scenarios:
- X 1. ls
- X 2. ls -flags
- X 3. ls directory
- X 4. ls -flags >outfile
- X 5. ls directory >outfile */
- X
- X if (argc > 1) {
- X remote = argv[1];
- X defltFlags = 0;
- X }
- X if (argc > 2)
- X local = argv[2];
- X if (argc > 3) {
- X (void) printf("usage: %s [remote-directory | flags] [local-file]\n", argv[0]);
- X code = -1;
- X return;
- X }
- X
- X /*
- X * If we are given an ls with some flags, make sure we use
- X * columnized output (-C) unless one column output (-1) is
- X * specified.
- X */
- X if (!listmode && !defltFlags && remote != NULL && *remote == '-') {
- X for (cp = remote + 1; *cp; cp++)
- X if (*cp == '1')
- X goto aa;
- X (void) sprintf(lsflags, "-CF%s", remote + 1);
- X remote = lsflags;
- X }
- Xaa: if (strcmp(local, "-") != 0 && !globulize(&local)) {
- X /* if #2 is not stdout, but there was a glob error, barf. */
- X code = -1;
- X return;
- X }
- X if (strcmp(local, "-") != 0 && *local != '|')
- X if (!globulize(&local) || !confirm("output to local-file:", local)) {
- X code = -1;
- X return;
- X }
- X#ifdef REDIR
- X is_ls=1; /* tells getreply() to buffer output on a lshead list */
- X#endif
- X recvrequest(whichcmd, local, remote, "w");
- X#ifdef REDIR
- X is_ls=0;
- X#endif
- X} /* ls */
- X
- X
- X
- X
- X/*
- X * Get a directory listing
- X * of multiple remote files.
- X */
- Xint mls(int argc, char **argv)
- X{
- X char *cmd, mode[1], *dest;
- X int i;
- X void (*oldintr)(int);
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-files) ", &argc);
- X if (argc < 3)
- X argv = re_makeargv("(local-file) ", &argc);
- X if (argc < 3) {
- X (void) printf("usage:%s remote-files local-file\n", argv[0]);
- X code = -1;
- X return;
- X }
- X dest = argv[argc - 1];
- X argv[argc - 1] = NULL;
- X if (strcmp(dest, "-") && *dest != '|')
- X if (!globulize(&dest) || !confirm("output to local-file:", dest)) {
- X code = -1;
- X return;
- X }
- X cmd = argv[0][1] != 'd' ? "NLST" : "LIST";
- X mname = argv[0];
- X activemcmd = 1;
- X oldintr = signal(SIGINT, mabort);
- X (void) setjmp(jabort);
- X for (i = 1; activemcmd && i < argc-1; ++i) {
- X *mode = (i == 1) ? 'w' : 'a';
- X recvrequest(cmd, dest, argv[i], mode);
- X if (!activemcmd && fromatty) {
- X if (confirm("Continue with", argv[0])) {
- X activemcmd++;
- X }
- X }
- X }
- X (void) signal(SIGINT, oldintr);
- X activemcmd = 0;
- X} /* mls */
- X
- X
- X
- X
- X/*
- X * Do a shell escape
- X */
- X/*ARGSUSED*/
- Xint shell(int argc, char **argv)
- X{
- X int pid;
- X void (*old1)(int), (*old2)(int);
- X char *theShell, *namep;
- X#ifndef U_WAIT
- X long Status;
- X#else
- X union wait Status;
- X#endif
- X string str;
- X
- X old1 = signal (SIGINT, SIG_IGN);
- X old2 = signal (SIGQUIT, SIG_IGN);
- X if ((pid = fork()) == 0) {
- X for (pid = 3; pid < 20; pid++)
- X (void) close(pid);
- X (void) signal(SIGINT, SIG_DFL);
- X (void) signal(SIGQUIT, SIG_DFL);
- X if ((theShell = getenv("SHELL")) == NULL)
- X theShell = uinfo.shell;
- X if (theShell == NULL)
- X theShell = "/bin/sh";
- X namep = rindex(theShell, '/');
- X if (namep == NULL)
- X namep = theShell;
- X (void) strcpy(str, "-");
- X (void) strcat(str, ++namep);
- X if (strcmp(namep, "sh") != 0)
- X str[0] = '+';
- X if (debug) {
- X (void) printf ("%s\n", theShell);
- X (void) fflush (stdout);
- X }
- X if (argc > 1)
- X (void) execl(theShell, str, "-c", altarg, (char *)0);
- X else
- X (void) execl(theShell, str, (char *)0);
- X Perror(theShell);
- X code = -1;
- X exit(1);
- X }
- X if (pid > 0)
- X while (wait((void *) &Status) != pid)
- X ;
- X (void) signal(SIGINT, old1);
- X (void) signal(SIGQUIT, old2);
- X if (pid == -1) {
- X Perror("Try again later");
- X code = -1;
- X } else code = 0;
- X return (0);
- X} /* shell */
- X
- X
- X
- X
- X/*
- X * Send new user information (re-login)
- X */
- Xint do_user(int argc, char **argv)
- X{
- X char acct[80];
- X int n, aflag = 0;
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(username) ", &argc);
- X if (argc > 4) {
- X (void) printf("usage: %s username [password] [account]\n", argv[0]);
- X code = -1;
- X return (0);
- X }
- X (void) sprintf(str, "USER %s", argv[1]);
- X n = command(str);
- X if (n == CONTINUE) {
- X if (argc < 3 )
- X argv[2] = getpass2("Password: "), argc++;
- X (void) sprintf(str, "PASS %s", argv[2]);
- X n = command(str);
- X }
- X if (n == CONTINUE) {
- X if (argc < 4) {
- X (void) printf("Account: "); (void) fflush(stdout);
- X (void) FGets(acct, stdin);
- X acct[strlen(acct) - 1] = '\0';
- X argv[3] = acct; argc++;
- X }
- X (void) sprintf(str, "ACCT %s", argv[3]);
- X n = command(str);
- X aflag++;
- X }
- X if (n != COMPLETE) {
- X (void) fprintf(stdout, "Login failed.\n");
- X return (0);
- X }
- X if (!aflag && argc == 4) {
- X (void) sprintf(str, "ACCT %s", argv[3]);
- X (void) command(str);
- X }
- X return (1);
- X} /* user */
- X
- X
- X
- X
- X/*
- X * Print working directory.
- X */
- X/*ARGSUSED*/
- Xint pwd(int argc, char **argv)
- X{
- X int tmpverbose = verbose;
- X verbose = V_VERBOSE;
- X (void) command("PWD");
- X verbose = tmpverbose;
- X} /* pwd */
- X
- X
- X
- X
- X/*
- X * Make a directory.
- X */
- Xint makedir(int argc, char **argv)
- X{
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(directory-name) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage: %s directory-name\n", argv[0]);
- X code = -1;
- X return;
- X }
- X (void) sprintf(str, "MKD %s", argv[1]);
- X (void) command(str);
- X} /* makedir */
- X
- X
- X
- X
- X/*
- X * Remove a directory.
- X */
- Xint removedir(int argc, char **argv)
- X{
- X string str;
- X if (argc < 2)
- X argv = re_makeargv("(directory-name) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage: %s directory-name\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (rem_glob_one(argv[1]) == 0) {
- X (void) sprintf(str, "RMD %s", argv[1]);
- X (void) command(str);
- X }
- X} /* removedir */
- X
- X
- X
- X
- X/*
- X * Send a line, verbatim, to the remote machine.
- X */
- Xint quote(int argc, char **argv)
- X{
- X int i;
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(command line to send) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage: %s line-to-send\n", argv[0]);
- X code = -1;
- X return;
- X }
- X (void) Strncpy(str, argv[1]);
- X for (i = 2; i < argc; i++) {
- X (void) Strncat(str, " ");
- X (void) Strncat(str, argv[i]);
- X }
- X if (command(str) == PRELIM) {
- X while (getreply(0) == PRELIM);
- X }
- X} /* quote */
- X
- X
- X
- X
- X/*
- X * Ask the other side for help.
- X */
- Xint rmthelp(int argc, char **argv)
- X{
- X int oldverbose = verbose;
- X string str;
- X
- X verbose = V_VERBOSE;
- X if (argc == 1) (void) command("HELP");
- X else {
- X (void) sprintf(str, "HELP %s", argv[1]);
- X (void) command(str);
- X }
- X verbose = oldverbose;
- X} /* rmthelp */
- X
- X
- X
- X
- X/*
- X * Terminate session and exit.
- X */
- X/*ARGSUSED*/
- Xint quit(int argc, char **argv)
- X{
- X close_up_shop();
- X trim_log();
- X exit(0);
- X} /* quit */
- X
- X
- X
- Xvoid close_streams(int wantShutDown)
- X{
- X if (cout != NULL) {
- X if (wantShutDown)
- X (void) shutdown(fileno(cout), 1+1);
- X (void) fclose(cout);
- X cout = NULL;
- X }
- X if (cin != NULL) {
- X if (wantShutDown)
- X (void) shutdown(fileno(cin), 1+1);
- X (void) fclose(cin);
- X cin = NULL;
- X }
- X} /* close_streams */
- X
- X
- X
- X
- X/*
- X * Terminate session, but don't exit.
- X */
- X/*ARGSUSED*/
- Xint disconnect(int argc, char **argv)
- X{
- X (void) command("QUIT");
- X close_streams(0);
- X hostname[0] = cwd[0] = 0;
- X connected = 0;
- X data = -1;
- X macnum = 0;
- X} /* disconnect */
- X
- X
- X
- X
- Xint confirm(char *cmd, char *file)
- X{
- X str32 str;
- X
- X if (!fromatty || (activemcmd && !mprompt))
- X return 1;
- X (void) printf("%s %s? ", cmd, file);
- X (void) fflush(stdout);
- X (void) gets(str);
- X return (*str != 'n' && *str != 'N');
- X} /* confirm */
- X
- X
- X
- Xvoid
- Xfatal(char *msg)
- X{
- X (void) fprintf(stderr, "%s: %s\n", progname, msg);
- X close_up_shop();
- X exit(1);
- X} /* fatal */
- X
- X
- X
- Xvoid
- Xclose_up_shop(void)
- X{
- X static int only_once = 0;
- X if (only_once++ > 0)
- X return;
- X if (connected)
- X disconnect(0, NULL);
- X if (logf != NULL) {
- X (void) fclose(logf);
- X logf = NULL;
- X }
- X} /* close_up_shop */
- X
- X
- X
- X
- X/*
- X * Glob a local file name specification with
- X * the expectation of a single return value.
- X * Can't control multiple values being expanded
- X * from the expression, we return only the first.
- X */
- Xint globulize(char **cpp)
- X{
- X char **globbed;
- X
- X globbed = glob(*cpp);
- X if (globerr != NULL) {
- X (void) printf("%s: %s\n", *cpp, globerr);
- X if (globbed) {
- X blkfree(globbed);
- X free(globbed);
- X }
- X return (0);
- X }
- X if (globbed) {
- X *cpp = *globbed++;
- X /* don't waste too much memory */
- X if (*globbed) {
- X blkfree(globbed);
- X free(globbed);
- X }
- X }
- X return (1);
- X} /* globulize */
- X
- X
- X
- X/* change directory to perent directory */
- X/*ARGSUSED*/
- Xint cdup(int argc, char **argv)
- X{
- X (void) _cd("CDUP");
- X}
- X
- X
- X/* show remote system type */
- X/*ARGSUSED*/
- Xint syst(int argc, char **argv)
- X{
- X (void) command("SYST");
- X}
- X
- X
- X
- X
- Xint make_macro(char *name, FILE *fp)
- X{
- X char *tmp;
- X char *cp;
- X string str;
- X size_t len;
- X
- X if (macnum == MAXMACROS) {
- X (void) fprintf(stderr, "Limit of %d macros have already been defined.\n", MAXMACROS);
- X return -1;
- X }
- X (void) strncpy(macros[macnum].mac_name, name, (size_t)8);
- X if (macnum == 0)
- X macros[macnum].mac_start = macbuf;
- X else
- X macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
- X tmp = macros[macnum].mac_start;
- X while (1) {
- X cp = fgets(str, sizeof(str) - 1, fp);
- X if (cp == NULL) {
- X /*
- X * If we had started a macro, we will say it is
- X * okay to skip the blank line delimiter if we
- X * are at the EOF.
- X */
- X if (tmp > macros[macnum].mac_start)
- X goto endmac;
- X (void) fprintf(stderr, "No text supplied for macro \"%s.\"\n", name);
- X }
- X /* see if we have a 'blank' line: just whitespace. */
- X while (*cp && isspace(*cp)) ++cp;
- X if (*cp == '\0') {
- X /* Blank line; end this macro. */
- Xendmac:
- X macros[macnum++].mac_end = tmp;
- X return 0;
- X }
- X len = strlen(cp) + 1; /* we need the \0 too. */
- X if (tmp + len >= macbuf + MACBUFLEN) {
- X (void) fprintf(stderr, "Macro \"%s\" not defined -- %d byte buffer exceeded.\n", name, MACBUFLEN);
- X return -1;
- X }
- X (void) strcpy(tmp, cp);
- X tmp += len;
- X }
- X} /* make_macro */
- X
- X
- X
- X
- Xint macdef(int argc, char **argv)
- X{
- X if (argc < 2)
- X argv = re_makeargv("(macro name) ", &argc);
- X if (argc != 2) {
- X (void) printf("Usage: %s macro_name\n", argv[0]);
- X code = -1;
- X return;
- X }
- X (void) printf("Enter macro line by line, terminating it with a blank line\n");
- X code = make_macro(argv[0], stdin);
- X} /* macdef */
- X
- X
- X
- X
- Xint domacro(int argc, char **argv)
- X{
- X register int i, j;
- X register char *cp1, *cp2;
- X int count = 2, loopflg = 0;
- X string str;
- X struct cmd *c;
- X
- X if (argc < 2) {
- X /* print macros. */
- X if (macnum == 0)
- X (void) printf("No macros defined.\n");
- X else
- X for (i = 0; i < macnum; ++i) {
- X (void) printf("%s:\n", macros[i].mac_name);
- X cp1 = macros[i].mac_start;
- X cp2 = macros[i].mac_end;
- X while (cp1 < cp2) {
- X (void) printf(" > ");
- X while (cp1 < cp2 && *cp1)
- X putchar(*cp1++);
- X ++cp1;
- X /* putchar('\n'); */
- X }
- X }
- X argv = re_makeargv("(macro to run) ", &argc);
- X }
- X if (argc < 2) {
- X (void) printf("Usage: %s macro_name.\n", argv[0]);
- X code = -1;
- X return;
- X }
- X for (i = 0; i < macnum; ++i) {
- X if (!strncmp(argv[1], macros[i].mac_name, (size_t) 9)) {
- X break;
- X }
- X }
- X if (i == macnum) {
- X (void) printf("'%s' macro not found.\n", argv[1]);
- X code = -1;
- X return;
- X }
- X (void) Strncpy(str, line);
- XTOP:
- X cp1 = macros[i].mac_start;
- X while (cp1 != macros[i].mac_end) {
- X while (isspace(*cp1)) {
- X cp1++;
- X }
- X cp2 = line;
- X while (*cp1 != '\0') {
- X switch(*cp1) {
- X case '\\':
- X *cp2++ = *++cp1;
- X break;
- X case '$':
- X if (isdigit(*(cp1+1))) {
- X j = 0;
- X while (isdigit(*++cp1)) {
- X j = 10*j + *cp1 - '0';
- X }
- X cp1--;
- X if (argc - 2 >= j) {
- X (void) strcpy(cp2, argv[j+1]);
- X cp2 += strlen(argv[j+1]);
- X }
- X break;
- X }
- X if (*(cp1+1) == 'i') {
- X loopflg = 1;
- X cp1++;
- X if (count < argc) {
- X (void) strcpy(cp2, argv[count]);
- X cp2 += strlen(argv[count]);
- X }
- X break;
- X }
- X /* intentional drop through */
- X default:
- X *cp2++ = *cp1;
- X break;
- X }
- X if (*cp1 != '\0') {
- X cp1++;
- X }
- X }
- X *cp2 = '\0';
- X makeargv();
- X c = getcmd(margv[0]);
- X if (c == (struct cmd *)-1) {
- X (void) printf("?Ambiguous command\n");
- X code = -1;
- X }
- X else if (c == 0) {
- X (void) printf("?Invalid command\n");
- X code = -1;
- X } else if (c->c_conn && !connected) {
- X (void) printf("Not connected.\n");
- X code = -1;
- X } else {
- X if (IS_VVERBOSE)
- X (void) printf("%s\n",line);
- X (*c->c_handler)(margc, margv);
- X (void) strcpy(line, str);
- X makeargv();
- X argc = margc;
- X argv = margv;
- X }
- X if (cp1 != macros[i].mac_end) {
- X cp1++;
- X }
- X }
- X if (loopflg && ++count < argc) {
- X goto TOP;
- X }
- X} /* domacro */
- X
- X
- X
- X/*
- X * get size of file on remote machine
- X */
- Xint sizecmd(int argc, char **argv)
- X{
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-file) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s filename\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (rem_glob_one(argv[1]) == 0) {
- X (void) sprintf(str, "SIZE %s", argv[1]);
- X (void) command(str);
- X }
- X} /* sizecmd */
- X
- X
- X
- X
- X/*
- X * get last modification time of file on remote machine
- X */
- Xint modtime(int argc, char **argv)
- X{
- X int overbose;
- X string str;
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-file) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s filename\n", argv[0]);
- X code = -1;
- X return;
- X }
- X if (rem_glob_one(argv[1]) == 0) {
- X overbose = verbose;
- X if (debug == 0)
- X verbose = V_QUIET;
- X (void) sprintf(str, "MDTM %s", argv[1]);
- X if (command(str) == COMPLETE) {
- X int yy, mo, day, hour, min, sec;
- X (void) sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
- X &day, &hour, &min, &sec);
- X /* might want to print this in local time */
- X (void) printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
- X mo, day, yy, hour, min, sec);
- X } else
- X (void) fputs(reply_string, stdout);
- X verbose = overbose;
- X }
- X} /* modtime */
- X
- X
- X
- Xint lookup(int argc, char **argv)
- X{
- X int i, j, by_name, result = 0;
- X unsigned long addr; /* address in host order */
- X struct hostent *host; /* structure returned by gethostbyaddr() */
- X extern int h_errno;
- X
- X if (argc < 2)
- X argv = re_makeargv("(sitename) ", &argc);
- X if (argc < 2) {
- X (void) printf("usages:\n\t%s <sitenames>\n\t%s <ip numbers>\n",
- X argv[0], argv[0]);
- X }
- X
- X lasthostname[0] = 0;
- X for (i=1; i<argc; i++) {
- X /* does the argument look like an address? */
- X if (4 == sscanf (argv[i], "%d.%d.%d.%d", &j, &j, &j, &j)) {
- X /* ip */
- X if ((addr = inet_addr (argv[i])) == 0xffffffff) {
- X (void) fprintf(stderr, "## could not convert \"%s\" into a valid IP address.\n", argv[i]);
- X continue;
- X }
- X host = gethostbyaddr ((char *) &addr, 4, AF_INET);
- X by_name = 0;
- X } else {
- X /* name */
- X host = gethostbyname (argv[i]);
- X by_name = 1;
- X }
- X if (host == NULL) {
- X if (NOT_VQUIET) {
- X /* gethostxxx error */
- X result = h_errno;
- X if (h_errno == HOST_NOT_FOUND) {
- X (void) printf("%s: lookup error (%d).\n",
- X argv[i], h_errno);
- X result = h_errno;
- X } else {
- X (void) printf("%s \"%s\"\n",
- X (by_name==0 ? "unknown address" : "unknown host"),
- X argv[i]);
- X result =
- X h_errno != 0 ? h_errno :
- X -1;
- X }
- X }
- X } else {
- X if (*host->h_name)
- X Strncpy(lasthostname, host->h_name);
- X if (NOT_VQUIET) {
- X (void) printf("%-32s ", *host->h_name ? host->h_name : "???");
- X if (*host->h_addr_list) {
- X unsigned long horder;
- X
- X horder = ntohl (*(unsigned long *) *(char **)host->h_addr_list);
- X (void) printf ("%lu.%lu.%lu.%lu\n",
- X (horder >> 24),
- X (horder >> 16) & 0xff,
- X (horder >> 8) & 0xff,
- X horder & 0xff);
- X }
- X else (void) printf("???\n");
- X }
- X }
- X } /* loop thru all sites */
- X return result;
- X} /* lookup */
- X
- X
- X
- X
- Xint getlocalhostname(char *host, size_t size)
- X{
- X int oldv, r;
- X char *argv[2];
- X
- X#ifdef HOSTNAME
- X (void) strncpy(host, HOSTNAME, size);
- X return 0;
- X#else
- X *host = 0;
- X if ((r = gethostname(host, size)) == 0) {
- X oldv = verbose;
- X verbose = V_QUIET;
- X argv[0] = "lookup";
- X (void) sprintf(line, "lookup %s", host);
- X (void) makeargv();
- X if (lookup(margc, margv) == 0 && lasthostname[0])
- X (void) strncpy(host, lasthostname, size);
- X verbose = oldv;
- X }
- X return r;
- X#endif
- X} /* getlocalhostname */
- X
- X
- X
- X
- X/*
- X * show status on remote machine
- X */
- Xint rmtstatus(int argc, char **argv)
- X{
- X string str;
- X if (argc > 1) {
- X (void) sprintf(str, "STAT %s" , argv[1]);
- X (void) command(str);
- X } else (void) command("STAT");
- X} /* rmtstatus */
- X
- X
- X
- X
- X/*
- X * create an empty file on remote machine.
- X */
- Xint create(int argc, char **argv)
- X{
- X string str;
- X FILE *ftemp;
- X
- X if (argc < 2)
- X argv = re_makeargv("(remote-file) ", &argc);
- X if (argc < 2) {
- X (void) printf("usage:%s filename\n", argv[0]);
- X code = -1;
- X return;
- X }
- X (void) tmp_name(str);
- X ftemp = fopen(str, "w");
- X /* (void) fputc('x', ftemp); */
- X (void) fclose(ftemp);
- X creating = 1;
- X sendrequest("STOR", str, argv[1]);
- X creating = 0;
- X (void) unlink(str);
- X} /* create */
- X
- X
- X/* Peter Jaspers-Fayer pjf@osiris.cs.uoguelph.ca Nov'92 */
- Xchar *getpass2(char *promptstr)
- X{
- X static char pass[80]; /* That should be enough! */
- X
- X struct termio t, s;
- X
- X (void) printf("%s", promptstr);
- X if (0 > ioctl(0, TCGETA, &t))
- X Perror("termio failed");
- X s.c_lflag = t.c_lflag; /* -- save */
- X
- X t.c_lflag &= ~ECHO; /* disable echo */
- X if (0 > ioctl(0, TCSETA, &t))
- X Perror("termio failed");
- X
- X (void) gets(pass);
- X
- X t.c_lflag = s.c_lflag; /* -- restore */
- X if (0 > ioctl(0, TCSETA, &t))
- X Perror("termio failed");
- X
- X (void) printf("\n"); /* Only because the original did */
- X return (pass);
- X} /* getpass2 */
- X
- X
- X/* show version info */
- X/*ARGSUSED*/
- Xint show_version(int argc, char **argv)
- X{
- X char *DStrs[20];
- X int nDStrs = 0, i, j;
- X
- X (void) printf("%s\n%-30s %s\n", version, "Author:",
- X "Mike Gleason, NCEMRSoft (mgleason@cse.unl.edu).");
- X
- X/* Now entering CPP hell... */
- X#ifdef __DATE__
- X (void) printf("%-30s %s\n", "Compile Date:", __DATE__);
- X#endif
- X (void) printf("%-30s %s (%s)\n", "Operating System:",
- X#ifdef System
- X System,
- X#else
- X# ifdef unix
- X "UNIX",
- X# else
- X "??",
- X# endif
- X#endif
- X#ifdef SYSV
- X "SYSV");
- X#else
- X# ifdef BSD
- X "BSD");
- X# else
- X "??");
- X# endif
- X#endif
- X
- X#ifdef RINDEX
- X DStrs[nDStrs++] = "RINDEX";
- X#endif
- X#ifdef HERROR
- X DStrs[nDStrs++] = "HERROR";
- X#endif
- X#ifdef U_WAIT
- X DStrs[nDStrs++] = "U_WAIT";
- X#endif
- X#ifdef const
- X DStrs[nDStrs++] = "const";
- X#endif
- X#ifdef HOSTNAME
- X DStrs[nDStrs++] = "HOSTNAME";
- X#endif
- X#ifdef SYSDIRH
- X DStrs[nDStrs++] = "SYSDIRH";
- X#endif
- X#ifdef SYSSELECTH
- X DStrs[nDStrs++] = "SYSSELECTH";
- X#endif
- X#ifdef REDIR
- X DStrs[nDStrs++] = "REDIR";
- X#endif
- X
- X (void) printf ("\nCompile Options:\n");
- X for (i=j=0; i<nDStrs; i++) {
- X if (j == 0)
- X (void) printf(" ");
- X (void) printf("%-15s", DStrs[i]);
- X if (++j == 4) {
- X j = 0;
- X (void) putchar('\n');
- X }
- X }
- X if (j != 0)
- X (void) putchar('\n');
- X
- X (void) printf("\nDefaults:\n");
- X (void) printf("\
- X Xfer Buf Size: %8d Debug: %d MPrompt: %d Verbosity: %d\n\
- X Prompt: %s Pager: %s ZCat: %s\n\
- X Logname: %s Logging: %d Type: %s Cmd Len: %d\n\
- X Recv Line Len: %d #Macros: %d Macbuf: %d Auto-Binary: %d\n\
- X Redial Delay: %d New Mail Message: \"%s\"\n",
- X MAX_XFER_BUFSIZE, dDEBUG, dMPROMPT, dVERBOSE,
- X dPROMPT, dPAGER, ZCAT,
- X dLOGNAME, dLOGGING, dTYPESTR, CMDLINELEN,
- X RECEIVEDLINELEN, MAXMACROS, MACBUFLEN, dAUTOBINARY,
- X dREDIALDELAY, NEWMAILMESSAGE
- X );
- X} /* show_version */
- X
- X
- X
- Xvoid Perror(char *s)
- X{
- X extern int errno;
- X
- X if (NOT_VQUIET) {
- X if (s != NULL)
- X (void) fprintf(stderr, "NcFTP: %s (%d): ", s, errno);
- X perror(NULL);
- X }
- X} /* Perror */
- X
- X
- X
- X#ifdef REDIR
- X/*ARGSUSED*/
- Xint showlsbuffer(int argc, char **argv)
- X{
- X register struct lslist *a = lshead;
- X int pagemode;
- X FILE *fp;
- X void (*oldintp)(int);
- X
- X if (a == NULL)
- X return;
- X pagemode= (**argv) == 'p' && pager[0] == '|';
- X if (pagemode) {
- X fp = popen(pager + 1, "w");
- X if (!fp) {
- X Perror(pager + 1);
- X return;
- X }
- X } else
- X fp = stdout;
- X oldintp = signal(SIGPIPE, SIG_IGN);
- X while (a) {
- X if (a->string)
- X (void) fprintf(fp, "%s\n", a->string);
- X a = a->next;
- X }
- X if (pagemode)
- X (void) pclose(fp);
- X if (oldintp)
- X signal(SIGPIPE, oldintp);
- X} /* showlsbuffer */
- X#endif
- X
- X/* eof cmds.c */
- END_OF_FILE
- if test 44217 -ne `wc -c <'cmds.c'`; then
- echo shar: \"'cmds.c'\" unpacked with wrong size!
- fi
- # end of 'cmds.c'
- fi
- if test -f 'ftpdefs.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ftpdefs.h'\"
- else
- echo shar: Extracting \"'ftpdefs.h'\" \(644 characters\)
- sed "s/^X//" >'ftpdefs.h' <<'END_OF_FILE'
- X/* ftpdefs.h */
- X
- X#ifndef _ftpdefs_h_
- X#define _ftpdefs_h_
- X
- X#define FTP_VERSION "NcFTP 1.0 (6 Dec 92)"
- X
- Xtypedef char string[128], str32[32];
- X
- Xstruct userinfo {
- X str32 username;
- X string homedir;
- X string shell;
- X string hostname;
- X int uid;
- X};
- X
- X/* Your compiler may not like the 'const' directives. If it chokes
- X * here, add -Dconst to your SDEFS line in the Makefile, or delete the word
- X * const here.
- X */
- X#define Strncpy(a,b) strncpy((a), (const char *) (b), (size_t) sizeof (a))
- X#define Strncat(a,b) strncat((a), (const char *) (b), (size_t) sizeof (a))
- X#define FGets(a,b) fgets((a), sizeof(a) - 1, (b))
- X
- X#endif /* _ftpdefs_h_ */
- X/* eof */
- END_OF_FILE
- if test 644 -ne `wc -c <'ftpdefs.h'`; then
- echo shar: \"'ftpdefs.h'\" unpacked with wrong size!
- fi
- # end of 'ftpdefs.h'
- fi
- if test -f 'sys.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sys.h'\"
- else
- echo shar: Extracting \"'sys.h'\" \(4116 characters\)
- sed "s/^X//" >'sys.h' <<'END_OF_FILE'
- X/* sys.h */
- X
- X/*
- X * ncftp may need work arounds for some things due to the differences
- X * in implementations of unix. The following systems are taken care
- X * of automatically:
- X *
- X * SunOS/Solaris (but use gcc)
- X * Silicon Graphics IRIX
- X * AIX
- X * SINIX
- X *
- X * For those systems, you should be able to 'make' ncftp without any
- X * problems. Otherwise you will have to configure ncftp manually.
- X * You will need to add these things to the SDEFS line in the Makefile
- X * as applicable.
- X *
- X * For these systems, some things are taken care of automatically, but
- X * you still need to add something to CFLAGS or SDEFS:
- X *
- X * Hewlett-Packard HP-UX: If you have 7.0, you'll need to find
- X * a copy of <ftp.h> from somewhere (8.0 has it though). Then
- X * set CFLAGS= -Aa. You may also need to use gcc if your
- X * compiler is non-ANSI.
- X *
- X * SCO Unix: Add -DSCO324 to SDEFS.
- X *
- X * Bull DPX/2: Add -DBULL to SDEFS, add -linet to MORELIBS, and
- X * use gcc.
- X *
- X * Is your system closer to System V or BSD? Your SDEFS line should have
- X * either -DBSD or -DSYSV. If you don't know, try leaving it blank first;
- X * some compilers automatically define it for you. So far, defining
- X * SYSV just defines a couple of macros for similar functions in BSD.
- X *
- X * You may need to add -DRINDEX if your system uses strrchr instead.
- X * If SYSV is defined, RINDEX is defined automatically because System V
- X * uses strrchr.
- X *
- X * Add -Dconst if your compiler chokes on the const directive.
- X *
- X * Add -DSYSSELECTH if you need <sys/select.h> included for definitions
- X * of fd_set, etc.
- X *
- X * (Optional) Add -DHERROR if you know you have the herror() system
- X * call.
- X *
- X * (Optional) Add -DU_WAIT if you know your wait system call takes
- X * a pointer to a 'union wait.' Defined automatically if you define
- X * BSD.
- X *
- X * (Optional) Add -DHOSTNAME=\"machine.domain.nam\" if your system
- X * doesn't generate it's own hostname. To check this, compile ncftp
- X * then run it and type 'set.' Look at the variable anon-password.
- X * If the hostname is wrong, recompile it with HOSTNAME set to your
- X * machine's address.
- X */
- X
- X#ifdef sun
- X# define System "SunOS"
- X# ifndef RINDEX
- X# define RINDEX 1
- X# endif
- X#endif /* sun */
- X
- X#ifdef sgi
- X# define System "IRIX"
- X# ifndef SYSV
- X# define SYSV 1
- X# endif
- X# ifndef HERROR
- X# define HERROR 1
- X# endif
- X# ifndef U_WAIT
- X# define U_WAIT 1
- X# endif
- X#endif /* sgi */
- X
- X#ifdef _AIX
- X# define System "AIX"
- X# define SYSSELECTH 1
- X#endif /* _AIX */
- X
- X#ifdef SCO324
- X# define System "SCO Unix"
- X# ifndef SYSV
- X# define SYSV 1
- X# endif
- X#endif /* SCO */
- X
- X#if defined(__hpux) || defined(HPUX)
- X# define System "HP-UX"
- X# ifndef _HPUX_SOURCE
- X# define _HPUX_SOURCE 1
- X# endif
- X# define SYSV 1
- X#endif /* HPUX */
- X
- X#ifdef SINIX
- X# define System "SINIX"
- X# ifndef SYSV
- X# define SYSV 1
- X# endif
- X/* You may need to add -lresolv, -lport, -lcurses to MORELIBS in Makefile. */
- X#endif
- X
- X#ifdef BULL /* added 23nov92 for Bull DPX/2 */
- X# define _POSIX_SOURCE
- X# define _XOPEN_SOURCE
- X# define _BULL_SOURCE
- X# ifndef SYSV
- X# define SYSV 1
- X# endif
- X# define bull
- X# define System "Bull DPX/2 BOS"
- X# include <sys/types.h>
- X# define SYSSELECTH
- X#endif /* BULL */ /* added 23nov92 for Bull DPX/2 */
- X
- X/* -------------------------------------------------------------------- */
- X
- X#ifdef _SYSV
- X# ifndef SYSV
- X# define SYSV 1
- X# endif
- X#endif
- X
- X#ifdef USG
- X# ifndef SYSV
- X# define SYSV 1
- X# endif
- X#endif
- X
- X#ifdef _BSD
- X# ifndef BSD
- X# define BSD 1
- X# endif
- X# ifndef SYSDIRH
- X# define SYSDIRH 1
- X# endif
- X#endif
- X
- X#ifdef SYSV
- X# ifndef RINDEX
- X# define RINDEX 1
- X# endif
- X# define unlink remove
- X# define bcopy(s,d,l) memcpy((d),(s),(l))
- X# define bzero(cp,l) memset((cp),0,(l))
- X#endif
- X
- X#ifdef BSD
- X# ifndef U_WAIT
- X# define U_WAIT 1 /* Use a 'union wait' parameter with wait(). */
- X# endif
- X#endif
- X
- X/*
- X * Some systems besides System V don't use rindex/index (like SunOS).
- X * Add -DRINDEX to your SDEFS line if you need to.
- X */
- X#ifdef RINDEX
- X /* or #include <strings.h> if you have it. */
- X# define rindex strrchr
- X# define index strchr
- X#endif /* RINDEX */
- X
- X/* Turn on the redir command. */
- X#ifndef REDIR
- X# define REDIR 1
- X#endif
- X
- X/* eof sys.h */
- END_OF_FILE
- if test 4116 -ne `wc -c <'sys.h'`; then
- echo shar: \"'sys.h'\" unpacked with wrong size!
- fi
- # end of 'sys.h'
- fi
- echo shar: End of archive 1 \(of 3\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-