4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
40 * FTP User Program -- Command Routines.
45 FILE *tmp_nlst
= NULL
; /* tmp file; holds NLST results for mget, etc */
48 static jmp_buf jabort
;
49 static jmp_buf abortprox
;
51 static char *remglob(char *argv
[], int doswitch
);
52 static char *onoff(int bool);
53 static int confirm(char *cmd
, char *file
);
54 static int globulize(char **cpp
);
55 static void proxabort(int sig
);
56 static void mabort(int sig
);
57 static char *dotrans(char *name
);
58 static char *domap(char *name
);
59 static void getit(int argc
, char *argv
[], int restartit
, char *mode
);
61 static char *getlevel(int);
63 /* Prompt for command argument, add to buffer with space separator */
65 prompt_for_arg(char *buffer
, int buffer_size
, char *prompt
)
67 if (strlen(buffer
) > buffer_size
- 2) {
68 (void) printf("Line too long\n");
73 (void) printf("(%s) ", prompt
);
74 if (fgets(buffer
+ strlen(buffer
), buffer_size
- strlen(buffer
), stdin
)
80 /* Flush what didn't fit in the buffer */
81 if (buffer
[strlen(buffer
)-1] != '\n') {
82 while (fgetc(stdin
) != '\n' && !ferror(stdin
) && !feof(stdin
))
84 (void) printf("Line too long\n");
88 buffer
[strlen(buffer
)-1] = 0;
96 * Connect to peer server and
97 * auto-login, if possible.
100 setpeer(int argc
, char *argv
[])
105 (void) printf("Already connected to %s, use close first.\n",
111 if (prompt_for_arg(line
, sizeof (line
), "to") == -1) {
119 if (argc
> 3 || argc
< 2) {
120 (void) printf("usage: %s host-name [port]\n", argv
[0]);
124 strcpy(typename
, "ascii");
125 host
= hookup(argv
[1], (argc
> 2 ? argv
[2] : "ftp"));
128 extern char reply_string
[];
132 * Set up defaults for FTP.
134 clevel
= dlevel
= PROT_C
;
136 if (do_auth() && autoencrypt
) {
139 if (command("PROT P") == COMPLETE
)
142 (void) fprintf(stderr
,
143 "%s: couldn't enable encryption\n",
145 /* unable to encrypt command channel, too! */
146 dlevel
= clevel
= PROT_C
;
149 if ((auth_type
!= AUTHTYPE_NONE
) && (clevel
== PROT_C
))
154 (void) login(argv
[1]);
155 /* if skipsyst is enabled, then don't send SYST command */
162 if (command("SYST") == COMPLETE
&& overbose
) {
165 cp
= index(reply_string
+4, ' ');
167 cp
= index(reply_string
+4, '\r');
175 (void) printf("Remote system type is %s.\n",
180 if (strncmp(reply_string
, "215 UNIX Type: L8", 17) == 0) {
184 "Using %s mode to transfer files.\n",
186 } else if (overbose
&&
187 strncmp(reply_string
, "215 TOPS20", 10) == 0) {
189 "Remember to set tenex mode when transfering "
190 "binary files from this machine.\n");
196 static struct types
{
202 { "ascii", "A", TYPE_A
, 0 },
203 { "binary", "I", TYPE_I
, 0 },
204 { "image", "I", TYPE_I
, 0 },
205 { "ebcdic", "E", TYPE_E
, 0 },
206 { "tenex", "L", TYPE_L
, bytename
},
214 settype(int argc
, char *argv
[])
222 (void) printf("usage: %s [", argv
[0]);
224 for (p
= types
; p
->t_name
; p
++) {
225 (void) printf("%s%s", sep
, p
->t_name
);
229 (void) printf(" ]\n");
234 (void) printf("Using %s mode to transfer files.\n", typename
);
238 for (p
= types
; p
->t_name
; p
++)
239 if (strcmp(argv
[1], p
->t_name
) == 0)
241 if (p
->t_name
== 0) {
242 (void) printf("%s: unknown mode\n", argv
[1]);
246 if ((p
->t_arg
!= NULL
) && (*(p
->t_arg
) != '\0'))
247 comret
= command("TYPE %s %s", p
->t_mode
, p
->t_arg
);
249 comret
= command("TYPE %s", p
->t_mode
);
250 if (comret
== COMPLETE
) {
251 (void) strcpy(typename
, p
->t_name
);
257 * Set binary transfer type.
261 setbinary(int argc
, char *argv
[])
263 call(settype
, "type", "binary", 0);
267 * Set ascii transfer type.
271 setascii(int argc
, char *argv
[])
273 call(settype
, "type", "ascii", 0);
277 * Set tenex transfer type.
281 settenex(int argc
, char *argv
[])
283 call(settype
, "type", "tenex", 0);
287 * Set ebcdic transfer type.
291 setebcdic(int argc
, char *argv
[])
293 call(settype
, "type", "ebcdic", 0);
297 * Set file transfer mode.
301 setftpmode(int argc
, char *argv
[])
303 (void) printf("We only support %s mode, sorry.\n", modename
);
308 * Set file transfer format.
312 setform(int argc
, char *argv
[])
314 (void) printf("We only support %s format, sorry.\n", formname
);
319 * Set file transfer structure.
323 setstruct(int argc
, char *argv
[])
326 (void) printf("We only support %s structure, sorry.\n", structname
);
331 * Send a single file.
334 put(int argc
, char *argv
[])
346 if (prompt_for_arg(line
, sizeof (line
), "local-file") == -1) {
356 (void) printf("usage: %s local-file remote-file\n", argv
[0]);
361 if (prompt_for_arg(line
, sizeof (line
), "remote-file") == -1) {
372 if (!globulize(&argv
[1])) {
377 * If "globulize" modifies argv[1], and argv[2] is a copy of
378 * the old argv[1], make it a copy of the new argv[1].
380 if (argv
[1] != oldargv1
&& argv
[2] == oldargv1
) {
383 cmd
= (argv
[0][0] == 'a') ? "APPE" : ((sunique
) ? "STOU" : "STOR");
385 argv
[2] = dotrans(argv
[2]);
387 if (loc
&& mapflag
) {
388 argv
[2] = domap(argv
[2]);
390 sendrequest(cmd
, argv
[1], argv
[2], 1);
400 (void) fflush(stdout
);
401 if (mflag
&& fromatty
) {
402 ointer
= interactive
;
404 if (confirm("Continue with", mname
)) {
405 interactive
= ointer
;
408 interactive
= ointer
;
415 * Send multiple files.
418 mput(int argc
, char *argv
[])
427 if (prompt_for_arg(line
, sizeof (line
), "local-files") == -1) {
436 (void) printf("usage: %s local-files\n", argv
[0]);
442 oldintr
= signal(SIGINT
, mabort
);
443 (void) setjmp(jabort
);
445 char *cp
, *tp2
, tmpbuf
[MAXPATHLEN
];
447 while ((cp
= remglob(argv
, 0)) != NULL
) {
452 if (mflag
&& confirm(argv
[0], cp
)) {
457 mblen(tp
, MB_CUR_MAX
)) <= 0)
470 memcpy(tp2
, tp
, len
);
488 sendrequest((sunique
) ? "STOU" : "STOR",
490 if (!mflag
&& fromatty
) {
491 ointer
= interactive
;
493 if (confirm("Continue with", "mput")) {
496 interactive
= ointer
;
500 (void) signal(SIGINT
, oldintr
);
504 for (i
= 1; i
< argc
; i
++) {
508 if (mflag
&& confirm(argv
[0], argv
[i
])) {
509 tp
= (ntflag
) ? dotrans(argv
[i
]) : argv
[i
];
510 tp
= (mapflag
) ? domap(tp
) : tp
;
511 sendrequest((sunique
) ? "STOU" : "STOR",
513 if (!mflag
&& fromatty
) {
514 ointer
= interactive
;
516 if (confirm("Continue with", "mput")) {
519 interactive
= ointer
;
524 gargs
= glob(argv
[i
]);
525 if (globerr
!= NULL
) {
526 (void) printf("%s\n", globerr
);
531 for (cpp
= gargs
; cpp
&& *cpp
!= NULL
; cpp
++) {
532 if (mflag
&& confirm(argv
[0], *cpp
)) {
533 tp
= (ntflag
) ? dotrans(*cpp
) : *cpp
;
534 tp
= (mapflag
) ? domap(tp
) : tp
;
535 sendrequest((sunique
) ? "STOU" : "STOR",
537 if (!mflag
&& fromatty
) {
538 ointer
= interactive
;
540 if (confirm("Continue with", "mput")) {
543 interactive
= ointer
;
550 (void) signal(SIGINT
, oldintr
);
555 * Restart transfer at a specific offset.
558 restart(int argc
, char *argv
[])
560 off_t orestart_point
= restart_point
;
563 (void) printf("usage: %s [marker]\n", argv
[0]);
572 rp
= strtoll(argv
[1], &endp
, 10);
573 if (errno
|| rp
< 0 || *endp
!= '\0')
574 (void) printf("%s: Invalid offset `%s'\n",
579 if (restart_point
== 0) {
580 if (orestart_point
== 0)
581 (void) printf("No restart marker defined\n");
583 (void) printf("Restart marker cleared\n");
586 "Restarting at %lld for next get, put or append\n",
587 (longlong_t
)restart_point
);
591 reget(int argc
, char *argv
[])
593 getit(argc
, argv
, 1, "r+w");
597 get(int argc
, char *argv
[])
599 getit(argc
, argv
, 0, restart_point
? "r+w" : "w");
606 getit(int argc
, char *argv
[], int restartit
, char *mode
)
615 /* Only permit !file if two arguments. */
620 if (prompt_for_arg(line
, sizeof (line
), "remote-file") == -1) {
630 (void) printf("usage: %s remote-file [ local-file ]\n",
636 if (prompt_for_arg(line
, sizeof (line
), "local-file") == -1) {
646 if (!globulize(&argv
[2])) {
651 char *tp
= argv
[1], *tp2
, tmpbuf
[MAXPATHLEN
];
654 if ((len
= mblen(tp
, MB_CUR_MAX
)) <= 0)
664 if ((len
= mblen(tp
, MB_CUR_MAX
)) <= 0)
666 memcpy(tp2
, tp
, len
);
668 *tp2
= 'a' + *tp2
- 'A';
677 argv
[2] = dotrans(argv
[2]);
679 if (loc
&& mapflag
) {
680 argv
[2] = domap(argv
[2]);
685 if (stat(argv
[2], &stbuf
) < 0) {
690 restart_point
= stbuf
.st_size
;
692 recvrequest("RETR", argv
[2], argv
[1], mode
, allowpipe
);
697 * Get multiple files.
700 mget(int argc
, char *argv
[])
702 char *cp
, *tp
, *tp2
, tmpbuf
[MAXPATHLEN
];
709 if (prompt_for_arg(line
, sizeof (line
), "remote-files") < 0) {
718 (void) printf("usage: %s remote-files\n", argv
[0]);
724 oldintr
= signal(SIGINT
, mabort
);
725 (void) setjmp(jabort
);
726 while ((cp
= remglob(argv
, proxy
)) != NULL
) {
731 if (mflag
&& confirm(argv
[0], cp
)) {
737 while (*tp2
&& need_convert
) {
738 /* Need any case convert? */
741 if ((len
= mblen(tp2
, MB_CUR_MAX
)) <= 0)
746 while (need_convert
&& *tp2
) {
747 /* Convert to lower case */
749 *tp2
= tolower(*tp2
);
750 if ((len
= mblen(tp2
, MB_CUR_MAX
)) <= 0)
762 recvrequest("RETR", tp
, cp
, "w", 0);
764 if (!mflag
&& fromatty
) {
765 ointer
= interactive
;
767 if (confirm("Continue with", "mget")) {
770 interactive
= ointer
;
774 (void) signal(SIGINT
, oldintr
);
779 remglob(char *argv
[], int doswitch
)
781 static char buf
[MAXPATHLEN
];
783 int oldverbose
, oldhash
;
790 if (tmp_nlst
!= NULL
) {
791 (void) fclose(tmp_nlst
);
800 if ((cp
= *++args
) == NULL
)
804 if (tmp_nlst
== NULL
) {
805 if ((tmp_nlst
= tmpfile()) == NULL
) {
806 (void) printf("%s\n", strerror(errno
));
809 oldverbose
= verbose
, verbose
= 0;
810 oldhash
= hash
, hash
= 0;
814 for (; *++argv
!= NULL
; )
815 recvrequest("NLST", NULL
, *argv
, "", 0);
820 verbose
= oldverbose
; hash
= oldhash
;
823 if (fgets(buf
, sizeof (buf
), tmp_nlst
) == NULL
) {
824 (void) fclose(tmp_nlst
), tmp_nlst
= NULL
;
827 if ((cp
= index(buf
, '\n')) != NULL
)
835 return (bool ? "on" : "off");
843 status(int argc
, char *argv
[])
849 (void) printf("Connected to %s.\n", hostname
);
851 (void) printf("Not connected.\n");
855 (void) printf("Connected for proxy commands to %s.\n",
858 (void) printf("No proxy connection.\n");
863 if (auth_type
!= AUTHTYPE_NONE
)
864 (void) printf("Authentication type: %s\n",
865 GSS_AUTHTYPE_NAME(auth_type
));
867 (void) printf("Not authenticated.\n");
868 (void) printf("Mechanism: %s\n", mechstr
);
869 (void) printf("Autoauth: %s; Autologin: %s\n",
870 onoff(autoauth
), onoff(autologin
));
871 levelp
= getlevel(clevel
);
872 (void) printf("Control Channel Protection Level: %s\n",
873 levelp
? levelp
: "<unknown>");
874 levelp
= getlevel(dlevel
);
875 (void) printf("Data Channel Protection Level: %s\n",
876 levelp
? levelp
: "<unknown>");
878 (void) printf("Passive mode: %s.\n", onoff(passivemode
));
879 (void) printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
880 modename
, typename
, formname
, structname
);
881 (void) printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
882 onoff(verbose
), onoff(bell
), onoff(interactive
),
884 (void) printf("Store unique: %s; Receive unique: %s\n", onoff(sunique
),
886 (void) printf("Case: %s; CR stripping: %s\n",
887 onoff(mcase
), onoff(crflag
));
889 (void) printf("Ntrans: (in) %s (out) %s\n", ntin
, ntout
);
891 (void) printf("Ntrans: off\n");
894 (void) printf("Nmap: (in) %s (out) %s\n", mapin
, mapout
);
896 (void) printf("Nmap: off\n");
898 (void) printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
899 onoff(hash
), onoff(sendport
));
901 (void) printf("Macros:\n");
902 for (i
= 0; i
< macnum
; i
++) {
903 (void) printf("\t%s\n", macros
[i
].mac_name
);
910 * Set beep on cmd completed mode.
914 setbell(int argc
, char *argv
[])
917 (void) printf("Bell mode %s.\n", onoff(bell
));
922 * Turn on packet tracing.
926 settrace(int argc
, char *argv
[])
929 (void) printf("Packet tracing %s.\n", onoff(trace
));
934 * Toggle hash mark printing during transfers.
938 sethash(int argc
, char *argv
[])
941 (void) printf("Hash mark printing %s", onoff(hash
));
944 (void) printf(" (%d bytes/hash mark)", HASHSIZ
);
945 (void) printf(".\n");
949 * Turn on printing of server echo's.
953 setverbose(int argc
, char *argv
[])
956 (void) printf("Verbose mode %s.\n", onoff(verbose
));
961 * Toggle PORT cmd use before each data connection.
965 setport(int argc
, char *argv
[])
967 sendport
= !sendport
;
968 (void) printf("Use of PORT cmds %s.\n", onoff(sendport
));
973 * Turn on interactive prompting
974 * during mget, mput, and mdelete.
978 setprompt(int argc
, char *argv
[])
980 interactive
= !interactive
;
981 (void) printf("Interactive mode %s.\n", onoff(interactive
));
986 * Toggle metacharacter interpretation
987 * on local file names.
991 setglob(int argc
, char *argv
[])
994 (void) printf("Globbing %s.\n", onoff(doglob
));
999 * Set debugging mode on/off and/or
1000 * set level of debugging.
1003 setdebug(int argc
, char *argv
[])
1008 val
= atoi(argv
[1]);
1010 (void) printf("%s: bad debugging value.\n", argv
[1]);
1018 options
|= SO_DEBUG
;
1020 options
&= ~SO_DEBUG
;
1021 (void) printf("Debugging %s (debug=%d).\n", onoff(debug
), debug
);
1026 * Set current working directory
1027 * on remote machine.
1030 cd(int argc
, char *argv
[])
1033 if (prompt_for_arg(line
, sizeof (line
), "remote-directory") <
1043 (void) printf("usage: %s remote-directory\n", argv
[0]);
1047 (void) command("CWD %s", argv
[1]);
1051 * Set current working directory
1055 lcd(int argc
, char *argv
[])
1057 char buf
[MAXPATHLEN
], *bufptr
;
1060 argc
++, argv
[1] = home
;
1062 (void) printf("usage: %s local-directory\n", argv
[0]);
1066 if (!globulize(&argv
[1])) {
1070 if (chdir(argv
[1]) < 0) {
1075 bufptr
= getcwd(buf
, MAXPATHLEN
);
1077 * Even though chdir may succeed, getcwd may fail if a component
1078 * of the pwd is unreadable. In this case, print the argument to
1079 * chdir as the resultant directory, since we know it succeeded above.
1081 (void) printf("Local directory now %s\n", (bufptr
? bufptr
: argv
[1]));
1086 * Delete a single file.
1089 delete(int argc
, char *argv
[])
1093 if (prompt_for_arg(line
, sizeof (line
), "remote-file") < 0) {
1102 (void) printf("usage: %s remote-file\n", argv
[0]);
1106 (void) command("DELE %s", argv
[1]);
1110 * Delete multiple files.
1113 mdelete(int argc
, char *argv
[])
1120 if (prompt_for_arg(line
, sizeof (line
), "remote-files") < 0) {
1129 (void) printf("usage: %s remote-files\n", argv
[0]);
1135 oldintr
= signal(SIGINT
, mabort
);
1136 (void) setjmp(jabort
);
1137 while ((cp
= remglob(argv
, 0)) != NULL
) {
1142 if (mflag
&& confirm(argv
[0], cp
)) {
1143 (void) command("DELE %s", cp
);
1144 if (!mflag
&& fromatty
) {
1145 ointer
= interactive
;
1147 if (confirm("Continue with", "mdelete")) {
1150 interactive
= ointer
;
1154 (void) signal(SIGINT
, oldintr
);
1159 * Rename a remote file.
1162 renamefile(int argc
, char *argv
[])
1166 if (prompt_for_arg(line
, sizeof (line
), "from-name") < 0) {
1176 (void) printf("%s from-name to-name\n", argv
[0]);
1181 if (prompt_for_arg(line
, sizeof (line
), "to-name") < 0) {
1191 if (command("RNFR %s", argv
[1]) == CONTINUE
)
1192 (void) command("RNTO %s", argv
[2]);
1196 * Get a directory listing
1200 ls(int argc
, char *argv
[])
1205 argc
++, argv
[1] = NULL
;
1207 argc
++, argv
[2] = "-";
1209 (void) printf("usage: %s remote-directory local-file\n",
1214 if (ls_invokes_NLST
) {
1215 cmd
= ((argv
[0][0] == 'l' || argv
[0][0] == 'n') ?
1218 cmd
= ((argv
[0][0] == 'n') ? "NLST" : "LIST");
1220 if (strcmp(argv
[2], "-") && !globulize(&argv
[2])) {
1224 recvrequest(cmd
, argv
[2], argv
[1], "w", 1);
1228 * Get a directory listing
1229 * of multiple remote files.
1232 mls(int argc
, char *argv
[])
1234 char *cmd
, mode
[1], *dest
;
1239 if (prompt_for_arg(line
, sizeof (line
), "remote-files") < 0) {
1248 if (prompt_for_arg(line
, sizeof (line
), "local-file") < 0) {
1257 (void) printf("usage: %s remote-files local-file\n", argv
[0]);
1261 dest
= argv
[argc
- 1];
1262 argv
[argc
- 1] = NULL
;
1263 if (strcmp(dest
, "-") && *dest
!= '|')
1264 if (!globulize(&dest
) ||
1265 !confirm("output to local-file:", dest
)) {
1269 cmd
= argv
[0][1] == 'l' ? "NLST" : "LIST";
1272 oldintr
= signal(SIGINT
, mabort
);
1273 (void) setjmp(jabort
);
1274 for (i
= 1; mflag
&& i
< argc
-1; ++i
) {
1275 *mode
= (i
== 1) ? 'w' : 'a';
1276 recvrequest(cmd
, dest
, argv
[i
], mode
, 1);
1277 if (!mflag
&& fromatty
) {
1278 ointer
= interactive
;
1280 if (confirm("Continue with", argv
[0])) {
1283 interactive
= ointer
;
1286 (void) signal(SIGINT
, oldintr
);
1295 shell(int argc
, char *argv
[])
1298 void (*old1
)(), (*old2
)();
1299 char *shellstring
, *namep
;
1303 old1
= signal(SIGINT
, SIG_IGN
);
1304 old2
= signal(SIGQUIT
, SIG_IGN
);
1305 if ((pid
= fork()) == 0) {
1306 closefrom(STDERR_FILENO
+ 1);
1307 (void) signal(SIGINT
, SIG_DFL
);
1308 (void) signal(SIGQUIT
, SIG_DFL
);
1309 shellstring
= getenv("SHELL");
1310 if (shellstring
== NULL
)
1311 shellstring
= "/bin/sh";
1312 namep
= rindex(shellstring
, '/');
1314 namep
= shellstring
;
1317 (void) printf("%s -c %s\n", shellstring
,
1319 (void) fflush(stdout
);
1321 execl(shellstring
, namep
, "-c", altarg
, (char *)0);
1324 (void) printf("%s\n", shellstring
);
1325 (void) fflush(stdout
);
1327 execl(shellstring
, namep
, (char *)0);
1329 perror(shellstring
);
1334 while (wait(&status
) != pid
)
1336 (void) signal(SIGINT
, old1
);
1337 (void) signal(SIGQUIT
, old2
);
1339 if (pid
== (pid_t
)-1) {
1340 perror("Try again later");
1348 * Send new user information (re-login)
1351 user(int argc
, char *argv
[])
1357 if (prompt_for_arg(line
, sizeof (line
), "username") < 0) {
1366 (void) printf("usage: %s username [password] [account]\n",
1372 (void) printf("access for user (nil) denied\n");
1376 n
= command("USER %s", argv
[1]);
1377 if (n
== CONTINUE
) {
1380 argv
[2] = mygetpass("Password: "), argc
++;
1381 if ((oldclevel
= clevel
) == PROT_S
)
1383 n
= command("PASS %s", argv
[2]);
1384 /* level may have changed */
1385 if (clevel
== PROT_P
)
1388 if (n
== CONTINUE
) {
1390 (void) printf("Account: "); (void) fflush(stdout
);
1392 (void) fgets(acct
, sizeof (acct
) - 1, stdin
);
1394 acct
[strlen(acct
) - 1] = '\0';
1395 argv
[3] = acct
; argc
++;
1397 n
= command("ACCT %s", argv
[3]);
1400 if (n
!= COMPLETE
) {
1401 (void) fprintf(stdout
, "Login failed.\n");
1404 if (!aflag
&& argc
== 4) {
1405 (void) command("ACCT %s", argv
[3]);
1410 * Print working directory.
1414 pwd(int argc
, char *argv
[])
1416 (void) command("PWD");
1423 makedir(int argc
, char *argv
[])
1426 if (prompt_for_arg(line
, sizeof (line
), "directory-name") <
1436 (void) printf("usage: %s directory-name\n", argv
[0]);
1440 (void) command("MKD %s", argv
[1]);
1444 * Remove a directory.
1447 removedir(int argc
, char *argv
[])
1450 if (prompt_for_arg(line
, sizeof (line
), "directory-name") <
1460 (void) printf("usage: %s directory-name\n", argv
[0]);
1464 (void) command("RMD %s", argv
[1]);
1468 * Send a line, verbatim, to the remote machine.
1471 quote(int argc
, char *argv
[])
1474 char buf
[FTPBUFSIZ
];
1477 if (prompt_for_arg(line
, sizeof (line
),
1478 "command line to send") == -1) {
1487 (void) printf("usage: %s line-to-send\n", argv
[0]);
1491 len
= snprintf(buf
, sizeof (buf
), "%s", argv
[1]);
1492 if (len
>= 0 && len
< sizeof (buf
) - 1) {
1493 for (i
= 2; i
< argc
; i
++) {
1494 n
= snprintf(&buf
[len
], sizeof (buf
) - len
, " %s",
1496 if (n
< 0 || n
>= sizeof (buf
) - len
)
1501 if (command("%s", buf
) == PRELIM
) {
1502 while (getreply(0) == PRELIM
)
1508 * Send a line, verbatim, to the remote machine as a SITE command.
1511 site(int argc
, char *argv
[])
1514 char buf
[FTPBUFSIZ
];
1517 if (prompt_for_arg(line
, sizeof (line
),
1518 "arguments to SITE command") == -1) {
1527 (void) printf("usage: %s arg1 [arg2] ...\n", argv
[0]);
1531 len
= snprintf(buf
, sizeof (buf
), "%s", argv
[1]);
1532 if (len
>= 0 && len
< sizeof (buf
) - 1) {
1533 for (i
= 2; i
< argc
; i
++) {
1534 n
= snprintf(&buf
[len
], sizeof (buf
) - len
, " %s",
1536 if (n
< 0 || n
>= sizeof (buf
) - len
)
1541 if (command("SITE %s", buf
) == PRELIM
) {
1542 while (getreply(0) == PRELIM
)
1548 * Ask the other side for help.
1551 rmthelp(int argc
, char *argv
[])
1553 int oldverbose
= verbose
;
1556 (void) command(argc
== 1 ? "HELP" : "HELP %s", argv
[1]);
1557 verbose
= oldverbose
;
1561 * Terminate session and exit.
1565 quit(int argc
, char *argv
[])
1568 disconnect(0, NULL
);
1571 disconnect(0, NULL
);
1577 * Terminate session, but don't exit.
1581 disconnect(int argc
, char *argv
[])
1583 extern FILE *ctrl_in
, *ctrl_out
;
1588 (void) command("QUIT");
1591 (void) fclose(ctrl_in
);
1595 (void) fclose(ctrl_out
);
1597 ctrl_out
= ctrl_in
= NULL
;
1604 auth_type
= AUTHTYPE_NONE
;
1605 clevel
= dlevel
= PROT_C
;
1610 confirm(char *cmd
, char *file
)
1612 char line
[FTPBUFSIZ
];
1617 (void) printf("%s %s? ", cmd
, file
);
1618 (void) fflush(stdout
);
1620 (void) fgets(line
, sizeof (line
), stdin
);
1622 return (*line
!= 'n' && *line
!= 'N');
1628 (void) fprintf(stderr
, "ftp: %s\n", msg
);
1633 * Glob a local file name specification with
1634 * the expectation of a single return value.
1635 * Can't control multiple values being expanded
1636 * from the expression, we return only the first.
1639 globulize(char **cpp
)
1645 globbed
= glob(*cpp
);
1646 if (globbed
!= NULL
&& *globbed
== NULL
&& globerr
== NULL
)
1647 globerr
= "No match";
1648 if (globerr
!= NULL
) {
1649 (void) printf("%s: %s\n", *cpp
, globerr
);
1655 *cpp
= strdup(*globbed
);
1664 account(int argc
, char *argv
[])
1671 (void) strncpy(acct
, *argv
, 49);
1676 (void) strncat(acct
, *argv
, 49 - strlen(acct
));
1680 ap
= mygetpass("Account:");
1682 (void) command("ACCT %s", ap
);
1700 longjmp(abortprox
, 1);
1704 doproxy(int argc
, char *argv
[])
1710 if (prompt_for_arg(line
, sizeof (line
), "command") == -1) {
1719 (void) printf("usage: %s command\n", argv
[0]);
1723 c
= getcmd(argv
[1]);
1724 if (c
== (struct cmd
*)-1) {
1725 (void) printf("?Ambiguous command\n");
1726 (void) fflush(stdout
);
1731 (void) printf("?Invalid command\n");
1732 (void) fflush(stdout
);
1737 (void) printf("?Invalid proxy command\n");
1738 (void) fflush(stdout
);
1742 if (setjmp(abortprox
)) {
1746 oldintr
= signal(SIGINT
, (void (*)())proxabort
);
1748 if (c
->c_conn
&& !connected
) {
1749 (void) printf("Not connected\n");
1750 (void) fflush(stdout
);
1752 (void) signal(SIGINT
, oldintr
);
1756 (*c
->c_handler
)(argc
-1, argv
+1);
1763 (void) signal(SIGINT
, oldintr
);
1768 setcase(int argc
, char *argv
[])
1771 (void) printf("Case mapping %s.\n", onoff(mcase
));
1777 setcr(int argc
, char *argv
[])
1780 (void) printf("Carriage Return stripping %s.\n", onoff(crflag
));
1785 setntrans(int argc
, char *argv
[])
1789 (void) printf("Ntrans off.\n");
1795 (void) strncpy(ntin
, argv
[1], 16);
1801 (void) strncpy(ntout
, argv
[2], 16);
1808 static char new[MAXPATHLEN
];
1809 char *cp1
, *cp2
= new;
1810 int i
, ostop
, found
;
1812 for (ostop
= 0; *(ntout
+ ostop
) && ostop
< 16; ostop
++)
1814 for (cp1
= name
; *cp1
; cp1
++) {
1816 for (i
= 0; *(ntin
+ i
) && i
< 16; i
++) {
1817 if (*cp1
== *(ntin
+ i
)) {
1820 *cp2
++ = *(ntout
+ i
);
1834 setnmap(int argc
, char *argv
[])
1840 (void) printf("Nmap off.\n");
1845 if (prompt_for_arg(line
, sizeof (line
), "mapout") == -1) {
1854 (void) printf("Usage: %s [mapin mapout]\n", argv
[0]);
1860 cp
= index(altarg
, ' ');
1862 while (*++cp
== ' ')
1865 cp
= index(altarg
, ' ');
1868 (void) strncpy(mapin
, altarg
, MAXPATHLEN
- 1);
1869 while (*++cp
== ' ')
1871 (void) strncpy(mapout
, cp
, MAXPATHLEN
- 1);
1877 static char new[MAXPATHLEN
];
1878 char *cp1
= name
, *cp2
= mapin
;
1879 char *tp
[9], *te
[9];
1880 int i
, toks
[9], toknum
, match
= 1;
1884 for (i
= 0; i
< 9; ++i
) {
1887 while (match
&& *cp1
&& *cp2
) {
1888 if ((len1
= mbtowc(&wc1
, cp1
, MB_CUR_MAX
)) <= 0) {
1889 wc1
= (unsigned char)*cp1
;
1893 if ((len2
= mbtowc(&wc2
, cp2
, MB_CUR_MAX
)) <= 0) {
1894 wc2
= (unsigned char)*cp2
;
1901 if ((len2
= mbtowc(&wc2
, cp2
, MB_CUR_MAX
)) <= 0) {
1902 wc2
= (unsigned char)*cp2
;
1911 if (*cp2
>= '1' && *cp2
<= '9') {
1913 mbtowc(&wc2
, cp2
+ 1, MB_CUR_MAX
)) <= 0) {
1914 wc2
= (unsigned char)*(cp2
+ 1);
1918 toks
[toknum
= *cp2
- '1']++;
1919 tp
[toknum
] = cp1
- len1
;
1921 if ((len1
= mbtowc(&wc1
,
1922 cp1
, MB_CUR_MAX
)) <= 0) {
1924 (unsigned char)*cp1
;
1931 if (*cp1
== 0 && wc2
!= wc1
)
1934 te
[toknum
] = cp1
- len1
;
1936 cp2
++; /* Consume the digit */
1938 cp2
+= len2
; /* Consume wide char */
1958 if ((len2
= mblen(cp2
, MB_CUR_MAX
)) <= 0)
1960 memcpy(cp1
, cp2
, len2
);
1969 if (*cp2
== '$' && isdigit(*(cp2
+1))) {
1970 if (*++cp2
== '0') {
1977 } else if (toks
[toknum
= *cp2
- '1']) {
1978 char *cp3
= tp
[toknum
];
1980 while (cp3
!= te
[toknum
]) {
1986 while (*cp2
&& *cp2
!= ',' && *cp2
!= ']') {
1992 if (*cp2
== '$' && isdigit(*(cp2
+1))) {
1993 if (*++cp2
== '0') {
2000 if (toks
[toknum
= *cp2
- '1']) {
2001 char *cp3
= tp
[toknum
];
2011 mblen(cp2
, MB_CUR_MAX
)) <=
2015 memcpy(cp1
, cp2
, len2
);
2022 "nmap: unbalanced brackets\n");
2028 while (*cp2
&& *cp2
!= ']') {
2029 if (*cp2
== '\\' && *(cp2
+ 1)) {
2032 if ((len2
= mblen(cp2
, MB_CUR_MAX
)) <=
2039 "nmap: unbalanced brackets\n");
2057 if (isdigit(*(cp2
+ 1))) {
2058 if (*++cp2
== '0') {
2064 } else if (toks
[toknum
= *cp2
- '1']) {
2065 char *cp3
= tp
[toknum
];
2067 while (cp3
!= te
[toknum
]) {
2076 if ((len2
= mblen(cp2
, MB_CUR_MAX
)) <= 0)
2078 memcpy(cp1
, cp2
, len2
);
2093 setsunique(int argc
, char *argv
[])
2096 (void) printf("Store unique %s.\n", onoff(sunique
));
2102 setrunique(int argc
, char *argv
[])
2105 (void) printf("Receive unique %s.\n", onoff(runique
));
2111 setpassive(int argc
, char *argv
[])
2113 passivemode
= !passivemode
;
2114 (void) printf("Passive mode %s.\n", onoff(passivemode
));
2119 settcpwindow(int argc
, char *argv
[])
2121 int owindowsize
= tcpwindowsize
;
2124 (void) printf("usage: %s [size]\n", argv
[0]);
2133 window
= (int)strtol(argv
[1], &endp
, 10);
2134 if (errno
|| window
< 0 || *endp
!= '\0')
2135 (void) printf("%s: Invalid size `%s'\n",
2138 tcpwindowsize
= window
;
2140 if (tcpwindowsize
== 0) {
2141 if (owindowsize
== 0)
2142 (void) printf("No TCP window size defined\n");
2144 (void) printf("TCP window size cleared\n");
2146 (void) printf("TCP window size is set to %d\n", tcpwindowsize
);
2149 /* change directory to parent directory */
2152 cdup(int argc
, char *argv
[])
2154 (void) command("CDUP");
2158 macdef(int argc
, char *argv
[])
2164 (void) printf("Limit of 16 macros have already been defined\n");
2169 if (prompt_for_arg(line
, sizeof (line
), "macro name") == -1) {
2178 (void) printf("Usage: %s macro_name\n", argv
[0]);
2183 (void) printf("Enter macro line by line, terminating "
2184 "it with a null line\n");
2186 (void) strncpy(macros
[macnum
].mac_name
, argv
[1], 8);
2188 macros
[macnum
].mac_start
= macbuf
;
2190 macros
[macnum
].mac_start
= macros
[macnum
- 1].mac_end
+ 1;
2192 tmp
= macros
[macnum
].mac_start
;
2193 while (tmp
!= macbuf
+4096) {
2194 if ((c
= getchar()) == EOF
) {
2195 (void) printf("macdef:end of file encountered\n");
2199 if ((*tmp
= c
) == '\n') {
2200 if (tmp
== macros
[macnum
].mac_start
) {
2201 macros
[macnum
++].mac_end
= tmp
;
2205 if (*(tmp
-1) == '\0') {
2206 macros
[macnum
++].mac_end
= tmp
- 1;
2215 while ((c
= getchar()) != '\n' && c
!= EOF
)
2217 if (c
== EOF
|| getchar() == '\n') {
2219 "Macro not defined - 4k buffer exceeded\n");
2227 * The p_name strings are for the getlevel and setlevel commands.
2228 * The name strings for printing are in the arpa/ftp.h file in the
2229 * protnames[] array of strings.
2231 static struct levels
{
2236 { "clear", "C", PROT_C
},
2237 { "safe", "S", PROT_S
},
2238 { "private", "P", PROT_P
},
2243 * Return a pointer to a string which is the readable version of the
2244 * protection level, or NULL if the input level is not found.
2251 for (p
= levels
; (p
!= NULL
) && (p
->p_level
!= level
); p
++)
2253 return (p
? p
->p_name
: NULL
);
2256 static char *plevel
[] = {
2263 * Set control channel protection level.
2266 setclevel(int argc
, char *argv
[])
2275 (void) printf("usage: %s [", argv
[0]);
2277 for (p
= levels
; p
->p_name
; p
++) {
2278 (void) printf("%s%s", sep
, p
->p_name
);
2282 (void) printf(" ]\n");
2287 levelp
= getlevel(clevel
);
2288 (void) printf("Using %s protection level for commands.\n",
2289 levelp
? levelp
: "<unknown>");
2293 for (p
= levels
; (p
!= NULL
) && (p
->p_name
); p
++)
2294 if (strcmp(argv
[1], p
->p_name
) == 0)
2296 if (p
->p_name
== 0) {
2297 (void) printf("%s: unknown protection level\n", argv
[1]);
2301 if (auth_type
== AUTHTYPE_NONE
) {
2302 if (strcmp(p
->p_name
, "clear"))
2303 (void) printf("Cannot set protection level to %s\n",
2307 if (strcmp(p
->p_name
, "clear") == 0) {
2308 comret
= command("CCC");
2309 if (comret
== COMPLETE
)
2313 clevel
= p
->p_level
;
2314 (void) printf("Control channel protection level set to %s.\n",
2319 * Set data channel protection level.
2322 setdlevel(int argc
, char *argv
[])
2330 (void) printf("usage: %s [", argv
[0]);
2332 for (p
= levels
; p
->p_name
; p
++) {
2333 (void) printf("%s%s", sep
, p
->p_name
);
2337 (void) printf(" ]\n");
2341 for (p
= levels
; p
->p_name
; p
++)
2342 if (strcmp(argv
[1], p
->p_name
) == 0)
2344 if (p
->p_name
== 0) {
2345 (void) printf("%s: unknown protection level\n", argv
[1]);
2349 if (auth_type
== AUTHTYPE_NONE
) {
2350 if (strcmp(p
->p_name
, "clear"))
2351 (void) printf("Cannot set protection level to %s\n",
2355 /* Start with a PBSZ of 1 meg */
2356 if (p
->p_level
!= PROT_C
)
2358 comret
= command("PROT %s", p
->p_mode
);
2359 if (comret
== COMPLETE
)
2360 dlevel
= p
->p_level
;
2364 * Set clear command protection level.
2368 ccc(int argc
, char *argv
[])
2370 plevel
[1] = "clear";
2371 setclevel(2, plevel
);
2375 * Set clear data protection level.
2379 setclear(int argc
, char *argv
[])
2381 plevel
[1] = "clear";
2382 setdlevel(2, plevel
);
2386 * Set safe data protection level.
2390 setsafe(int argc
, char *argv
[])
2393 setdlevel(2, plevel
);
2397 * Set private data protection level.
2401 setprivate(int argc
, char *argv
[])
2403 plevel
[1] = "private";
2404 setdlevel(2, plevel
);
2408 * Set mechanism type
2411 setmech(int argc
, char *argv
[])
2413 char tempmech
[MECH_SZ
];
2416 if (prompt_for_arg(line
, sizeof (line
), "mech-type") == -1) {
2426 (void) printf("usage: %s [ mechanism type ]\n", argv
[0]);
2431 if ((strlcpy(tempmech
, argv
[1], MECH_SZ
) >= MECH_SZ
) ||
2432 __gss_mech_to_oid(tempmech
, (gss_OID
*)&mechoid
) !=
2434 (void) printf("%s: %s: not a valid security mechanism\n",
2439 (void) strlcpy(mechstr
, tempmech
, MECH_SZ
);
2440 (void) printf("Using %s mechanism type\n", mechstr
);