Annotation of src/usr.bin/ftp/cmds.c, Revision 1.71
1.71 ! bluhm 1: /* $OpenBSD: cmds.c,v 1.70 2009/05/05 19:35:30 martynas Exp $ */
1.23 millert 2: /* $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $ */
1.1 deraadt 3:
4: /*
1.32 itojun 5: * Copyright (C) 1997 and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
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. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
1.1 deraadt 34: * Copyright (c) 1985, 1989, 1993, 1994
35: * The Regents of the University of California. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
1.45 millert 45: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: */
61:
1.70 martynas 62: #ifndef SMALL
63:
1.1 deraadt 64: /*
65: * FTP User Program -- Command Routines.
66: */
1.13 millert 67: #include <sys/types.h>
68: #include <sys/socket.h>
69: #include <sys/stat.h>
1.1 deraadt 70: #include <sys/wait.h>
71: #include <arpa/ftp.h>
72:
73: #include <ctype.h>
74: #include <err.h>
1.63 martynas 75: #include <fnmatch.h>
1.1 deraadt 76: #include <glob.h>
77: #include <netdb.h>
78: #include <stdio.h>
79: #include <stdlib.h>
80: #include <string.h>
81: #include <unistd.h>
82:
83: #include "ftp_var.h"
84: #include "pathnames.h"
1.70 martynas 85: #include "cmds.h"
1.1 deraadt 86:
87: /*
88: * Set ascii transfer type.
89: */
1.48 deraadt 90: /*ARGSUSED*/
1.1 deraadt 91: void
1.47 deraadt 92: setascii(int argc, char *argv[])
1.1 deraadt 93: {
94:
95: stype[1] = "ascii";
96: settype(2, stype);
97: }
98:
99: /*
100: * Set tenex transfer type.
101: */
1.48 deraadt 102: /*ARGSUSED*/
1.1 deraadt 103: void
1.47 deraadt 104: settenex(int argc, char *argv[])
1.1 deraadt 105: {
106:
107: stype[1] = "tenex";
108: settype(2, stype);
109: }
110:
111: /*
112: * Set file transfer mode.
113: */
114: /*ARGSUSED*/
115: void
1.47 deraadt 116: setftmode(int argc, char *argv[])
1.1 deraadt 117: {
118:
1.20 deraadt 119: fprintf(ttyout, "We only support %s mode, sorry.\n", modename);
1.1 deraadt 120: code = -1;
121: }
122:
123: /*
124: * Set file transfer format.
125: */
126: /*ARGSUSED*/
127: void
1.47 deraadt 128: setform(int argc, char *argv[])
1.1 deraadt 129: {
130:
1.20 deraadt 131: fprintf(ttyout, "We only support %s format, sorry.\n", formname);
1.1 deraadt 132: code = -1;
133: }
134:
135: /*
136: * Set file transfer structure.
137: */
138: /*ARGSUSED*/
139: void
1.47 deraadt 140: setstruct(int argc, char *argv[])
1.1 deraadt 141: {
142:
1.20 deraadt 143: fprintf(ttyout, "We only support %s structure, sorry.\n", structname);
1.1 deraadt 144: code = -1;
145: }
146:
1.62 martynas 147: void
148: reput(int argc, char *argv[])
149: {
150:
151: (void)putit(argc, argv, 1);
152: }
153:
154: void
155: put(int argc, char *argv[])
156: {
157:
158: (void)putit(argc, argv, 0);
159: }
160:
1.1 deraadt 161: /*
162: * Send a single file.
163: */
164: void
1.62 martynas 165: putit(int argc, char *argv[], int restartit)
1.1 deraadt 166: {
167: char *cmd;
168: int loc = 0;
169: char *oldargv1, *oldargv2;
170:
171: if (argc == 2) {
172: argc++;
173: argv[2] = argv[1];
174: loc++;
175: }
176: if (argc < 2 && !another(&argc, &argv, "local-file"))
177: goto usage;
1.13 millert 178: if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
1.1 deraadt 179: usage:
1.64 sobrado 180: fprintf(ttyout, "usage: %s local-file [remote-file]\n",
181: argv[0]);
1.1 deraadt 182: code = -1;
183: return;
184: }
185: oldargv1 = argv[1];
186: oldargv2 = argv[2];
187: if (!globulize(&argv[1])) {
188: code = -1;
189: return;
190: }
191: /*
192: * If "globulize" modifies argv[1], and argv[2] is a copy of
193: * the old argv[1], make it a copy of the new argv[1].
194: */
195: if (argv[1] != oldargv1 && argv[2] == oldargv1) {
196: argv[2] = argv[1];
197: }
1.62 martynas 198: if (restartit == 1) {
199: if (curtype != type)
200: changetype(type, 0);
201: restart_point = remotesize(argv[2], 1);
202: if (restart_point < 0) {
203: restart_point = 0;
204: code = -1;
205: return;
206: }
207: }
208: if (strcmp(argv[0], "append") == 0) {
209: restartit = 1;
210: }
211: cmd = restartit ? "APPE" : ((sunique) ? "STOU" : "STOR");
1.1 deraadt 212: if (loc && ntflag) {
213: argv[2] = dotrans(argv[2]);
214: }
215: if (loc && mapflag) {
216: argv[2] = domap(argv[2]);
217: }
218: sendrequest(cmd, argv[1], argv[2],
219: argv[1] != oldargv1 || argv[2] != oldargv2);
1.62 martynas 220: restart_point = 0;
1.23 millert 221: if (oldargv1 != argv[1]) /* free up after globulize() */
222: free(argv[1]);
1.1 deraadt 223: }
224:
225: /*
226: * Send multiple files.
227: */
228: void
1.47 deraadt 229: mput(int argc, char *argv[])
1.1 deraadt 230: {
1.62 martynas 231: extern int optind, optreset;
232: int ch, i, restartit = 0;
1.1 deraadt 233: sig_t oldintr;
1.71 ! bluhm 234: char *cmd, *tp, *xargv[] = { argv[0], NULL, NULL };
! 235: const char *errstr;
! 236: static int depth = 0, max_depth = 0;
1.62 martynas 237:
238: optind = optreset = 1;
1.1 deraadt 239:
1.71 ! bluhm 240: if (depth)
! 241: depth++;
! 242:
! 243: while ((ch = getopt(argc, argv, "cd:r")) != -1) {
1.62 martynas 244: switch(ch) {
245: case 'c':
246: restartit = 1;
247: break;
1.71 ! bluhm 248: case 'd':
! 249: max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
! 250: if (errstr != NULL) {
! 251: fprintf(ttyout, "bad depth value, %s: %s\n",
! 252: errstr, optarg);
! 253: code = -1;
! 254: return;
! 255: }
! 256: break;
! 257: case 'r':
! 258: depth = 1;
! 259: break;
1.62 martynas 260: default:
261: goto usage;
262: }
263: }
264:
265: if (argc - optind < 1 && !another(&argc, &argv, "local-files")) {
266: usage:
1.71 ! bluhm 267: fprintf(ttyout, "usage: %s [-cr] [-d depth] local-files\n",
! 268: argv[0]);
1.1 deraadt 269: code = -1;
270: return;
271: }
1.62 martynas 272:
1.63 martynas 273: argv[optind - 1] = argv[0];
274: argc -= optind - 1;
275: argv += optind - 1;
1.62 martynas 276:
1.1 deraadt 277: mname = argv[0];
278: mflag = 1;
1.62 martynas 279:
1.1 deraadt 280: oldintr = signal(SIGINT, mabort);
1.14 millert 281: (void)setjmp(jabort);
1.1 deraadt 282: if (proxy) {
283: char *cp, *tp2, tmpbuf[MAXPATHLEN];
284:
1.16 millert 285: while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.13 millert 286: if (*cp == '\0') {
1.1 deraadt 287: mflag = 0;
288: continue;
289: }
1.63 martynas 290: if (mflag && confirm(argv[0], cp)) {
1.1 deraadt 291: tp = cp;
292: if (mcase) {
293: while (*tp && !islower(*tp)) {
294: tp++;
295: }
296: if (!*tp) {
297: tp = cp;
298: tp2 = tmpbuf;
1.21 millert 299: while ((*tp2 = *tp) != '\0') {
1.1 deraadt 300: if (isupper(*tp2)) {
1.23 millert 301: *tp2 =
302: tolower(*tp2);
1.1 deraadt 303: }
304: tp++;
305: tp2++;
306: }
307: }
308: tp = tmpbuf;
309: }
310: if (ntflag) {
311: tp = dotrans(tp);
312: }
313: if (mapflag) {
314: tp = domap(tp);
315: }
1.62 martynas 316: if (restartit == 1) {
317: off_t ret;
318:
319: if (curtype != type)
320: changetype(type, 0);
321: ret = remotesize(tp, 0);
322: restart_point = (ret < 0) ? 0 : ret;
323: }
324: cmd = restartit ? "APPE" : ((sunique) ?
325: "STOU" : "STOR");
326: sendrequest(cmd, cp, tp,
327: cp != tp || !interactive);
328: restart_point = 0;
1.1 deraadt 329: if (!mflag && fromatty) {
1.63 martynas 330: if (confirm(argv[0], NULL))
1.61 martynas 331: mflag = 1;
1.1 deraadt 332: }
333: }
334: }
1.14 millert 335: (void)signal(SIGINT, oldintr);
1.1 deraadt 336: mflag = 0;
337: return;
338: }
1.71 ! bluhm 339:
1.1 deraadt 340: for (i = 1; i < argc; i++) {
1.13 millert 341: char **cpp;
1.1 deraadt 342: glob_t gl;
343: int flags;
344:
1.71 ! bluhm 345: /* Copy files without word expansion */
1.1 deraadt 346: if (!doglob) {
1.63 martynas 347: if (mflag && confirm(argv[0], argv[i])) {
1.1 deraadt 348: tp = (ntflag) ? dotrans(argv[i]) : argv[i];
349: tp = (mapflag) ? domap(tp) : tp;
1.62 martynas 350: if (restartit == 1) {
351: off_t ret;
352:
353: if (curtype != type)
354: changetype(type, 0);
355: ret = remotesize(tp, 0);
356: restart_point = (ret < 0) ? 0 : ret;
357: }
358: cmd = restartit ? "APPE" : ((sunique) ?
359: "STOU" : "STOR");
360: sendrequest(cmd, argv[i], tp,
361: tp != argv[i] || !interactive);
362: restart_point = 0;
1.1 deraadt 363: if (!mflag && fromatty) {
1.63 martynas 364: if (confirm(argv[0], NULL))
1.61 martynas 365: mflag = 1;
1.1 deraadt 366: }
367: }
368: continue;
369: }
370:
1.71 ! bluhm 371: /* expanding file names */
1.1 deraadt 372: memset(&gl, 0, sizeof(gl));
373: flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
374: if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
375: warnx("%s: not found", argv[i]);
376: globfree(&gl);
377: continue;
378: }
1.71 ! bluhm 379:
! 380: /* traverse all expanded file names */
1.1 deraadt 381: for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
1.71 ! bluhm 382: struct stat filestat;
! 383:
! 384: if (!mflag)
! 385: continue;
! 386: if (stat(*cpp, &filestat) != 0) {
! 387: warn("local: %s", *cpp);
! 388: continue;
! 389: }
! 390: if (S_ISDIR(filestat.st_mode) && depth == max_depth)
! 391: continue;
! 392: if (!confirm(argv[0], *cpp))
! 393: continue;
! 394:
! 395: /*
! 396: * If file is a directory then create a new one
! 397: * at the remote machine.
! 398: */
! 399: if (S_ISDIR(filestat.st_mode)) {
! 400: xargv[1] = *cpp;
! 401: makedir(2, xargv);
! 402: cd(2, xargv);
! 403: if (dirchange != 1) {
! 404: warnx("remote: %s", *cpp);
! 405: continue;
! 406: }
! 407:
! 408: if (chdir(*cpp) != 0) {
! 409: warn("local: %s", *cpp);
! 410: goto out;
! 411: }
1.62 martynas 412:
1.71 ! bluhm 413: /* Copy the whole directory recursively. */
! 414: xargv[1] = "*";
! 415: mput(2, xargv);
! 416:
! 417: if (chdir("..") != 0) {
! 418: mflag = 0;
! 419: warn("local: %s", *cpp);
! 420: goto out;
1.62 martynas 421: }
1.71 ! bluhm 422:
! 423: out:
! 424: xargv[1] = "..";
! 425: cd(2, xargv);
! 426: if (dirchange != 1) {
! 427: warnx("remote: %s", *cpp);
! 428: mflag = 0;
1.1 deraadt 429: }
1.71 ! bluhm 430: continue;
! 431: }
! 432:
! 433: tp = (ntflag) ? dotrans(*cpp) : *cpp;
! 434: tp = (mapflag) ? domap(tp) : tp;
! 435: if (restartit == 1) {
! 436: off_t ret;
! 437:
! 438: if (curtype != type)
! 439: changetype(type, 0);
! 440: ret = remotesize(tp, 0);
! 441: restart_point = (ret < 0) ? 0 : ret;
! 442: }
! 443: cmd = restartit ? "APPE" : ((sunique) ?
! 444: "STOU" : "STOR");
! 445: sendrequest(cmd, *cpp, tp,
! 446: *cpp != tp || !interactive);
! 447: restart_point = 0;
! 448: if (!mflag && fromatty) {
! 449: if (confirm(argv[0], NULL))
! 450: mflag = 1;
1.1 deraadt 451: }
452: }
453: globfree(&gl);
454: }
1.71 ! bluhm 455:
1.14 millert 456: (void)signal(SIGINT, oldintr);
1.71 ! bluhm 457:
! 458: if (depth)
! 459: depth--;
! 460: if (depth == 0 || mflag == 0)
! 461: depth = max_depth = mflag = 0;
1.1 deraadt 462: }
463:
464: void
1.47 deraadt 465: reget(int argc, char *argv[])
1.1 deraadt 466: {
467:
1.67 martynas 468: (void)getit(argc, argv, 1, "a+w");
1.1 deraadt 469: }
470:
471: char *
1.47 deraadt 472: onoff(int bool)
1.1 deraadt 473: {
474:
475: return (bool ? "on" : "off");
476: }
477:
478: /*
479: * Show status.
480: */
481: /*ARGSUSED*/
482: void
1.47 deraadt 483: status(int argc, char *argv[])
1.1 deraadt 484: {
485: int i;
486:
487: if (connected)
1.20 deraadt 488: fprintf(ttyout, "Connected %sto %s.\n",
1.19 millert 489: connected == -1 ? "and logged in" : "", hostname);
1.1 deraadt 490: else
1.20 deraadt 491: fputs("Not connected.\n", ttyout);
1.1 deraadt 492: if (!proxy) {
493: pswitch(1);
494: if (connected) {
1.20 deraadt 495: fprintf(ttyout, "Connected for proxy commands to %s.\n",
1.13 millert 496: hostname);
1.1 deraadt 497: }
498: else {
1.20 deraadt 499: fputs("No proxy connection.\n", ttyout);
1.1 deraadt 500: }
501: pswitch(0);
502: }
1.32 itojun 503: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode),
504: *gateserver ? gateserver : "(none)", gateport);
1.20 deraadt 505: fprintf(ttyout, "Passive mode: %s.\n", onoff(passivemode));
506: fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
1.1 deraadt 507: modename, typename, formname, structname);
1.20 deraadt 508: fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
1.1 deraadt 509: onoff(verbose), onoff(bell), onoff(interactive),
510: onoff(doglob));
1.20 deraadt 511: fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n", onoff(sunique),
1.1 deraadt 512: onoff(runique));
1.20 deraadt 513: fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve));
514: fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase), onoff(crflag));
1.1 deraadt 515: if (ntflag) {
1.20 deraadt 516: fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout);
1.1 deraadt 517: }
518: else {
1.20 deraadt 519: fputs("Ntrans: off.\n", ttyout);
1.1 deraadt 520: }
521: if (mapflag) {
1.20 deraadt 522: fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout);
1.1 deraadt 523: }
524: else {
1.20 deraadt 525: fputs("Nmap: off.\n", ttyout);
1.1 deraadt 526: }
1.20 deraadt 527: fprintf(ttyout, "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
1.13 millert 528: onoff(hash), mark, onoff(progress));
1.32 itojun 529: fprintf(ttyout, "Use of PORT/LPRT cmds: %s.\n", onoff(sendport));
1.34 itojun 530: fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
531: epsv4bad ? " (disabled for this connection)" : "");
1.20 deraadt 532: fprintf(ttyout, "Command line editing: %s.\n", onoff(editing));
1.1 deraadt 533: if (macnum > 0) {
1.27 millert 534: fputs("Macros:\n", ttyout);
1.1 deraadt 535: for (i=0; i<macnum; i++) {
1.20 deraadt 536: fprintf(ttyout, "\t%s\n", macros[i].mac_name);
1.1 deraadt 537: }
538: }
539: code = 0;
540: }
541:
542: /*
1.13 millert 543: * Toggle a variable
544: */
545: int
1.47 deraadt 546: togglevar(int argc, char *argv[], int *var, const char *mesg)
1.13 millert 547: {
548: if (argc < 2) {
549: *var = !*var;
550: } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
551: *var = 1;
552: } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
553: *var = 0;
554: } else {
1.64 sobrado 555: fprintf(ttyout, "usage: %s [on | off]\n", argv[0]);
1.16 millert 556: return (-1);
1.13 millert 557: }
1.15 millert 558: if (mesg)
1.20 deraadt 559: fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
1.14 millert 560: return (*var);
1.13 millert 561: }
562:
563: /*
1.1 deraadt 564: * Set beep on cmd completed mode.
565: */
1.48 deraadt 566: /*ARGSUSED*/
1.1 deraadt 567: void
1.47 deraadt 568: setbell(int argc, char *argv[])
1.1 deraadt 569: {
570:
1.13 millert 571: code = togglevar(argc, argv, &bell, "Bell mode");
1.1 deraadt 572: }
573:
574: /*
1.13 millert 575: * Set command line editing
1.1 deraadt 576: */
1.48 deraadt 577: /*ARGSUSED*/
1.1 deraadt 578: void
1.47 deraadt 579: setedit(int argc, char *argv[])
1.1 deraadt 580: {
581:
1.13 millert 582: code = togglevar(argc, argv, &editing, "Editing mode");
1.18 millert 583: controlediting();
1.1 deraadt 584: }
1.34 itojun 585:
586: /*
587: * Toggle use of IPv4 EPSV/EPRT
588: */
1.48 deraadt 589: /*ARGSUSED*/
1.34 itojun 590: void
1.47 deraadt 591: setepsv4(int argc, char *argv[])
1.34 itojun 592: {
593:
594: code = togglevar(argc, argv, &epsv4, "EPSV/EPRT on IPv4");
595: epsv4bad = 0;
596: }
1.1 deraadt 597:
598: /*
1.13 millert 599: * Turn on packet tracing.
1.1 deraadt 600: */
1.48 deraadt 601: /*ARGSUSED*/
1.1 deraadt 602: void
1.47 deraadt 603: settrace(int argc, char *argv[])
1.1 deraadt 604: {
605:
1.13 millert 606: code = togglevar(argc, argv, &trace, "Packet tracing");
1.1 deraadt 607: }
1.6 kstailey 608:
609: /*
1.13 millert 610: * Toggle hash mark printing during transfers, or set hash mark bytecount.
1.6 kstailey 611: */
1.48 deraadt 612: /*ARGSUSED*/
1.6 kstailey 613: void
1.47 deraadt 614: sethash(int argc, char *argv[])
1.6 kstailey 615: {
616: if (argc == 1)
1.13 millert 617: hash = !hash;
1.6 kstailey 618: else if (argc != 2) {
1.64 sobrado 619: fprintf(ttyout, "usage: %s [on | off | size]\n", argv[0]);
1.13 millert 620: code = -1;
621: return;
622: } else if (strcasecmp(argv[1], "on") == 0)
623: hash = 1;
624: else if (strcasecmp(argv[1], "off") == 0)
625: hash = 0;
626: else {
1.50 tedu 627: int nmark;
628: const char *errstr;
1.28 millert 629:
1.50 tedu 630: nmark = strtonum(argv[1], 1, INT_MAX, &errstr);
631: if (errstr) {
632: fprintf(ttyout, "bytecount value is %s: %s\n",
633: errstr, argv[1]);
1.13 millert 634: code = -1;
635: return;
1.6 kstailey 636: }
1.13 millert 637: mark = nmark;
638: hash = 1;
1.6 kstailey 639: }
1.20 deraadt 640: fprintf(ttyout, "Hash mark printing %s", onoff(hash));
1.13 millert 641: if (hash)
1.20 deraadt 642: fprintf(ttyout, " (%d bytes/hash mark)", mark);
643: fputs(".\n", ttyout);
1.13 millert 644: code = hash;
1.6 kstailey 645: }
646:
1.1 deraadt 647: /*
648: * Turn on printing of server echo's.
649: */
1.48 deraadt 650: /*ARGSUSED*/
1.1 deraadt 651: void
1.47 deraadt 652: setverbose(int argc, char *argv[])
1.1 deraadt 653: {
654:
1.13 millert 655: code = togglevar(argc, argv, &verbose, "Verbose mode");
1.1 deraadt 656: }
657:
658: /*
1.32 itojun 659: * Toggle PORT/LPRT cmd use before each data connection.
1.1 deraadt 660: */
1.48 deraadt 661: /*ARGSUSED*/
1.1 deraadt 662: void
1.47 deraadt 663: setport(int argc, char *argv[])
1.1 deraadt 664: {
665:
1.32 itojun 666: code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
1.13 millert 667: }
668:
669: /*
670: * Toggle transfer progress bar.
671: */
1.48 deraadt 672: /*ARGSUSED*/
1.13 millert 673: void
1.47 deraadt 674: setprogress(int argc, char *argv[])
1.13 millert 675: {
676:
677: code = togglevar(argc, argv, &progress, "Progress bar");
1.1 deraadt 678: }
679:
680: /*
1.23 millert 681: * Turn on interactive prompting during mget, mput, and mdelete.
1.1 deraadt 682: */
1.48 deraadt 683: /*ARGSUSED*/
1.1 deraadt 684: void
1.47 deraadt 685: setprompt(int argc, char *argv[])
1.1 deraadt 686: {
687:
1.13 millert 688: code = togglevar(argc, argv, &interactive, "Interactive mode");
1.1 deraadt 689: }
690:
691: /*
1.23 millert 692: * Toggle gate-ftp mode, or set gate-ftp server
693: */
1.48 deraadt 694: /*ARGSUSED*/
1.23 millert 695: void
1.47 deraadt 696: setgate(int argc, char *argv[])
1.23 millert 697: {
698: static char gsbuf[MAXHOSTNAMELEN];
699:
700: if (argc > 3) {
1.64 sobrado 701: fprintf(ttyout, "usage: %s [on | off | host [port]]\n",
1.23 millert 702: argv[0]);
703: code = -1;
704: return;
705: } else if (argc < 2) {
706: gatemode = !gatemode;
707: } else {
708: if (argc == 2 && strcasecmp(argv[1], "on") == 0)
709: gatemode = 1;
710: else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
711: gatemode = 0;
712: else {
713: if (argc == 3) {
1.32 itojun 714: gateport = strdup(argv[2]);
1.41 deraadt 715: if (gateport == NULL)
716: err(1, NULL);
1.23 millert 717: }
1.36 lebel 718: strlcpy(gsbuf, argv[1], sizeof(gsbuf));
1.23 millert 719: gateserver = gsbuf;
720: gatemode = 1;
721: }
722: }
723: if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
724: fprintf(ttyout,
725: "Disabling gate-ftp mode - no gate-ftp server defined.\n");
726: gatemode = 0;
727: } else {
1.32 itojun 728: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
1.23 millert 729: onoff(gatemode),
1.32 itojun 730: *gateserver ? gateserver : "(none)", gateport);
1.23 millert 731: }
732: code = gatemode;
733: }
734:
735: /*
736: * Toggle metacharacter interpretation on local file names.
1.1 deraadt 737: */
1.48 deraadt 738: /*ARGSUSED*/
1.1 deraadt 739: void
1.47 deraadt 740: setglob(int argc, char *argv[])
1.1 deraadt 741: {
1.13 millert 742:
743: code = togglevar(argc, argv, &doglob, "Globbing");
744: }
745:
746: /*
1.31 aaron 747: * Toggle preserving modification times on retrieved files.
1.13 millert 748: */
1.48 deraadt 749: /*ARGSUSED*/
1.13 millert 750: void
1.47 deraadt 751: setpreserve(int argc, char *argv[])
1.13 millert 752: {
753:
754: code = togglevar(argc, argv, &preserve, "Preserve modification times");
1.1 deraadt 755: }
756:
757: /*
1.23 millert 758: * Set debugging mode on/off and/or set level of debugging.
1.1 deraadt 759: */
1.48 deraadt 760: /*ARGSUSED*/
1.1 deraadt 761: void
1.47 deraadt 762: setdebug(int argc, char *argv[])
1.1 deraadt 763: {
1.13 millert 764: if (argc > 2) {
1.64 sobrado 765: fprintf(ttyout, "usage: %s [on | off | debuglevel]\n", argv[0]);
1.13 millert 766: code = -1;
767: return;
768: } else if (argc == 2) {
769: if (strcasecmp(argv[1], "on") == 0)
770: debug = 1;
771: else if (strcasecmp(argv[1], "off") == 0)
772: debug = 0;
773: else {
1.50 tedu 774: const char *errstr;
775: int val;
1.21 millert 776:
1.50 tedu 777: val = strtonum(argv[1], 0, INT_MAX, &errstr);
778: if (errstr) {
779: fprintf(ttyout, "debugging value is %s: %s\n",
780: errstr, argv[1]);
1.13 millert 781: code = -1;
782: return;
783: }
1.50 tedu 784: debug = val;
1.1 deraadt 785: }
786: } else
1.13 millert 787: debug = !debug;
1.1 deraadt 788: if (debug)
789: options |= SO_DEBUG;
790: else
791: options &= ~SO_DEBUG;
1.20 deraadt 792: fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
1.1 deraadt 793: code = debug > 0;
794: }
795:
796: /*
1.23 millert 797: * Set current working directory on local machine.
1.1 deraadt 798: */
799: void
1.47 deraadt 800: lcd(int argc, char *argv[])
1.1 deraadt 801: {
802: char buf[MAXPATHLEN];
1.23 millert 803: char *oldargv1;
1.1 deraadt 804:
805: if (argc < 2)
806: argc++, argv[1] = home;
807: if (argc != 2) {
1.64 sobrado 808: fprintf(ttyout, "usage: %s [local-directory]\n", argv[0]);
1.1 deraadt 809: code = -1;
810: return;
811: }
1.23 millert 812: oldargv1 = argv[1];
1.1 deraadt 813: if (!globulize(&argv[1])) {
814: code = -1;
815: return;
816: }
817: if (chdir(argv[1]) < 0) {
818: warn("local: %s", argv[1]);
819: code = -1;
1.23 millert 820: } else {
821: if (getcwd(buf, sizeof(buf)) != NULL)
822: fprintf(ttyout, "Local directory now %s\n", buf);
823: else
824: warn("getcwd: %s", argv[1]);
825: code = 0;
1.1 deraadt 826: }
1.23 millert 827: if (oldargv1 != argv[1]) /* free up after globulize() */
828: free(argv[1]);
1.1 deraadt 829: }
830:
831: /*
832: * Delete a single file.
833: */
834: void
1.48 deraadt 835: deletecmd(int argc, char *argv[])
1.1 deraadt 836: {
837:
1.13 millert 838: if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
1.20 deraadt 839: fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.1 deraadt 840: code = -1;
841: return;
842: }
1.14 millert 843: (void)command("DELE %s", argv[1]);
1.1 deraadt 844: }
845:
846: /*
847: * Delete multiple files.
848: */
849: void
1.47 deraadt 850: mdelete(int argc, char *argv[])
1.1 deraadt 851: {
852: sig_t oldintr;
853: char *cp;
854:
855: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
1.20 deraadt 856: fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
1.1 deraadt 857: code = -1;
858: return;
859: }
860: mname = argv[0];
861: mflag = 1;
862: oldintr = signal(SIGINT, mabort);
1.14 millert 863: (void)setjmp(jabort);
1.16 millert 864: while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.1 deraadt 865: if (*cp == '\0') {
866: mflag = 0;
867: continue;
868: }
1.63 martynas 869: if (mflag && confirm(argv[0], cp)) {
1.14 millert 870: (void)command("DELE %s", cp);
1.1 deraadt 871: if (!mflag && fromatty) {
1.63 martynas 872: if (confirm(argv[0], NULL))
1.61 martynas 873: mflag = 1;
1.1 deraadt 874: }
875: }
876: }
1.14 millert 877: (void)signal(SIGINT, oldintr);
1.1 deraadt 878: mflag = 0;
879: }
880:
881: /*
882: * Rename a remote file.
883: */
884: void
1.47 deraadt 885: renamefile(int argc, char *argv[])
1.1 deraadt 886: {
887:
888: if (argc < 2 && !another(&argc, &argv, "from-name"))
889: goto usage;
1.13 millert 890: if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1.1 deraadt 891: usage:
1.20 deraadt 892: fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]);
1.1 deraadt 893: code = -1;
894: return;
895: }
896: if (command("RNFR %s", argv[1]) == CONTINUE)
1.14 millert 897: (void)command("RNTO %s", argv[2]);
1.1 deraadt 898: }
899:
900: /*
1.23 millert 901: * Get a directory listing of remote files.
1.1 deraadt 902: */
903: void
1.47 deraadt 904: ls(int argc, char *argv[])
1.1 deraadt 905: {
1.13 millert 906: const char *cmd;
1.23 millert 907: char *oldargv2, *globargv2;
1.1 deraadt 908:
909: if (argc < 2)
910: argc++, argv[1] = NULL;
911: if (argc < 3)
912: argc++, argv[2] = "-";
913: if (argc > 3) {
1.64 sobrado 914: fprintf(ttyout, "usage: %s [remote-directory [local-file]]\n",
915: argv[0]);
1.1 deraadt 916: code = -1;
917: return;
918: }
1.33 millert 919: cmd = strcmp(argv[0], "nlist") == 0 ? "NLST" : "LIST";
1.23 millert 920: oldargv2 = argv[2];
1.1 deraadt 921: if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
922: code = -1;
923: return;
924: }
1.23 millert 925: globargv2 = argv[2];
926: if (strcmp(argv[2], "-") && *argv[2] != '|' && (!globulize(&argv[2]) ||
1.63 martynas 927: !confirm("output to local-file:", argv[2]))) {
1.23 millert 928: code = -1;
929: goto freels;
1.1 deraadt 930: }
1.23 millert 931: recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
1.3 downsj 932:
933: /* flush results in case commands are coming from a pipe */
1.20 deraadt 934: fflush(ttyout);
1.23 millert 935: freels:
936: if (argv[2] != globargv2) /* free up after globulize() */
937: free(argv[2]);
938: if (globargv2 != oldargv2)
939: free(globargv2);
1.1 deraadt 940: }
941:
942: /*
1.23 millert 943: * Get a directory listing of multiple remote files.
1.1 deraadt 944: */
945: void
1.47 deraadt 946: mls(int argc, char *argv[])
1.1 deraadt 947: {
948: sig_t oldintr;
1.60 martynas 949: int i;
1.51 ray 950: char lmode[1], *dest, *odest;
1.1 deraadt 951:
952: if (argc < 2 && !another(&argc, &argv, "remote-files"))
953: goto usage;
954: if (argc < 3 && !another(&argc, &argv, "local-file")) {
955: usage:
1.20 deraadt 956: fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]);
1.1 deraadt 957: code = -1;
958: return;
959: }
1.23 millert 960: odest = dest = argv[argc - 1];
1.1 deraadt 961: argv[argc - 1] = NULL;
962: if (strcmp(dest, "-") && *dest != '|')
963: if (!globulize(&dest) ||
1.63 martynas 964: !confirm("output to local-file:", dest)) {
1.1 deraadt 965: code = -1;
966: return;
967: }
968: mname = argv[0];
969: mflag = 1;
970: oldintr = signal(SIGINT, mabort);
1.14 millert 971: (void)setjmp(jabort);
1.1 deraadt 972: for (i = 1; mflag && i < argc-1; ++i) {
1.51 ray 973: *lmode = (i == 1) ? 'w' : 'a';
974: recvrequest("LIST", dest, argv[i], lmode, 0, 0);
1.1 deraadt 975: if (!mflag && fromatty) {
1.63 martynas 976: if (confirm(argv[0], NULL))
1.1 deraadt 977: mflag ++;
978: }
979: }
1.14 millert 980: (void)signal(SIGINT, oldintr);
1.1 deraadt 981: mflag = 0;
1.23 millert 982: if (dest != odest) /* free up after globulize() */
983: free(dest);
1.1 deraadt 984: }
985:
986: /*
987: * Do a shell escape
988: */
989: /*ARGSUSED*/
990: void
1.47 deraadt 991: shell(int argc, char *argv[])
1.1 deraadt 992: {
993: pid_t pid;
994: sig_t old1, old2;
1.51 ray 995: char shellnam[MAXPATHLEN], *shellp, *namep;
1.24 millert 996: int wait_status;
1.1 deraadt 997:
998: old1 = signal (SIGINT, SIG_IGN);
999: old2 = signal (SIGQUIT, SIG_IGN);
1000: if ((pid = fork()) == 0) {
1001: for (pid = 3; pid < 20; pid++)
1.14 millert 1002: (void)close(pid);
1003: (void)signal(SIGINT, SIG_DFL);
1004: (void)signal(SIGQUIT, SIG_DFL);
1.51 ray 1005: shellp = getenv("SHELL");
1006: if (shellp == NULL || *shellp == '\0')
1007: shellp = _PATH_BSHELL;
1008: namep = strrchr(shellp, '/');
1.1 deraadt 1009: if (namep == NULL)
1.51 ray 1010: namep = shellp;
1.13 millert 1011: shellnam[0] = '-';
1.36 lebel 1012: (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
1.1 deraadt 1013: if (strcmp(namep, "sh") != 0)
1014: shellnam[0] = '+';
1015: if (debug) {
1.51 ray 1016: fputs(shellp, ttyout);
1.21 millert 1017: fputc('\n', ttyout);
1.20 deraadt 1018: (void)fflush(ttyout);
1.1 deraadt 1019: }
1020: if (argc > 1) {
1.51 ray 1021: execl(shellp, shellnam, "-c", altarg, (char *)0);
1.1 deraadt 1022: }
1023: else {
1.51 ray 1024: execl(shellp, shellnam, (char *)0);
1.1 deraadt 1025: }
1.51 ray 1026: warn("%s", shellp);
1.1 deraadt 1027: code = -1;
1028: exit(1);
1029: }
1030: if (pid > 0)
1.24 millert 1031: while (wait(&wait_status) != pid)
1.1 deraadt 1032: ;
1.14 millert 1033: (void)signal(SIGINT, old1);
1034: (void)signal(SIGQUIT, old2);
1.1 deraadt 1035: if (pid == -1) {
1.16 millert 1036: warn("Try again later");
1.1 deraadt 1037: code = -1;
1038: }
1039: else {
1040: code = 0;
1041: }
1042: }
1043:
1044: /*
1045: * Send new user information (re-login)
1046: */
1047: void
1.47 deraadt 1048: user(int argc, char *argv[])
1.1 deraadt 1049: {
1.51 ray 1050: char acctname[80];
1.1 deraadt 1051: int n, aflag = 0;
1052:
1053: if (argc < 2)
1.14 millert 1054: (void)another(&argc, &argv, "username");
1.1 deraadt 1055: if (argc < 2 || argc > 4) {
1.64 sobrado 1056: fprintf(ttyout, "usage: %s username [password [account]]\n",
1057: argv[0]);
1.1 deraadt 1058: code = -1;
1059: return;
1060: }
1061: n = command("USER %s", argv[1]);
1062: if (n == CONTINUE) {
1063: if (argc < 3 )
1.56 millert 1064: argv[2] = getpass("Password:"), argc++;
1.1 deraadt 1065: n = command("PASS %s", argv[2]);
1066: }
1067: if (n == CONTINUE) {
1068: if (argc < 4) {
1.20 deraadt 1069: (void)fputs("Account: ", ttyout);
1070: (void)fflush(ttyout);
1.59 martynas 1071: if (fgets(acctname, sizeof(acctname), stdin) == NULL) {
1072: clearerr(stdin);
1.53 ray 1073: goto fail;
1.59 martynas 1074: }
1.57 gilles 1075:
1076: acctname[strcspn(acctname, "\n")] = '\0';
1077:
1.51 ray 1078: argv[3] = acctname;
1079: argc++;
1.1 deraadt 1080: }
1081: n = command("ACCT %s", argv[3]);
1082: aflag++;
1083: }
1084: if (n != COMPLETE) {
1.53 ray 1085: fail:
1.20 deraadt 1086: fputs("Login failed.\n", ttyout);
1.1 deraadt 1087: return;
1088: }
1089: if (!aflag && argc == 4) {
1.14 millert 1090: (void)command("ACCT %s", argv[3]);
1.1 deraadt 1091: }
1.19 millert 1092: connected = -1;
1.1 deraadt 1093: }
1094:
1095: /*
1.13 millert 1096: * Print working directory on remote machine.
1.1 deraadt 1097: */
1.48 deraadt 1098: /*ARGSUSED*/
1.1 deraadt 1099: void
1.47 deraadt 1100: pwd(int argc, char *argv[])
1.1 deraadt 1101: {
1102: int oldverbose = verbose;
1103:
1104: /*
1105: * If we aren't verbose, this doesn't do anything!
1106: */
1107: verbose = 1;
1108: if (command("PWD") == ERROR && code == 500) {
1.20 deraadt 1109: fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1.14 millert 1110: (void)command("XPWD");
1.1 deraadt 1111: }
1112: verbose = oldverbose;
1113: }
1114:
1115: /*
1.13 millert 1116: * Print working directory on local machine.
1117: */
1.48 deraadt 1118: /* ARGSUSED */
1.13 millert 1119: void
1.47 deraadt 1120: lpwd(int argc, char *argv[])
1.13 millert 1121: {
1122: char buf[MAXPATHLEN];
1123:
1124: if (getcwd(buf, sizeof(buf)) != NULL)
1.20 deraadt 1125: fprintf(ttyout, "Local directory %s\n", buf);
1.13 millert 1126: else
1127: warn("getcwd");
1128: code = 0;
1129: }
1130:
1131: /*
1.1 deraadt 1132: * Make a directory.
1133: */
1134: void
1.47 deraadt 1135: makedir(int argc, char *argv[])
1.1 deraadt 1136: {
1137:
1.13 millert 1138: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1139: argc > 2) {
1.20 deraadt 1140: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1141: code = -1;
1142: return;
1143: }
1144: if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1145: if (verbose)
1.20 deraadt 1146: fputs("MKD command not recognized, trying XMKD.\n", ttyout);
1.14 millert 1147: (void)command("XMKD %s", argv[1]);
1.1 deraadt 1148: }
1149: }
1150:
1151: /*
1152: * Remove a directory.
1153: */
1154: void
1.47 deraadt 1155: removedir(int argc, char *argv[])
1.1 deraadt 1156: {
1157:
1.13 millert 1158: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1159: argc > 2) {
1.20 deraadt 1160: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1161: code = -1;
1162: return;
1163: }
1164: if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1165: if (verbose)
1.20 deraadt 1166: fputs("RMD command not recognized, trying XRMD.\n", ttyout);
1.14 millert 1167: (void)command("XRMD %s", argv[1]);
1.1 deraadt 1168: }
1169: }
1170:
1171: /*
1172: * Send a line, verbatim, to the remote machine.
1173: */
1174: void
1.47 deraadt 1175: quote(int argc, char *argv[])
1.1 deraadt 1176: {
1177:
1178: if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1.64 sobrado 1179: fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1.1 deraadt 1180: code = -1;
1181: return;
1182: }
1183: quote1("", argc, argv);
1184: }
1185:
1186: /*
1187: * Send a SITE command to the remote machine. The line
1188: * is sent verbatim to the remote machine, except that the
1189: * word "SITE" is added at the front.
1190: */
1191: void
1.47 deraadt 1192: site(int argc, char *argv[])
1.1 deraadt 1193: {
1194:
1195: if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1.64 sobrado 1196: fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1.1 deraadt 1197: code = -1;
1198: return;
1199: }
1.26 weingart 1200: quote1("SITE", argc, argv);
1.1 deraadt 1201: }
1202:
1203: /*
1204: * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1205: * Send the result as a one-line command and get response.
1206: */
1207: void
1.47 deraadt 1208: quote1(const char *initial, int argc, char *argv[])
1.1 deraadt 1209: {
1210: int i, len;
1211: char buf[BUFSIZ]; /* must be >= sizeof(line) */
1212:
1.36 lebel 1213: (void)strlcpy(buf, initial, sizeof(buf));
1.1 deraadt 1214: if (argc > 1) {
1.26 weingart 1215: for (i = 1, len = strlen(buf); i < argc && len < sizeof(buf)-1; i++) {
1216: /* Space for next arg */
1217: if (len > 1)
1218: buf[len++] = ' ';
1219:
1220: /* Sanity check */
1221: if (len >= sizeof(buf) - 1)
1222: break;
1223:
1.27 millert 1224: /* Copy next argument, NUL terminate always */
1.36 lebel 1225: strlcpy(&buf[len], argv[i], sizeof(buf) - len);
1.26 weingart 1226:
1227: /* Update string length */
1228: len = strlen(buf);
1.1 deraadt 1229: }
1230: }
1.26 weingart 1231:
1.35 aaron 1232: /* Make double (triple?) sure the sucker is NUL terminated */
1.26 weingart 1233: buf[sizeof(buf) - 1] = '\0';
1234:
1.29 deraadt 1235: if (command("%s", buf) == PRELIM) {
1.1 deraadt 1236: while (getreply(0) == PRELIM)
1237: continue;
1238: }
1239: }
1240:
1241: void
1.47 deraadt 1242: do_chmod(int argc, char *argv[])
1.1 deraadt 1243: {
1244:
1245: if (argc < 2 && !another(&argc, &argv, "mode"))
1246: goto usage;
1.64 sobrado 1247: if ((argc < 3 && !another(&argc, &argv, "file")) || argc > 3) {
1.1 deraadt 1248: usage:
1.64 sobrado 1249: fprintf(ttyout, "usage: %s mode file\n", argv[0]);
1.1 deraadt 1250: code = -1;
1251: return;
1252: }
1.14 millert 1253: (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1.1 deraadt 1254: }
1255:
1256: void
1.47 deraadt 1257: do_umask(int argc, char *argv[])
1.1 deraadt 1258: {
1259: int oldverbose = verbose;
1260:
1261: verbose = 1;
1.14 millert 1262: (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1.1 deraadt 1263: verbose = oldverbose;
1264: }
1265:
1266: void
1.47 deraadt 1267: idle(int argc, char *argv[])
1.1 deraadt 1268: {
1269: int oldverbose = verbose;
1270:
1271: verbose = 1;
1.14 millert 1272: (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1.1 deraadt 1273: verbose = oldverbose;
1274: }
1275:
1276: /*
1277: * Ask the other side for help.
1278: */
1279: void
1.47 deraadt 1280: rmthelp(int argc, char *argv[])
1.1 deraadt 1281: {
1282: int oldverbose = verbose;
1283:
1284: verbose = 1;
1.14 millert 1285: (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1.1 deraadt 1286: verbose = oldverbose;
1287: }
1288:
1289: /*
1290: * Terminate session and exit.
1291: */
1.48 deraadt 1292: /*ARGSUSED*/
1.1 deraadt 1293: void
1.47 deraadt 1294: quit(int argc, char *argv[])
1.1 deraadt 1295: {
1296:
1297: if (connected)
1298: disconnect(0, 0);
1299: pswitch(1);
1300: if (connected) {
1301: disconnect(0, 0);
1302: }
1303: exit(0);
1304: }
1305:
1306: void
1.47 deraadt 1307: account(int argc, char *argv[])
1.1 deraadt 1308: {
1.13 millert 1309: char *ap;
1.1 deraadt 1310:
1.13 millert 1311: if (argc > 2) {
1.20 deraadt 1312: fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1.13 millert 1313: code = -1;
1314: return;
1.1 deraadt 1315: }
1.13 millert 1316: else if (argc == 2)
1317: ap = argv[1];
1318: else
1.1 deraadt 1319: ap = getpass("Account:");
1.14 millert 1320: (void)command("ACCT %s", ap);
1.1 deraadt 1321: }
1322:
1323: jmp_buf abortprox;
1324:
1.48 deraadt 1325: /* ARGSUSED */
1.1 deraadt 1326: void
1.48 deraadt 1327: proxabort(int signo)
1.1 deraadt 1328: {
1329:
1.13 millert 1330: alarmtimer(0);
1.1 deraadt 1331: if (!proxy) {
1332: pswitch(1);
1333: }
1334: if (connected) {
1335: proxflag = 1;
1336: }
1337: else {
1338: proxflag = 0;
1339: }
1340: pswitch(0);
1.13 millert 1341: longjmp(abortprox, 1);
1.1 deraadt 1342: }
1343:
1344: void
1.47 deraadt 1345: doproxy(int argc, char *argv[])
1.1 deraadt 1346: {
1347: struct cmd *c;
1.13 millert 1348: int cmdpos;
1.1 deraadt 1349: sig_t oldintr;
1350:
1351: if (argc < 2 && !another(&argc, &argv, "command")) {
1.20 deraadt 1352: fprintf(ttyout, "usage: %s command\n", argv[0]);
1.1 deraadt 1353: code = -1;
1354: return;
1355: }
1356: c = getcmd(argv[1]);
1357: if (c == (struct cmd *) -1) {
1.20 deraadt 1358: fputs("?Ambiguous command.\n", ttyout);
1359: (void)fflush(ttyout);
1.1 deraadt 1360: code = -1;
1361: return;
1362: }
1363: if (c == 0) {
1.20 deraadt 1364: fputs("?Invalid command.\n", ttyout);
1365: (void)fflush(ttyout);
1.1 deraadt 1366: code = -1;
1367: return;
1368: }
1369: if (!c->c_proxy) {
1.20 deraadt 1370: fputs("?Invalid proxy command.\n", ttyout);
1371: (void)fflush(ttyout);
1.1 deraadt 1372: code = -1;
1373: return;
1374: }
1375: if (setjmp(abortprox)) {
1376: code = -1;
1377: return;
1378: }
1379: oldintr = signal(SIGINT, proxabort);
1380: pswitch(1);
1381: if (c->c_conn && !connected) {
1.20 deraadt 1382: fputs("Not connected.\n", ttyout);
1383: (void)fflush(ttyout);
1.1 deraadt 1384: pswitch(0);
1.14 millert 1385: (void)signal(SIGINT, oldintr);
1.1 deraadt 1386: code = -1;
1387: return;
1388: }
1.13 millert 1389: cmdpos = strcspn(line, " \t");
1390: if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1391: memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1.1 deraadt 1392: (*c->c_handler)(argc-1, argv+1);
1393: if (connected) {
1394: proxflag = 1;
1395: }
1396: else {
1397: proxflag = 0;
1398: }
1399: pswitch(0);
1.14 millert 1400: (void)signal(SIGINT, oldintr);
1.1 deraadt 1401: }
1402:
1403: void
1.47 deraadt 1404: setcase(int argc, char *argv[])
1.1 deraadt 1405: {
1406:
1.13 millert 1407: code = togglevar(argc, argv, &mcase, "Case mapping");
1.1 deraadt 1408: }
1409:
1410: void
1.47 deraadt 1411: setcr(int argc, char *argv[])
1.1 deraadt 1412: {
1413:
1.13 millert 1414: code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1.1 deraadt 1415: }
1416:
1417: void
1.47 deraadt 1418: setntrans(int argc, char *argv[])
1.1 deraadt 1419: {
1420: if (argc == 1) {
1421: ntflag = 0;
1.20 deraadt 1422: fputs("Ntrans off.\n", ttyout);
1.1 deraadt 1423: code = ntflag;
1424: return;
1425: }
1426: ntflag++;
1427: code = ntflag;
1.36 lebel 1428: (void)strlcpy(ntin, argv[1], sizeof(ntin));
1.1 deraadt 1429: if (argc == 2) {
1430: ntout[0] = '\0';
1431: return;
1432: }
1.36 lebel 1433: (void)strlcpy(ntout, argv[2], sizeof(ntout));
1.1 deraadt 1434: }
1435:
1436: void
1.47 deraadt 1437: setnmap(int argc, char *argv[])
1.1 deraadt 1438: {
1439: char *cp;
1440:
1441: if (argc == 1) {
1442: mapflag = 0;
1.20 deraadt 1443: fputs("Nmap off.\n", ttyout);
1.1 deraadt 1444: code = mapflag;
1445: return;
1446: }
1.64 sobrado 1447: if ((argc < 3 && !another(&argc, &argv, "outpattern")) || argc > 3) {
1448: fprintf(ttyout, "usage: %s [inpattern outpattern]\n", argv[0]);
1.1 deraadt 1449: code = -1;
1450: return;
1451: }
1452: mapflag = 1;
1453: code = 1;
1454: cp = strchr(altarg, ' ');
1455: if (proxy) {
1456: while(*++cp == ' ')
1457: continue;
1458: altarg = cp;
1459: cp = strchr(altarg, ' ');
1460: }
1461: *cp = '\0';
1.14 millert 1462: (void)strncpy(mapin, altarg, MAXPATHLEN - 1);
1.1 deraadt 1463: while (*++cp == ' ')
1464: continue;
1.14 millert 1465: (void)strncpy(mapout, cp, MAXPATHLEN - 1);
1.1 deraadt 1466: }
1467:
1468: void
1.47 deraadt 1469: setpassive(int argc, char *argv[])
1.1 deraadt 1470: {
1471:
1.15 millert 1472: code = togglevar(argc, argv, &passivemode,
1473: verbose ? "Passive mode" : NULL);
1.1 deraadt 1474: }
1475:
1476: void
1.47 deraadt 1477: setsunique(int argc, char *argv[])
1.1 deraadt 1478: {
1479:
1.13 millert 1480: code = togglevar(argc, argv, &sunique, "Store unique");
1.1 deraadt 1481: }
1482:
1483: void
1.47 deraadt 1484: setrunique(int argc, char *argv[])
1.1 deraadt 1485: {
1486:
1.13 millert 1487: code = togglevar(argc, argv, &runique, "Receive unique");
1.1 deraadt 1488: }
1489:
1.13 millert 1490: /* change directory to parent directory */
1.48 deraadt 1491: /* ARGSUSED */
1.1 deraadt 1492: void
1.47 deraadt 1493: cdup(int argc, char *argv[])
1.1 deraadt 1494: {
1.13 millert 1495: int r;
1.1 deraadt 1496:
1.13 millert 1497: r = command("CDUP");
1498: if (r == ERROR && code == 500) {
1.1 deraadt 1499: if (verbose)
1.20 deraadt 1500: fputs("CDUP command not recognized, trying XCUP.\n", ttyout);
1.13 millert 1501: r = command("XCUP");
1.1 deraadt 1502: }
1.13 millert 1503: if (r == COMPLETE)
1504: dirchange = 1;
1.1 deraadt 1505: }
1506:
1.23 millert 1507: /*
1508: * Restart transfer at specific point
1509: */
1.1 deraadt 1510: void
1.47 deraadt 1511: restart(int argc, char *argv[])
1.1 deraadt 1512: {
1.27 millert 1513: quad_t nrestart_point;
1514: char *ep;
1.1 deraadt 1515:
1516: if (argc != 2)
1.20 deraadt 1517: fputs("restart: offset not specified.\n", ttyout);
1.1 deraadt 1518: else {
1.38 millert 1519: nrestart_point = strtoq(argv[1], &ep, 10);
1.27 millert 1520: if (nrestart_point == QUAD_MAX || *ep != '\0')
1521: fputs("restart: invalid offset.\n", ttyout);
1522: else {
1.39 millert 1523: fprintf(ttyout, "Restarting at %lld. Execute get, put "
1524: "or append to initiate transfer\n",
1.37 deraadt 1525: (long long)nrestart_point);
1.27 millert 1526: restart_point = nrestart_point;
1527: }
1.1 deraadt 1528: }
1529: }
1530:
1.23 millert 1531: /*
1532: * Show remote system type
1533: */
1.48 deraadt 1534: /* ARGSUSED */
1.1 deraadt 1535: void
1.47 deraadt 1536: syst(int argc, char *argv[])
1.1 deraadt 1537: {
1538:
1.14 millert 1539: (void)command("SYST");
1.1 deraadt 1540: }
1541:
1542: void
1.47 deraadt 1543: macdef(int argc, char *argv[])
1.1 deraadt 1544: {
1545: char *tmp;
1546: int c;
1547:
1548: if (macnum == 16) {
1.20 deraadt 1549: fputs("Limit of 16 macros have already been defined.\n", ttyout);
1.1 deraadt 1550: code = -1;
1551: return;
1552: }
1.64 sobrado 1553: if ((argc < 2 && !another(&argc, &argv, "macro-name")) || argc > 2) {
1554: fprintf(ttyout, "usage: %s macro-name\n", argv[0]);
1.1 deraadt 1555: code = -1;
1556: return;
1557: }
1.16 millert 1558: if (interactive)
1.20 deraadt 1559: fputs(
1560: "Enter macro line by line, terminating it with a null line.\n", ttyout);
1.36 lebel 1561: (void)strlcpy(macros[macnum].mac_name, argv[1],
1562: sizeof(macros[macnum].mac_name));
1.14 millert 1563: if (macnum == 0)
1.1 deraadt 1564: macros[macnum].mac_start = macbuf;
1.14 millert 1565: else
1.1 deraadt 1566: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
1567: tmp = macros[macnum].mac_start;
1568: while (tmp != macbuf+4096) {
1569: if ((c = getchar()) == EOF) {
1.20 deraadt 1570: fputs("macdef: end of file encountered.\n", ttyout);
1.1 deraadt 1571: code = -1;
1572: return;
1573: }
1574: if ((*tmp = c) == '\n') {
1575: if (tmp == macros[macnum].mac_start) {
1576: macros[macnum++].mac_end = tmp;
1577: code = 0;
1578: return;
1579: }
1580: if (*(tmp-1) == '\0') {
1581: macros[macnum++].mac_end = tmp - 1;
1582: code = 0;
1583: return;
1584: }
1585: *tmp = '\0';
1586: }
1587: tmp++;
1588: }
1589: while (1) {
1590: while ((c = getchar()) != '\n' && c != EOF)
1591: /* LOOP */;
1592: if (c == EOF || getchar() == '\n') {
1.20 deraadt 1593: fputs("Macro not defined - 4K buffer exceeded.\n", ttyout);
1.1 deraadt 1594: code = -1;
1595: return;
1596: }
1597: }
1598: }
1599:
1600: /*
1.23 millert 1601: * Get size of file on remote machine
1.1 deraadt 1602: */
1603: void
1.47 deraadt 1604: sizecmd(int argc, char *argv[])
1.1 deraadt 1605: {
1.13 millert 1606: off_t size;
1.1 deraadt 1607:
1.64 sobrado 1608: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1609: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.1 deraadt 1610: code = -1;
1611: return;
1612: }
1.13 millert 1613: size = remotesize(argv[1], 1);
1614: if (size != -1)
1.37 deraadt 1615: fprintf(ttyout, "%s\t%lld\n", argv[1], (long long)size);
1.13 millert 1616: code = size;
1.1 deraadt 1617: }
1618:
1619: /*
1.23 millert 1620: * Get last modification time of file on remote machine
1.1 deraadt 1621: */
1622: void
1.47 deraadt 1623: modtime(int argc, char *argv[])
1.1 deraadt 1624: {
1.13 millert 1625: time_t mtime;
1.1 deraadt 1626:
1.64 sobrado 1627: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1628: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.1 deraadt 1629: code = -1;
1630: return;
1631: }
1.13 millert 1632: mtime = remotemodtime(argv[1], 1);
1633: if (mtime != -1)
1.20 deraadt 1634: fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1.13 millert 1635: code = mtime;
1.1 deraadt 1636: }
1637:
1638: /*
1.23 millert 1639: * Show status on remote machine
1.1 deraadt 1640: */
1641: void
1.47 deraadt 1642: rmtstatus(int argc, char *argv[])
1.1 deraadt 1643: {
1644:
1.14 millert 1645: (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1.1 deraadt 1646: }
1647:
1648: /*
1.23 millert 1649: * Get file if modtime is more recent than current file
1.1 deraadt 1650: */
1651: void
1.47 deraadt 1652: newer(int argc, char *argv[])
1.1 deraadt 1653: {
1654:
1655: if (getit(argc, argv, -1, "w"))
1.20 deraadt 1656: fprintf(ttyout, "Local file \"%s\" is newer than remote file \"%s\".\n",
1.1 deraadt 1657: argv[2], argv[1]);
1.16 millert 1658: }
1659:
1660: /*
1661: * Display one file through $PAGER (defaults to "more").
1662: */
1663: void
1.47 deraadt 1664: page(int argc, char *argv[])
1.16 millert 1665: {
1666: int orestart_point, ohash, overbose;
1.23 millert 1667: char *p, *pager, *oldargv1;
1.16 millert 1668:
1.64 sobrado 1669: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1670: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.16 millert 1671: code = -1;
1672: return;
1673: }
1.23 millert 1674: oldargv1 = argv[1];
1.16 millert 1675: if (!globulize(&argv[1])) {
1676: code = -1;
1677: return;
1678: }
1679: p = getenv("PAGER");
1.30 pjanzen 1680: if (p == NULL || (*p == '\0'))
1.16 millert 1681: p = PAGER;
1.44 deraadt 1682: if (asprintf(&pager, "|%s", p) == -1)
1.16 millert 1683: errx(1, "Can't allocate memory for $PAGER");
1684:
1685: orestart_point = restart_point;
1686: ohash = hash;
1687: overbose = verbose;
1688: restart_point = hash = verbose = 0;
1.23 millert 1689: recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1.16 millert 1690: (void)free(pager);
1691: restart_point = orestart_point;
1692: hash = ohash;
1693: verbose = overbose;
1.23 millert 1694: if (oldargv1 != argv[1]) /* free up after globulize() */
1695: free(argv[1]);
1.1 deraadt 1696: }
1.70 martynas 1697:
1698: #endif /* !SMALL */
1699: