1 /* $Id: cmds.c,v 1.13 1998/01/09 13:45:11 msmith Exp $ */
2 /* $NetBSD: cmds.c,v 1.30.2.1 1997/11/18 00:58:26 mellon Exp $ */
5 * Copyright (c) 1985, 1989, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/cdefs.h>
40 static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
42 __RCSID("$Id: cmds.c,v 1.13 1998/01/09 13:45:11 msmith Exp $");
43 __RCSID_SOURCE("$NetBSD: cmds.c,v 1.30.2.1 1997/11/18 00:58:26 mellon Exp $");
48 * FTP User Program -- Command Routines.
50 #include <sys/types.h>
51 #include <sys/socket.h>
66 #include "pathnames.h"
78 { "ascii", "A", TYPE_A, 0 },
79 { "binary", "I", TYPE_I, 0 },
80 { "image", "I", TYPE_I, 0 },
81 { "ebcdic", "E", TYPE_E, 0 },
82 { "tenex", "L", TYPE_L, bytename },
100 printf("usage: %s [", argv[0]);
102 for (p = types; p->t_name; p++) {
103 printf("%s%s", sep, p->t_name);
111 printf("Using %s mode to transfer files.\n", typename);
115 for (p = types; p->t_name; p++)
116 if (strcmp(argv[1], p->t_name) == 0)
118 if (p->t_name == 0) {
119 printf("%s: unknown mode.\n", argv[1]);
123 if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
124 comret = command("TYPE %s %s", p->t_mode, p->t_arg);
126 comret = command("TYPE %s", p->t_mode);
127 if (comret == COMPLETE) {
128 (void)strcpy(typename, p->t_name);
129 curtype = type = p->t_type;
134 * Internal form of settype; changes current type in use with server
135 * without changing our notion of the type for data transfers.
136 * Used to change to and from ascii for listings.
139 changetype(newtype, show)
143 int comret, oldverbose = verbose;
147 if (newtype == curtype)
149 if (debug == 0 && show == 0)
151 for (p = types; p->t_name; p++)
152 if (newtype == p->t_type)
154 if (p->t_name == 0) {
155 warnx("internal error: unknown type %d.", newtype);
158 if (newtype == TYPE_L && bytename[0] != '\0')
159 comret = command("TYPE %s %s", p->t_mode, bytename);
161 comret = command("TYPE %s", p->t_mode);
162 if (comret == COMPLETE)
164 verbose = oldverbose;
174 * Set binary transfer type.
178 setbinary(argc, argv)
188 * Set ascii transfer type.
202 * Set tenex transfer type.
216 * Set file transfer mode.
220 setftmode(argc, argv)
225 printf("We only support %s mode, sorry.\n", modename);
230 * Set file transfer format.
239 printf("We only support %s format, sorry.\n", formname);
244 * Set file transfer structure.
248 setstruct(argc, argv)
253 printf("We only support %s structure, sorry.\n", structname);
258 * Send a single file.
267 char *oldargv1, *oldargv2;
274 if (argc < 2 && !another(&argc, &argv, "local-file"))
276 if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
278 printf("usage: %s local-file [ remote-file ]\n", argv[0]);
284 if (!globulize(&argv[1])) {
289 * If "globulize" modifies argv[1], and argv[2] is a copy of
290 * the old argv[1], make it a copy of the new argv[1].
292 if (argv[1] != oldargv1 && argv[2] == oldargv1) {
295 cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
297 argv[2] = dotrans(argv[2]);
299 if (loc && mapflag) {
300 argv[2] = domap(argv[2]);
302 sendrequest(cmd, argv[1], argv[2],
303 argv[1] != oldargv1 || argv[2] != oldargv2);
304 if (oldargv1 != argv[1]) /* free up after globulize() */
309 * Send multiple files.
321 if (argc < 2 && !another(&argc, &argv, "local-files")) {
322 printf("usage: %s local-files\n", argv[0]);
328 oldintr = signal(SIGINT, mabort);
329 (void)setjmp(jabort);
331 char *cp, *tp2, tmpbuf[MAXPATHLEN];
333 while ((cp = remglob(argv, 0, NULL)) != NULL) {
338 if (mflag && confirm(argv[0], cp)) {
341 while (*tp && !islower((unsigned char)*tp)) {
347 while ((*tp2 = *tp) != '\0') {
348 if (isupper((unsigned char)*tp2))
349 *tp2 = tolower((unsigned char)*tp2);
362 sendrequest((sunique) ? "STOU" : "STOR",
363 cp, tp, cp != tp || !interactive);
364 if (!mflag && fromatty) {
365 ointer = interactive;
367 if (confirm("Continue with", "mput")) {
370 interactive = ointer;
374 (void)signal(SIGINT, oldintr);
378 for (i = 1; i < argc; i++) {
384 if (mflag && confirm(argv[0], argv[i])) {
385 tp = (ntflag) ? dotrans(argv[i]) : argv[i];
386 tp = (mapflag) ? domap(tp) : tp;
387 sendrequest((sunique) ? "STOU" : "STOR",
388 argv[i], tp, tp != argv[i] || !interactive);
389 if (!mflag && fromatty) {
390 ointer = interactive;
392 if (confirm("Continue with", "mput")) {
395 interactive = ointer;
401 memset(&gl, 0, sizeof(gl));
402 flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
403 if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
404 warnx("%s: not found", argv[i]);
408 for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
409 if (mflag && confirm(argv[0], *cpp)) {
410 tp = (ntflag) ? dotrans(*cpp) : *cpp;
411 tp = (mapflag) ? domap(tp) : tp;
412 sendrequest((sunique) ? "STOU" : "STOR",
413 *cpp, tp, *cpp != tp || !interactive);
414 if (!mflag && fromatty) {
415 ointer = interactive;
417 if (confirm("Continue with", "mput")) {
420 interactive = ointer;
426 (void)signal(SIGINT, oldintr);
436 (void)getit(argc, argv, 1, "r+w");
445 (void)getit(argc, argv, 0, restart_point ? "r+w" : "w" );
452 getit(argc, argv, restartit, mode)
460 char *oldargv1, *oldargv2, *globargv2;
467 if (argc < 2 && !another(&argc, &argv, "remote-file"))
469 if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
471 printf("usage: %s remote-file [ local-file ]\n", argv[0]);
477 if (!globulize(&argv[2])) {
483 char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
485 while (*tp && !islower((unsigned char)*tp)) {
491 while ((*tp2 = *tp) != '\0') {
492 if (isupper((unsigned char)*tp2)) {
493 *tp2 = tolower((unsigned char)*tp2);
502 argv[2] = dotrans(argv[2]);
504 argv[2] = domap(argv[2]);
509 ret = stat(argv[2], &stbuf);
510 if (restartit == 1) {
512 warn("local: %s", argv[2]);
515 restart_point = stbuf.st_size;
520 mtime = remotemodtime(argv[1], 0);
523 if (stbuf.st_mtime >= mtime) {
531 recvrequest("RETR", argv[2], argv[1], mode,
532 argv[1] != oldargv1 || argv[2] != oldargv2, loc);
535 if (oldargv2 != globargv2) /* free up after globulize() */
549 (void)fflush(stdout);
550 if (mflag && fromatty) {
551 ointer = interactive;
555 if (confirm("Continue with", mname)) {
556 interactive = ointer;
560 interactive = ointer;
568 * Get multiple files.
577 char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
579 if (argc < 2 && !another(&argc, &argv, "remote-files")) {
580 printf("usage: %s remote-files\n", argv[0]);
586 oldintr = signal(SIGINT, mabort);
587 (void)setjmp(jabort);
588 while ((cp = remglob(argv, proxy, NULL)) != NULL) {
593 if (mflag && confirm(argv[0], cp)) {
596 for (tp2 = tmpbuf; (ch = *tp++) != 0; )
597 *tp2++ = isupper((unsigned char)ch) ?
598 tolower((unsigned char)ch) :
609 recvrequest("RETR", tp, cp, "w",
610 tp != cp || !interactive, 1);
611 if (!mflag && fromatty) {
612 ointer = interactive;
614 if (confirm("Continue with", "mget")) {
617 interactive = ointer;
621 (void)signal(SIGINT, oldintr);
630 return (bool ? "on" : "off");
645 printf("Connected %sto %s.\n",
646 connected == -1 ? "and logged in" : "", hostname);
648 puts("Not connected.");
652 printf("Connected for proxy commands to %s.\n",
656 puts("No proxy connection.");
660 printf("Gate ftp: %s, server %s, port %d.\n", onoff(gatemode),
661 *gateserver ? gateserver : "(none)", ntohs(gateport));
662 printf("Passive mode: %s.\n", onoff(passivemode));
663 printf("Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
664 modename, typename, formname, structname);
665 printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
666 onoff(verbose), onoff(bell), onoff(interactive),
668 printf("Store unique: %s; Receive unique: %s.\n", onoff(sunique),
670 printf("Preserve modification times: %s.\n", onoff(preserve));
671 printf("Case: %s; CR stripping: %s.\n", onoff(mcase), onoff(crflag));
673 printf("Ntrans: (in) %s (out) %s\n", ntin, ntout);
676 puts("Ntrans: off.");
679 printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
684 printf("Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
685 onoff(hash), mark, onoff(progress));
686 printf("Use of PORT cmds: %s.\n", onoff(sendport));
688 printf("Command line editing: %s.\n", onoff(editing));
692 for (i=0; i<macnum; i++) {
693 printf("\t%s\n", macros[i].mac_name);
703 togglevar(argc, argv, var, mesg)
711 } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
713 } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
716 printf("usage: %s [ on | off ]\n", argv[0]);
720 printf("%s %s.\n", mesg, onoff(*var));
725 * Set beep on cmd completed mode.
734 code = togglevar(argc, argv, &bell, "Bell mode");
739 * Set command line editing
748 code = togglevar(argc, argv, &editing, "Editing mode");
754 * Turn on packet tracing.
763 code = togglevar(argc, argv, &trace, "Packet tracing");
767 * Toggle hash mark printing during transfers, or set hash mark bytecount.
777 else if (argc != 2) {
778 printf("usage: %s [ on | off | bytecount ]\n", argv[0]);
781 } else if (strcasecmp(argv[1], "on") == 0)
783 else if (strcasecmp(argv[1], "off") == 0)
789 nmark = strtol(argv[1], &ep, 10);
790 if (nmark < 1 || *ep != '\0') {
791 printf("mark: bad bytecount value `%s'.\n", argv[1]);
798 printf("Hash mark printing %s", onoff(hash));
800 printf(" (%d bytes/hash mark)", mark);
806 * Turn on printing of server echo's.
810 setverbose(argc, argv)
815 code = togglevar(argc, argv, &verbose, "Verbose mode");
819 * Toggle PORT cmd use before each data connection.
828 code = togglevar(argc, argv, &sendport, "Use of PORT cmds");
832 * Toggle transfer progress bar.
836 setprogress(argc, argv)
841 code = togglevar(argc, argv, &progress, "Progress bar");
845 * Turn on interactive prompting during mget, mput, and mdelete.
849 setprompt(argc, argv)
854 code = togglevar(argc, argv, &interactive, "Interactive mode");
858 * Toggle gate-ftp mode, or set gate-ftp server
866 static char gsbuf[MAXHOSTNAMELEN];
869 printf("usage: %s [ on | off | gateserver [ port ] ]\n",
873 } else if (argc < 2) {
874 gatemode = !gatemode;
876 if (argc == 2 && strcasecmp(argv[1], "on") == 0)
878 else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
885 port = strtol(argv[2], &ep, 10);
886 if (port < 0 || port > 0xffff || *ep != '\0') {
887 printf("%s: bad gateport value.\n",
892 gateport = htons(port);
894 strncpy(gsbuf, argv[1], sizeof(gsbuf) - 1);
895 gsbuf[sizeof(gsbuf) - 1] = '\0';
900 if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
902 "Disabling gate-ftp mode - no gate-ftp server defined.\n");
905 printf("Gate ftp: %s, server %s, port %d.\n", onoff(gatemode),
906 *gateserver ? gateserver : "(none)", ntohs(gateport));
912 * Toggle metacharacter interpretation on local file names.
921 code = togglevar(argc, argv, &doglob, "Globbing");
925 * Toggle preserving modification times on retreived files.
929 setpreserve(argc, argv)
934 code = togglevar(argc, argv, &preserve, "Preserve modification times");
938 * Set debugging mode on/off and/or set level of debugging.
947 printf("usage: %s [ on | off | debuglevel ]\n", argv[0]);
950 } else if (argc == 2) {
951 if (strcasecmp(argv[1], "on") == 0)
953 else if (strcasecmp(argv[1], "off") == 0)
959 val = strtol(argv[1], &ep, 10);
960 if (val < 0 || val > INT_MAX || *ep != '\0') {
961 printf("%s: bad debugging value.\n", argv[1]);
972 options &= ~SO_DEBUG;
973 printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
978 * Set current working directory on remote machine.
987 if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
989 printf("usage: %s remote-directory\n", argv[0]);
993 r = command("CWD %s", argv[1]);
994 if (r == ERROR && code == 500) {
996 puts("CWD command not recognized, trying XCWD.");
997 r = command("XCWD %s", argv[1]);
1004 * Set current working directory on local machine.
1011 char buf[MAXPATHLEN];
1015 argc++, argv[1] = home;
1017 printf("usage: %s local-directory\n", argv[0]);
1022 if (!globulize(&argv[1])) {
1026 if (chdir(argv[1]) < 0) {
1027 warn("local: %s", argv[1]);
1030 if (getcwd(buf, sizeof(buf)) != NULL)
1031 printf("Local directory now %s\n", buf);
1033 warn("getcwd: %s", argv[1]);
1036 if (oldargv1 != argv[1]) /* free up after globulize() */
1041 * Delete a single file.
1049 if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
1050 printf("usage: %s remote-file\n", argv[0]);
1054 (void)command("DELE %s", argv[1]);
1058 * Delete multiple files.
1069 if (argc < 2 && !another(&argc, &argv, "remote-files")) {
1070 printf("usage: %s remote-files\n", argv[0]);
1076 oldintr = signal(SIGINT, mabort);
1077 (void)setjmp(jabort);
1078 while ((cp = remglob(argv, 0, NULL)) != NULL) {
1083 if (mflag && confirm(argv[0], cp)) {
1084 (void)command("DELE %s", cp);
1085 if (!mflag && fromatty) {
1086 ointer = interactive;
1088 if (confirm("Continue with", "mdelete")) {
1091 interactive = ointer;
1095 (void)signal(SIGINT, oldintr);
1100 * Rename a remote file.
1103 renamefile(argc, argv)
1108 if (argc < 2 && !another(&argc, &argv, "from-name"))
1110 if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1112 printf("usage: %s from-name to-name\n", argv[0]);
1116 if (command("RNFR %s", argv[1]) == CONTINUE)
1117 (void)command("RNTO %s", argv[2]);
1121 * Get a directory listing of remote files.
1129 char *oldargv2, *globargv2;
1132 argc++, argv[1] = NULL;
1134 argc++, argv[2] = "-";
1136 printf("usage: %s remote-directory local-file\n", argv[0]);
1140 cmd = strcmp(argv[0], "nlist") == 0 ? "NLST" : "LIST";
1142 if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
1146 globargv2 = argv[2];
1147 if (strcmp(argv[2], "-") && *argv[2] != '|')
1148 if (!globulize(&argv[2]) || !confirm("output to local-file:",
1153 recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
1155 /* flush results in case commands are coming from a pipe */
1158 if (argv[2] != globargv2) /* free up after globulize() */
1160 if (globargv2 != oldargv2)
1165 * Get a directory listing of multiple remote files.
1175 char mode[1], *dest, *odest;
1177 if (argc < 2 && !another(&argc, &argv, "remote-files"))
1179 if (argc < 3 && !another(&argc, &argv, "local-file")) {
1181 printf("usage: %s remote-files local-file\n", argv[0]);
1185 odest = dest = argv[argc - 1];
1186 argv[argc - 1] = NULL;
1187 if (strcmp(dest, "-") && *dest != '|')
1188 if (!globulize(&dest) ||
1189 !confirm("output to local-file:", dest)) {
1193 dolist = strcmp(argv[0], "mls");
1196 oldintr = signal(SIGINT, mabort);
1197 (void)setjmp(jabort);
1198 for (i = 1; mflag && i < argc-1; ++i) {
1199 *mode = (i == 1) ? 'w' : 'a';
1200 recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], mode,
1202 if (!mflag && fromatty) {
1203 ointer = interactive;
1205 if (confirm("Continue with", argv[0])) {
1208 interactive = ointer;
1211 (void)signal(SIGINT, oldintr);
1213 if (dest != odest) /* free up after globulize() */
1228 char shellnam[MAXPATHLEN], *shell, *namep;
1231 old1 = signal (SIGINT, SIG_IGN);
1232 old2 = signal (SIGQUIT, SIG_IGN);
1233 if ((pid = fork()) == 0) {
1234 for (pid = 3; pid < 20; pid++)
1236 (void)signal(SIGINT, SIG_DFL);
1237 (void)signal(SIGQUIT, SIG_DFL);
1238 shell = getenv("SHELL");
1240 shell = _PATH_BSHELL;
1241 namep = strrchr(shell, '/');
1245 (void)strncpy(shellnam + 1, ++namep, sizeof(shellnam) - 2);
1246 shellnam[sizeof(shellnam) - 1] = '\0';
1247 if (strcmp(namep, "sh") != 0)
1251 (void)fflush(stdout);
1254 execl(shell, shellnam, "-c", altarg, (char *)0);
1257 execl(shell, shellnam, (char *)0);
1264 while (wait(&wait_status) != pid)
1266 (void)signal(SIGINT, old1);
1267 (void)signal(SIGQUIT, old2);
1269 warn("Try again later");
1278 * Send new user information (re-login)
1289 (void)another(&argc, &argv, "username");
1290 if (argc < 2 || argc > 4) {
1291 printf("usage: %s username [password] [account]\n", argv[0]);
1295 n = command("USER %s", argv[1]);
1296 if (n == CONTINUE) {
1298 argv[2] = getpass("Password: "), argc++;
1299 n = command("PASS %s", argv[2]);
1301 if (n == CONTINUE) {
1303 (void)fputs("Account: ", stdout);
1304 (void)fflush(stdout);
1305 (void)fgets(acct, sizeof(acct) - 1, stdin);
1306 acct[strlen(acct) - 1] = '\0';
1307 argv[3] = acct; argc++;
1309 n = command("ACCT %s", argv[3]);
1312 if (n != COMPLETE) {
1313 puts("Login failed.");
1316 if (!aflag && argc == 4) {
1317 (void)command("ACCT %s", argv[3]);
1323 * Print working directory on remote machine.
1331 int oldverbose = verbose;
1334 * If we aren't verbose, this doesn't do anything!
1337 if (command("PWD") == ERROR && code == 500) {
1338 puts("PWD command not recognized, trying XPWD.");
1339 (void)command("XPWD");
1341 verbose = oldverbose;
1345 * Print working directory on local machine.
1352 char buf[MAXPATHLEN];
1354 if (getcwd(buf, sizeof(buf)) != NULL)
1355 printf("Local directory %s\n", buf);
1370 if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1372 printf("usage: %s directory-name\n", argv[0]);
1376 if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1378 puts("MKD command not recognized, trying XMKD.");
1379 (void)command("XMKD %s", argv[1]);
1384 * Remove a directory.
1387 removedir(argc, argv)
1392 if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1394 printf("usage: %s directory-name\n", argv[0]);
1398 if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1400 puts("RMD command not recognized, trying XRMD.");
1401 (void)command("XRMD %s", argv[1]);
1406 * Send a line, verbatim, to the remote machine.
1414 if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1415 printf("usage: %s line-to-send\n", argv[0]);
1419 quote1("", argc, argv);
1423 * Send a SITE command to the remote machine. The line
1424 * is sent verbatim to the remote machine, except that the
1425 * word "SITE" is added at the front.
1433 if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1434 printf("usage: %s line-to-send\n", argv[0]);
1438 quote1("SITE ", argc, argv);
1442 * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1443 * Send the result as a one-line command and get response.
1446 quote1(initial, argc, argv)
1447 const char *initial;
1452 char buf[BUFSIZ]; /* must be >= sizeof(line) */
1454 len = snprintf(buf, sizeof(buf), "%s", initial);
1455 if (len >= 0 && len < sizeof(buf)) {
1456 for (i = 1; i < argc; i++) {
1457 len1 = snprintf(&buf[len], sizeof(buf) - len,
1458 i == 1 ? "%s" : " %s", argv[i]);
1459 if (len1 < 0 || len1 > sizeof(buf) - len)
1464 if (command(buf) == PRELIM) {
1465 while (getreply(0) == PRELIM)
1471 do_chmod(argc, argv)
1476 if (argc < 2 && !another(&argc, &argv, "mode"))
1478 if ((argc < 3 && !another(&argc, &argv, "file-name")) || argc > 3) {
1480 printf("usage: %s mode file-name\n", argv[0]);
1484 (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1488 do_umask(argc, argv)
1492 int oldverbose = verbose;
1495 (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1496 verbose = oldverbose;
1504 int oldverbose = verbose;
1507 (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1508 verbose = oldverbose;
1512 * Ask the other side for help.
1519 int oldverbose = verbose;
1522 (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1523 verbose = oldverbose;
1527 * Terminate session and exit.
1546 * Terminate session, but don't exit.
1549 disconnect(argc, argv)
1556 (void)command("QUIT");
1576 printf("usage: %s [password]\n", argv[0]);
1583 ap = getpass("Account:");
1584 (void)command("ACCT %s", ap);
1605 longjmp(abortprox, 1);
1617 if (argc < 2 && !another(&argc, &argv, "command")) {
1618 printf("usage: %s command\n", argv[0]);
1622 c = getcmd(argv[1]);
1623 if (c == (struct cmd *) -1) {
1624 puts("?Ambiguous command.");
1625 (void)fflush(stdout);
1630 puts("?Invalid command.");
1631 (void)fflush(stdout);
1636 puts("?Invalid proxy command.");
1637 (void)fflush(stdout);
1641 if (setjmp(abortprox)) {
1645 oldintr = signal(SIGINT, proxabort);
1647 if (c->c_conn && !connected) {
1648 puts("Not connected.");
1649 (void)fflush(stdout);
1651 (void)signal(SIGINT, oldintr);
1655 cmdpos = strcspn(line, " \t");
1656 if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1657 memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1658 (*c->c_handler)(argc-1, argv+1);
1666 (void)signal(SIGINT, oldintr);
1675 code = togglevar(argc, argv, &mcase, "Case mapping");
1684 code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1688 setntrans(argc, argv)
1694 puts("Ntrans off.");
1700 (void)strncpy(ntin, argv[1], sizeof(ntin) - 1);
1701 ntin[sizeof(ntin) - 1] = '\0';
1706 (void)strncpy(ntout, argv[2], sizeof(ntout) - 1);
1707 ntout[sizeof(ntout) - 1] = '\0';
1714 static char new[MAXPATHLEN];
1715 char *cp1, *cp2 = new;
1716 int i, ostop, found;
1718 for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
1720 for (cp1 = name; *cp1; cp1++) {
1722 for (i = 0; *(ntin + i) && i < 16; i++) {
1723 if (*cp1 == *(ntin + i)) {
1726 *cp2++ = *(ntout + i);
1752 if ((argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) {
1753 printf("usage: %s [mapin mapout]\n", argv[0]);
1759 cp = strchr(altarg, ' ');
1764 cp = strchr(altarg, ' ');
1767 (void)strncpy(mapin, altarg, MAXPATHLEN - 1);
1768 while (*++cp == ' ')
1770 (void)strncpy(mapout, cp, MAXPATHLEN - 1);
1777 static char new[MAXPATHLEN];
1778 char *cp1 = name, *cp2 = mapin;
1779 char *tp[9], *te[9];
1780 int i, toks[9], toknum = 0, match = 1;
1782 for (i=0; i < 9; ++i) {
1785 while (match && *cp1 && *cp2) {
1788 if (*++cp2 != *cp1) {
1793 if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
1794 if (*cp1 != *(++cp2+1)) {
1795 toks[toknum = *cp2 - '1']++;
1797 while (*++cp1 && *(cp2+1)
1811 if (match && *cp1) {
1814 if (match && *cp2) {
1818 if (!match && *cp1) /* last token mismatch */
1835 if (*++cp2 == '$' &&
1836 isdigit((unsigned char)*(cp2+1))) {
1837 if (*++cp2 == '0') {
1845 else if (toks[toknum = *cp2 - '1']) {
1846 char *cp3 = tp[toknum];
1848 while (cp3 != te[toknum]) {
1855 while (*cp2 && *cp2 != ',' &&
1860 else if (*cp2 == '$' &&
1861 isdigit((unsigned char)*(cp2+1))) {
1862 if (*++cp2 == '0') {
1869 else if (toks[toknum =
1871 char *cp3=tp[toknum];
1885 "nmap: unbalanced brackets.");
1892 while (*++cp2 && *cp2 != ']') {
1893 if (*cp2 == '\\' && *(cp2 + 1)) {
1899 "nmap: unbalanced brackets.");
1915 if (isdigit((unsigned char)*(cp2 + 1))) {
1916 if (*++cp2 == '0') {
1923 else if (toks[toknum = *cp2 - '1']) {
1924 char *cp3 = tp[toknum];
1926 while (cp3 != te[toknum]) {
1932 /* intentional drop through */
1947 setpassive(argc, argv)
1952 code = togglevar(argc, argv, &passivemode,
1953 verbose ? "Passive mode" : NULL);
1957 setsunique(argc, argv)
1962 code = togglevar(argc, argv, &sunique, "Store unique");
1966 setrunique(argc, argv)
1971 code = togglevar(argc, argv, &runique, "Receive unique");
1974 /* change directory to parent directory */
1982 r = command("CDUP");
1983 if (r == ERROR && code == 500) {
1985 puts("CDUP command not recognized, trying XCUP.");
1986 r = command("XCUP");
1993 * Restart transfer at specific point
2002 printf("usage: %s [restart_point]\n", argv[0]);
2010 rp = strtoq(argv[1], &ep, 10);
2011 if (rp < 0 || *ep != '\0')
2012 printf("restart: Invalid offset `%s'\n", argv[1]);
2016 if (restart_point == 0)
2017 puts("No restart point defined");
2019 printf("Restarting at %qd for next get, put or append\n",
2020 (long long)restart_point);
2024 * Show remote system type
2032 (void)command("SYST");
2044 puts("Limit of 16 macros have already been defined.");
2048 if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) {
2049 printf("usage: %s macro_name\n", argv[0]);
2055 "Enter macro line by line, terminating it with a null line.");
2056 (void)strncpy(macros[macnum].mac_name, argv[1],
2057 sizeof(macros[macnum].mac_name) - 1);
2058 macros[macnum].mac_name[sizeof(macros[macnum].mac_name) - 1] = '\0';
2060 macros[macnum].mac_start = macbuf;
2062 macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
2063 tmp = macros[macnum].mac_start;
2064 while (tmp != macbuf+4096) {
2065 if ((c = getchar()) == EOF) {
2066 puts("macdef: end of file encountered.");
2070 if ((*tmp = c) == '\n') {
2071 if (tmp == macros[macnum].mac_start) {
2072 macros[macnum++].mac_end = tmp;
2076 if (*(tmp-1) == '\0') {
2077 macros[macnum++].mac_end = tmp - 1;
2086 while ((c = getchar()) != '\n' && c != EOF)
2088 if (c == EOF || getchar() == '\n') {
2089 puts("Macro not defined - 4K buffer exceeded.");
2097 * Restrict FTP data port range to a high group of "safe" ports
2100 setrestrict(argc, argv)
2104 code = togglevar(argc, argv, &restricted_data_ports,
2105 verbose ? "Restricted data ports" : NULL);
2109 * Get size of file on remote machine
2118 if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
2119 printf("usage: %s filename\n", argv[0]);
2123 size = remotesize(argv[1], 1);
2125 printf("%s\t%qd\n", argv[1], (long long)size);
2130 * Get last modification time of file on remote machine
2139 if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
2140 printf("usage: %s filename\n", argv[0]);
2144 mtime = remotemodtime(argv[1], 1);
2146 printf("%s\t%s", argv[1], asctime(localtime(&mtime)));
2151 * Show status on remote machine
2154 rmtstatus(argc, argv)
2159 (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
2163 * Get file if modtime is more recent than current file
2171 if (getit(argc, argv, -1, "w"))
2172 printf("Local file \"%s\" is newer than remote file \"%s\".\n",
2177 * Display one file through $PAGER (defaults to "more").
2184 int ohash, overbose;
2185 char *p, *pager, *oldargv1;
2187 if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
2188 printf("usage: %s filename\n", argv[0]);
2193 if (!globulize(&argv[1])) {
2197 p = getenv("PAGER");
2200 if ((pager = malloc(strlen(p) + 2)) == NULL)
2201 errx(1, "Can't allocate memory for $PAGER");
2202 (void)sprintf(pager, "|%s", p);
2207 recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
2211 if (oldargv1 != argv[1]) /* free up after globulize() */