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
39 #pragma ident "%Z%%M% %I% %E% SMI"
43 * FTP User Program -- Command Routines.
48 FILE *tmp_nlst
= NULL
; /* tmp file; holds NLST results for mget, etc */
51 static jmp_buf jabort
;
52 static jmp_buf abortprox
;
54 static char *remglob(char *argv
[], int doswitch
);
55 static char *onoff(int bool);
56 static int confirm(char *cmd
, char *file
);
57 static int globulize(char **cpp
);
58 static void proxabort(int sig
);
59 static void mabort(int sig
);
60 static char *dotrans(char *name
);
61 static char *domap(char *name
);
62 static void getit(int argc
, char *argv
[], int restartit
, char *mode
);
64 static char *getlevel(int);
66 /* Prompt for command argument, add to buffer with space separator */
68 prompt_for_arg(char *buffer
, int buffer_size
, char *prompt
)
70 if (strlen(buffer
) > buffer_size
- 2) {
71 (void) printf("Line too long\n");
76 (void) printf("(%s) ", prompt
);
77 if (fgets(buffer
+ strlen(buffer
), buffer_size
- strlen(buffer
), stdin
)
83 /* Flush what didn't fit in the buffer */
84 if (buffer
[strlen(buffer
)-1] != '\n') {
85 while (fgetc(stdin
) != '\n' && !ferror(stdin
) && !feof(stdin
))
87 (void) printf("Line too long\n");
91 buffer
[strlen(buffer
)-1] = 0;
99 * Connect to peer server and
100 * auto-login, if possible.
103 setpeer(int argc
, char *argv
[])
108 (void) printf("Already connected to %s, use close first.\n",
114 if (prompt_for_arg(line
, sizeof (line
), "to") == -1) {
122 if (argc
> 3 || argc
< 2) {
123 (void) printf("usage: %s host-name [port]\n", argv
[0]);
127 strcpy(typename
, "ascii");
128 host
= hookup(argv
[1], (argc
> 2 ? argv
[2] : "ftp"));
131 extern char reply_string
[];
135 * Set up defaults for FTP.
137 clevel
= dlevel
= PROT_C
;
139 if (do_auth() && autoencrypt
) {
142 if (command("PROT P") == COMPLETE
)
145 (void) fprintf(stderr
,
146 "%s: couldn't enable encryption\n",
148 /* unable to encrypt command channel, too! */
149 dlevel
= clevel
= PROT_C
;
152 if ((auth_type
!= AUTHTYPE_NONE
) && (clevel
== PROT_C
))
157 (void) login(argv
[1]);
158 /* if skipsyst is enabled, then don't send SYST command */
165 if (command("SYST") == COMPLETE
&& overbose
) {
168 cp
= index(reply_string
+4, ' ');
170 cp
= index(reply_string
+4, '\r');
178 (void) printf("Remote system type is %s.\n",
183 if (strncmp(reply_string
, "215 UNIX Type: L8", 17) == 0) {
187 "Using %s mode to transfer files.\n",
189 } else if (overbose
&&
190 strncmp(reply_string
, "215 TOPS20", 10) == 0) {
192 "Remember to set tenex mode when transfering "
193 "binary files from this machine.\n");
199 static struct types
{
205 { "ascii", "A", TYPE_A
, 0 },
206 { "binary", "I", TYPE_I
, 0 },
207 { "image", "I", TYPE_I
, 0 },
208 { "ebcdic", "E", TYPE_E
, 0 },
209 { "tenex", "L", TYPE_L
, bytename
},
217 settype(int argc
, char *argv
[])
225 (void) printf("usage: %s [", argv
[0]);
227 for (p
= types
; p
->t_name
; p
++) {
228 (void) printf("%s%s", sep
, p
->t_name
);
232 (void) printf(" ]\n");
237 (void) printf("Using %s mode to transfer files.\n", typename
);
241 for (p
= types
; p
->t_name
; p
++)
242 if (strcmp(argv
[1], p
->t_name
) == 0)
244 if (p
->t_name
== 0) {
245 (void) printf("%s: unknown mode\n", argv
[1]);
249 if ((p
->t_arg
!= NULL
) && (*(p
->t_arg
) != '\0'))
250 comret
= command("TYPE %s %s", p
->t_mode
, p
->t_arg
);
252 comret
= command("TYPE %s", p
->t_mode
);
253 if (comret
== COMPLETE
) {
254 (void) strcpy(typename
, p
->t_name
);
260 * Set binary transfer type.
264 setbinary(int argc
, char *argv
[])
266 call(settype
, "type", "binary", 0);
270 * Set ascii transfer type.
274 setascii(int argc
, char *argv
[])
276 call(settype
, "type", "ascii", 0);
280 * Set tenex transfer type.
284 settenex(int argc
, char *argv
[])
286 call(settype
, "type", "tenex", 0);
290 * Set ebcdic transfer type.
294 setebcdic(int argc
, char *argv
[])
296 call(settype
, "type", "ebcdic", 0);
300 * Set file transfer mode.
304 setmode(int argc
, char *argv
[])
306 (void) printf("We only support %s mode, sorry.\n", modename
);
311 * Set file transfer format.
315 setform(int argc
, char *argv
[])
317 (void) printf("We only support %s format, sorry.\n", formname
);
322 * Set file transfer structure.
326 setstruct(int argc
, char *argv
[])
329 (void) printf("We only support %s structure, sorry.\n", structname
);
334 * Send a single file.
337 put(int argc
, char *argv
[])
349 if (prompt_for_arg(line
, sizeof (line
), "local-file") == -1) {
359 (void) printf("usage: %s local-file remote-file\n", argv
[0]);
364 if (prompt_for_arg(line
, sizeof (line
), "remote-file") == -1) {
375 if (!globulize(&argv
[1])) {
380 * If "globulize" modifies argv[1], and argv[2] is a copy of
381 * the old argv[1], make it a copy of the new argv[1].
383 if (argv
[1] != oldargv1
&& argv
[2] == oldargv1
) {
386 cmd
= (argv
[0][0] == 'a') ? "APPE" : ((sunique
) ? "STOU" : "STOR");
388 argv
[2] = dotrans(argv
[2]);
390 if (loc
&& mapflag
) {
391 argv
[2] = domap(argv
[2]);
393 sendrequest(cmd
, argv
[1], argv
[2], 1);
403 (void) fflush(stdout
);
404 if (mflag
&& fromatty
) {
405 ointer
= interactive
;
407 if (confirm("Continue with", mname
)) {
408 interactive
= ointer
;
411 interactive
= ointer
;
418 * Send multiple files.
421 mput(int argc
, char *argv
[])
430 if (prompt_for_arg(line
, sizeof (line
), "local-files") == -1) {
439 (void) printf("usage: %s local-files\n", argv
[0]);
445 oldintr
= signal(SIGINT
, mabort
);
446 (void) setjmp(jabort
);
448 char *cp
, *tp2
, tmpbuf
[MAXPATHLEN
];
450 while ((cp
= remglob(argv
, 0)) != NULL
) {
455 if (mflag
&& confirm(argv
[0], cp
)) {
460 mblen(tp
, MB_CUR_MAX
)) <= 0)
473 memcpy(tp2
, tp
, len
);
491 sendrequest((sunique
) ? "STOU" : "STOR",
493 if (!mflag
&& fromatty
) {
494 ointer
= interactive
;
496 if (confirm("Continue with", "mput")) {
499 interactive
= ointer
;
503 (void) signal(SIGINT
, oldintr
);
507 for (i
= 1; i
< argc
; i
++) {
511 if (mflag
&& confirm(argv
[0], argv
[i
])) {
512 tp
= (ntflag
) ? dotrans(argv
[i
]) : argv
[i
];
513 tp
= (mapflag
) ? domap(tp
) : tp
;
514 sendrequest((sunique
) ? "STOU" : "STOR",
516 if (!mflag
&& fromatty
) {
517 ointer
= interactive
;
519 if (confirm("Continue with", "mput")) {
522 interactive
= ointer
;
527 gargs
= glob(argv
[i
]);
528 if (globerr
!= NULL
) {
529 (void) printf("%s\n", globerr
);
534 for (cpp
= gargs
; cpp
&& *cpp
!= NULL
; cpp
++) {
535 if (mflag
&& confirm(argv
[0], *cpp
)) {
536 tp
= (ntflag
) ? dotrans(*cpp
) : *cpp
;
537 tp
= (mapflag
) ? domap(tp
) : tp
;
538 sendrequest((sunique
) ? "STOU" : "STOR",
540 if (!mflag
&& fromatty
) {
541 ointer
= interactive
;
543 if (confirm("Continue with", "mput")) {
546 interactive
= ointer
;
553 (void) signal(SIGINT
, oldintr
);
558 * Restart transfer at a specific offset.
561 restart(int argc
, char *argv
[])
563 off_t orestart_point
= restart_point
;
566 (void) printf("usage: %s [marker]\n", argv
[0]);
575 rp
= strtoll(argv
[1], &endp
, 10);
576 if (errno
|| rp
< 0 || *endp
!= '\0')
577 (void) printf("%s: Invalid offset `%s'\n",
582 if (restart_point
== 0) {
583 if (orestart_point
== 0)
584 (void) printf("No restart marker defined\n");
586 (void) printf("Restart marker cleared\n");
589 "Restarting at %lld for next get, put or append\n",
590 (longlong_t
)restart_point
);
594 reget(int argc
, char *argv
[])
596 getit(argc
, argv
, 1, "r+w");
600 get(int argc
, char *argv
[])
602 getit(argc
, argv
, 0, restart_point
? "r+w" : "w");
609 getit(int argc
, char *argv
[], int restartit
, char *mode
)
618 /* Only permit !file if two arguments. */
623 if (prompt_for_arg(line
, sizeof (line
), "remote-file") == -1) {
633 (void) printf("usage: %s remote-file [ local-file ]\n",
639 if (prompt_for_arg(line
, sizeof (line
), "local-file") == -1) {
649 if (!globulize(&argv
[2])) {
654 char *tp
= argv
[1], *tp2
, tmpbuf
[MAXPATHLEN
];
657 if ((len
= mblen(tp
, MB_CUR_MAX
)) <= 0)
667 if ((len
= mblen(tp
, MB_CUR_MAX
)) <= 0)
669 memcpy(tp2
, tp
, len
);
671 *tp2
= 'a' + *tp2
- 'A';
680 argv
[2] = dotrans(argv
[2]);
682 if (loc
&& mapflag
) {
683 argv
[2] = domap(argv
[2]);
688 if (stat(argv
[2], &stbuf
) < 0) {
693 restart_point
= stbuf
.st_size
;
695 recvrequest("RETR", argv
[2], argv
[1], mode
, allowpipe
);
700 * Get multiple files.
703 mget(int argc
, char *argv
[])
705 char *cp
, *tp
, *tp2
, tmpbuf
[MAXPATHLEN
];
712 if (prompt_for_arg(line
, sizeof (line
), "remote-files") < 0) {
721 (void) printf("usage: %s remote-files\n", argv
[0]);
727 oldintr
= signal(SIGINT
, mabort
);
728 (void) setjmp(jabort
);
729 while ((cp
= remglob(argv
, proxy
)) != NULL
) {
734 if (mflag
&& confirm(argv
[0], cp
)) {
740 while (*tp2
&& need_convert
) {
741 /* Need any case convert? */
744 if ((len
= mblen(tp2
, MB_CUR_MAX
)) <= 0)
749 while (need_convert
&& *tp2
) {
750 /* Convert to lower case */
752 *tp2
= tolower(*tp2
);
753 if ((len
= mblen(tp2
, MB_CUR_MAX
)) <= 0)
765 recvrequest("RETR", tp
, cp
, "w", 0);
767 if (!mflag
&& fromatty
) {
768 ointer
= interactive
;
770 if (confirm("Continue with", "mget")) {
773 interactive
= ointer
;
777 (void) signal(SIGINT
, oldintr
);
782 remglob(char *argv
[], int doswitch
)
784 static char buf
[MAXPATHLEN
];
786 int oldverbose
, oldhash
;
793 if (tmp_nlst
!= NULL
) {
794 (void) fclose(tmp_nlst
);
803 if ((cp
= *++args
) == NULL
)
807 if (tmp_nlst
== NULL
) {
808 if ((tmp_nlst
= tmpfile()) == NULL
) {
809 (void) printf("%s\n", strerror(errno
));
812 oldverbose
= verbose
, verbose
= 0;
813 oldhash
= hash
, hash
= 0;
817 for (; *++argv
!= NULL
; )
818 recvrequest("NLST", NULL
, *argv
, "", 0);
823 verbose
= oldverbose
; hash
= oldhash
;
826 if (fgets(buf
, sizeof (buf
), tmp_nlst
) == NULL
) {
827 (void) fclose(tmp_nlst
), tmp_nlst
= NULL
;
830 if ((cp
= index(buf
, '\n')) != NULL
)
838 return (bool ? "on" : "off");
846 status(int argc
, char *argv
[])
852 (void) printf("Connected to %s.\n", hostname
);
854 (void) printf("Not connected.\n");
858 (void) printf("Connected for proxy commands to %s.\n",
861 (void) printf("No proxy connection.\n");
866 if (auth_type
!= AUTHTYPE_NONE
)
867 (void) printf("Authentication type: %s\n",
868 GSS_AUTHTYPE_NAME(auth_type
));
870 (void) printf("Not authenticated.\n");
871 (void) printf("Mechanism: %s\n", mechstr
);
872 (void) printf("Autoauth: %s; Autologin: %s\n",
873 onoff(autoauth
), onoff(autologin
));
874 levelp
= getlevel(clevel
);
875 (void) printf("Control Channel Protection Level: %s\n",
876 levelp
? levelp
: "<unknown>");
877 levelp
= getlevel(dlevel
);
878 (void) printf("Data Channel Protection Level: %s\n",
879 levelp
? levelp
: "<unknown>");
881 (void) printf("Passive mode: %s.\n", onoff(passivemode
));
882 (void) printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
883 modename
, typename
, formname
, structname
);
884 (void) printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
885 onoff(verbose
), onoff(bell
), onoff(interactive
),
887 (void) printf("Store unique: %s; Receive unique: %s\n", onoff(sunique
),
889 (void) printf("Case: %s; CR stripping: %s\n",
890 onoff(mcase
), onoff(crflag
));
892 (void) printf("Ntrans: (in) %s (out) %s\n", ntin
, ntout
);
894 (void) printf("Ntrans: off\n");
897 (void) printf("Nmap: (in) %s (out) %s\n", mapin
, mapout
);
899 (void) printf("Nmap: off\n");
901 (void) printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
902 onoff(hash
), onoff(sendport
));
904 (void) printf("Macros:\n");
905 for (i
= 0; i
< macnum
; i
++) {
906 (void) printf("\t%s\n", macros
[i
].mac_name
);
913 * Set beep on cmd completed mode.
917 setbell(int argc
, char *argv
[])
920 (void) printf("Bell mode %s.\n", onoff(bell
));
925 * Turn on packet tracing.
929 settrace(int argc
, char *argv
[])
932 (void) printf("Packet tracing %s.\n", onoff(trace
));
937 * Toggle hash mark printing during transfers.
941 sethash(int argc
, char *argv
[])
944 (void) printf("Hash mark printing %s", onoff(hash
));
947 (void) printf(" (%d bytes/hash mark)", HASHSIZ
);
948 (void) printf(".\n");
952 * Turn on printing of server echo's.
956 setverbose(int argc
, char *argv
[])
959 (void) printf("Verbose mode %s.\n", onoff(verbose
));
964 * Toggle PORT cmd use before each data connection.
968 setport(int argc
, char *argv
[])
970 sendport
= !sendport
;
971 (void) printf("Use of PORT cmds %s.\n", onoff(sendport
));
976 * Turn on interactive prompting
977 * during mget, mput, and mdelete.
981 setprompt(int argc
, char *argv
[])
983 interactive
= !interactive
;
984 (void) printf("Interactive mode %s.\n", onoff(interactive
));
989 * Toggle metacharacter interpretation
990 * on local file names.
994 setglob(int argc
, char *argv
[])
997 (void) printf("Globbing %s.\n", onoff(doglob
));
1002 * Set debugging mode on/off and/or
1003 * set level of debugging.
1006 setdebug(int argc
, char *argv
[])
1011 val
= atoi(argv
[1]);
1013 (void) printf("%s: bad debugging value.\n", argv
[1]);
1021 options
|= SO_DEBUG
;
1023 options
&= ~SO_DEBUG
;
1024 (void) printf("Debugging %s (debug=%d).\n", onoff(debug
), debug
);
1029 * Set current working directory
1030 * on remote machine.
1033 cd(int argc
, char *argv
[])
1036 if (prompt_for_arg(line
, sizeof (line
), "remote-directory") <
1046 (void) printf("usage: %s remote-directory\n", argv
[0]);
1050 (void) command("CWD %s", argv
[1]);
1054 * Set current working directory
1058 lcd(int argc
, char *argv
[])
1060 char buf
[MAXPATHLEN
], *bufptr
;
1063 argc
++, argv
[1] = home
;
1065 (void) printf("usage: %s local-directory\n", argv
[0]);
1069 if (!globulize(&argv
[1])) {
1073 if (chdir(argv
[1]) < 0) {
1078 bufptr
= getcwd(buf
, MAXPATHLEN
);
1080 * Even though chdir may succeed, getcwd may fail if a component
1081 * of the pwd is unreadable. In this case, print the argument to
1082 * chdir as the resultant directory, since we know it succeeded above.
1084 (void) printf("Local directory now %s\n", (bufptr
? bufptr
: argv
[1]));
1089 * Delete a single file.
1092 delete(int argc
, char *argv
[])
1096 if (prompt_for_arg(line
, sizeof (line
), "remote-file") < 0) {
1105 (void) printf("usage: %s remote-file\n", argv
[0]);
1109 (void) command("DELE %s", argv
[1]);
1113 * Delete multiple files.
1116 mdelete(int argc
, char *argv
[])
1123 if (prompt_for_arg(line
, sizeof (line
), "remote-files") < 0) {
1132 (void) printf("usage: %s remote-files\n", argv
[0]);
1138 oldintr
= signal(SIGINT
, mabort
);
1139 (void) setjmp(jabort
);
1140 while ((cp
= remglob(argv
, 0)) != NULL
) {
1145 if (mflag
&& confirm(argv
[0], cp
)) {
1146 (void) command("DELE %s", cp
);
1147 if (!mflag
&& fromatty
) {
1148 ointer
= interactive
;
1150 if (confirm("Continue with", "mdelete")) {
1153 interactive
= ointer
;
1157 (void) signal(SIGINT
, oldintr
);
1162 * Rename a remote file.
1165 renamefile(int argc
, char *argv
[])
1169 if (prompt_for_arg(line
, sizeof (line
), "from-name") < 0) {
1179 (void) printf("%s from-name to-name\n", argv
[0]);
1184 if (prompt_for_arg(line
, sizeof (line
), "to-name") < 0) {
1194 if (command("RNFR %s", argv
[1]) == CONTINUE
)
1195 (void) command("RNTO %s", argv
[2]);
1199 * Get a directory listing
1203 ls(int argc
, char *argv
[])
1208 argc
++, argv
[1] = NULL
;
1210 argc
++, argv
[2] = "-";
1212 (void) printf("usage: %s remote-directory local-file\n",
1217 if (ls_invokes_NLST
) {
1218 cmd
= ((argv
[0][0] == 'l' || argv
[0][0] == 'n') ?
1221 cmd
= ((argv
[0][0] == 'n') ? "NLST" : "LIST");
1223 if (strcmp(argv
[2], "-") && !globulize(&argv
[2])) {
1227 recvrequest(cmd
, argv
[2], argv
[1], "w", 1);
1231 * Get a directory listing
1232 * of multiple remote files.
1235 mls(int argc
, char *argv
[])
1237 char *cmd
, mode
[1], *dest
;
1242 if (prompt_for_arg(line
, sizeof (line
), "remote-files") < 0) {
1251 if (prompt_for_arg(line
, sizeof (line
), "local-file") < 0) {
1260 (void) printf("usage: %s remote-files local-file\n", argv
[0]);
1264 dest
= argv
[argc
- 1];
1265 argv
[argc
- 1] = NULL
;
1266 if (strcmp(dest
, "-") && *dest
!= '|')
1267 if (!globulize(&dest
) ||
1268 !confirm("output to local-file:", dest
)) {
1272 cmd
= argv
[0][1] == 'l' ? "NLST" : "LIST";
1275 oldintr
= signal(SIGINT
, mabort
);
1276 (void) setjmp(jabort
);
1277 for (i
= 1; mflag
&& i
< argc
-1; ++i
) {
1278 *mode
= (i
== 1) ? 'w' : 'a';
1279 recvrequest(cmd
, dest
, argv
[i
], mode
, 1);
1280 if (!mflag
&& fromatty
) {
1281 ointer
= interactive
;
1283 if (confirm("Continue with", argv
[0])) {
1286 interactive
= ointer
;
1289 (void) signal(SIGINT
, oldintr
);
1298 shell(int argc
, char *argv
[])
1301 void (*old1
)(), (*old2
)();
1302 char *shellstring
, *namep
;
1306 old1
= signal(SIGINT
, SIG_IGN
);
1307 old2
= signal(SIGQUIT
, SIG_IGN
);
1308 if ((pid
= fork()) == 0) {
1309 closefrom(STDERR_FILENO
+ 1);
1310 (void) signal(SIGINT
, SIG_DFL
);
1311 (void) signal(SIGQUIT
, SIG_DFL
);
1312 shellstring
= getenv("SHELL");
1313 if (shellstring
== NULL
)
1314 shellstring
= "/bin/sh";
1315 namep
= rindex(shellstring
, '/');
1317 namep
= shellstring
;
1320 (void) printf("%s -c %s\n", shellstring
,
1322 (void) fflush(stdout
);
1324 execl(shellstring
, namep
, "-c", altarg
, (char *)0);
1327 (void) printf("%s\n", shellstring
);
1328 (void) fflush(stdout
);
1330 execl(shellstring
, namep
, (char *)0);
1332 perror(shellstring
);
1337 while (wait(&status
) != pid
)
1339 (void) signal(SIGINT
, old1
);
1340 (void) signal(SIGQUIT
, old2
);
1342 if (pid
== (pid_t
)-1) {
1343 perror("Try again later");
1351 * Send new user information (re-login)
1354 user(int argc
, char *argv
[])
1360 if (prompt_for_arg(line
, sizeof (line
), "username") < 0) {
1369 (void) printf("usage: %s username [password] [account]\n",
1375 (void) printf("access for user (nil) denied\n");
1379 n
= command("USER %s", argv
[1]);
1380 if (n
== CONTINUE
) {
1383 argv
[2] = mygetpass("Password: "), argc
++;
1384 if ((oldclevel
= clevel
) == PROT_S
)
1386 n
= command("PASS %s", argv
[2]);
1387 /* level may have changed */
1388 if (clevel
== PROT_P
)
1391 if (n
== CONTINUE
) {
1393 (void) printf("Account: "); (void) fflush(stdout
);
1395 (void) fgets(acct
, sizeof (acct
) - 1, stdin
);
1397 acct
[strlen(acct
) - 1] = '\0';
1398 argv
[3] = acct
; argc
++;
1400 n
= command("ACCT %s", argv
[3]);
1403 if (n
!= COMPLETE
) {
1404 (void) fprintf(stdout
, "Login failed.\n");
1407 if (!aflag
&& argc
== 4) {
1408 (void) command("ACCT %s", argv
[3]);
1413 * Print working directory.
1417 pwd(int argc
, char *argv
[])
1419 (void) command("PWD");
1426 makedir(int argc
, char *argv
[])
1429 if (prompt_for_arg(line
, sizeof (line
), "directory-name") <
1439 (void) printf("usage: %s directory-name\n", argv
[0]);
1443 (void) command("MKD %s", argv
[1]);
1447 * Remove a directory.
1450 removedir(int argc
, char *argv
[])
1453 if (prompt_for_arg(line
, sizeof (line
), "directory-name") <
1463 (void) printf("usage: %s directory-name\n", argv
[0]);
1467 (void) command("RMD %s", argv
[1]);
1471 * Send a line, verbatim, to the remote machine.
1474 quote(int argc
, char *argv
[])
1477 char buf
[FTPBUFSIZ
];
1480 if (prompt_for_arg(line
, sizeof (line
),
1481 "command line to send") == -1) {
1490 (void) printf("usage: %s line-to-send\n", argv
[0]);
1494 len
= snprintf(buf
, sizeof (buf
), "%s", argv
[1]);
1495 if (len
>= 0 && len
< sizeof (buf
) - 1) {
1496 for (i
= 2; i
< argc
; i
++) {
1497 n
= snprintf(&buf
[len
], sizeof (buf
) - len
, " %s",
1499 if (n
< 0 || n
>= sizeof (buf
) - len
)
1504 if (command("%s", buf
) == PRELIM
) {
1505 while (getreply(0) == PRELIM
)
1511 * Send a line, verbatim, to the remote machine as a SITE command.
1514 site(int argc
, char *argv
[])
1517 char buf
[FTPBUFSIZ
];
1520 if (prompt_for_arg(line
, sizeof (line
),
1521 "arguments to SITE command") == -1) {
1530 (void) printf("usage: %s arg1 [arg2] ...\n", argv
[0]);
1534 len
= snprintf(buf
, sizeof (buf
), "%s", argv
[1]);
1535 if (len
>= 0 && len
< sizeof (buf
) - 1) {
1536 for (i
= 2; i
< argc
; i
++) {
1537 n
= snprintf(&buf
[len
], sizeof (buf
) - len
, " %s",
1539 if (n
< 0 || n
>= sizeof (buf
) - len
)
1544 if (command("SITE %s", buf
) == PRELIM
) {
1545 while (getreply(0) == PRELIM
)
1551 * Ask the other side for help.
1554 rmthelp(int argc
, char *argv
[])
1556 int oldverbose
= verbose
;
1559 (void) command(argc
== 1 ? "HELP" : "HELP %s", argv
[1]);
1560 verbose
= oldverbose
;
1564 * Terminate session and exit.
1568 quit(int argc
, char *argv
[])
1571 disconnect(0, NULL
);
1574 disconnect(0, NULL
);
1580 * Terminate session, but don't exit.
1584 disconnect(int argc
, char *argv
[])
1586 extern FILE *ctrl_in
, *ctrl_out
;
1591 (void) command("QUIT");
1594 (void) fclose(ctrl_in
);
1598 (void) fclose(ctrl_out
);
1600 ctrl_out
= ctrl_in
= NULL
;
1607 auth_type
= AUTHTYPE_NONE
;
1608 clevel
= dlevel
= PROT_C
;
1613 confirm(char *cmd
, char *file
)
1615 char line
[FTPBUFSIZ
];
1620 (void) printf("%s %s? ", cmd
, file
);
1621 (void) fflush(stdout
);
1623 (void) fgets(line
, sizeof (line
), stdin
);
1625 return (*line
!= 'n' && *line
!= 'N');
1631 (void) fprintf(stderr
, "ftp: %s\n", msg
);
1636 * Glob a local file name specification with
1637 * the expectation of a single return value.
1638 * Can't control multiple values being expanded
1639 * from the expression, we return only the first.
1642 globulize(char **cpp
)
1648 globbed
= glob(*cpp
);
1649 if (globbed
!= NULL
&& *globbed
== NULL
&& globerr
== NULL
)
1650 globerr
= "No match";
1651 if (globerr
!= NULL
) {
1652 (void) printf("%s: %s\n", *cpp
, globerr
);
1658 *cpp
= strdup(*globbed
);
1667 account(int argc
, char *argv
[])
1674 (void) strncpy(acct
, *argv
, 49);
1679 (void) strncat(acct
, *argv
, 49 - strlen(acct
));
1683 ap
= mygetpass("Account:");
1685 (void) command("ACCT %s", ap
);
1703 longjmp(abortprox
, 1);
1707 doproxy(int argc
, char *argv
[])
1713 if (prompt_for_arg(line
, sizeof (line
), "command") == -1) {
1722 (void) printf("usage: %s command\n", argv
[0]);
1726 c
= getcmd(argv
[1]);
1727 if (c
== (struct cmd
*)-1) {
1728 (void) printf("?Ambiguous command\n");
1729 (void) fflush(stdout
);
1734 (void) printf("?Invalid command\n");
1735 (void) fflush(stdout
);
1740 (void) printf("?Invalid proxy command\n");
1741 (void) fflush(stdout
);
1745 if (setjmp(abortprox
)) {
1749 oldintr
= signal(SIGINT
, (void (*)())proxabort
);
1751 if (c
->c_conn
&& !connected
) {
1752 (void) printf("Not connected\n");
1753 (void) fflush(stdout
);
1755 (void) signal(SIGINT
, oldintr
);
1759 (*c
->c_handler
)(argc
-1, argv
+1);
1766 (void) signal(SIGINT
, oldintr
);
1771 setcase(int argc
, char *argv
[])
1774 (void) printf("Case mapping %s.\n", onoff(mcase
));
1780 setcr(int argc
, char *argv
[])
1783 (void) printf("Carriage Return stripping %s.\n", onoff(crflag
));
1788 setntrans(int argc
, char *argv
[])
1792 (void) printf("Ntrans off.\n");
1798 (void) strncpy(ntin
, argv
[1], 16);
1804 (void) strncpy(ntout
, argv
[2], 16);
1811 static char new[MAXPATHLEN
];
1812 char *cp1
, *cp2
= new;
1813 int i
, ostop
, found
;
1815 for (ostop
= 0; *(ntout
+ ostop
) && ostop
< 16; ostop
++)
1817 for (cp1
= name
; *cp1
; cp1
++) {
1819 for (i
= 0; *(ntin
+ i
) && i
< 16; i
++) {
1820 if (*cp1
== *(ntin
+ i
)) {
1823 *cp2
++ = *(ntout
+ i
);
1837 setnmap(int argc
, char *argv
[])
1843 (void) printf("Nmap off.\n");
1848 if (prompt_for_arg(line
, sizeof (line
), "mapout") == -1) {
1857 (void) printf("Usage: %s [mapin mapout]\n", argv
[0]);
1863 cp
= index(altarg
, ' ');
1865 while (*++cp
== ' ')
1868 cp
= index(altarg
, ' ');
1871 (void) strncpy(mapin
, altarg
, MAXPATHLEN
- 1);
1872 while (*++cp
== ' ')
1874 (void) strncpy(mapout
, cp
, MAXPATHLEN
- 1);
1880 static char new[MAXPATHLEN
];
1881 char *cp1
= name
, *cp2
= mapin
;
1882 char *tp
[9], *te
[9];
1883 int i
, toks
[9], toknum
, match
= 1;
1887 for (i
= 0; i
< 9; ++i
) {
1890 while (match
&& *cp1
&& *cp2
) {
1891 if ((len1
= mbtowc(&wc1
, cp1
, MB_CUR_MAX
)) <= 0) {
1892 wc1
= (unsigned char)*cp1
;
1896 if ((len2
= mbtowc(&wc2
, cp2
, MB_CUR_MAX
)) <= 0) {
1897 wc2
= (unsigned char)*cp2
;
1904 if ((len2
= mbtowc(&wc2
, cp2
, MB_CUR_MAX
)) <= 0) {
1905 wc2
= (unsigned char)*cp2
;
1914 if (*cp2
>= '1' && *cp2
<= '9') {
1916 mbtowc(&wc2
, cp2
+ 1, MB_CUR_MAX
)) <= 0) {
1917 wc2
= (unsigned char)*(cp2
+ 1);
1921 toks
[toknum
= *cp2
- '1']++;
1922 tp
[toknum
] = cp1
- len1
;
1924 if ((len1
= mbtowc(&wc1
,
1925 cp1
, MB_CUR_MAX
)) <= 0) {
1927 (unsigned char)*cp1
;
1934 if (*cp1
== 0 && wc2
!= wc1
)
1937 te
[toknum
] = cp1
- len1
;
1939 cp2
++; /* Consume the digit */
1941 cp2
+= len2
; /* Consume wide char */
1944 /* intentional drop through */
1961 if ((len2
= mblen(cp2
, MB_CUR_MAX
)) <= 0)
1963 memcpy(cp1
, cp2
, len2
);
1972 if (*cp2
== '$' && isdigit(*(cp2
+1))) {
1973 if (*++cp2
== '0') {
1980 } else if (toks
[toknum
= *cp2
- '1']) {
1981 char *cp3
= tp
[toknum
];
1983 while (cp3
!= te
[toknum
]) {
1989 while (*cp2
&& *cp2
!= ',' && *cp2
!= ']') {
1995 if (*cp2
== '$' && isdigit(*(cp2
+1))) {
1996 if (*++cp2
== '0') {
2003 if (toks
[toknum
= *cp2
- '1']) {
2004 char *cp3
= tp
[toknum
];
2014 mblen(cp2
, MB_CUR_MAX
)) <=
2018 memcpy(cp1
, cp2
, len2
);
2025 "nmap: unbalanced brackets\n");
2031 while (*cp2
&& *cp2
!= ']') {
2032 if (*cp2
== '\\' && *(cp2
+ 1)) {
2035 if ((len2
= mblen(cp2
, MB_CUR_MAX
)) <=
2042 "nmap: unbalanced brackets\n");
2060 if (isdigit(*(cp2
+ 1))) {
2061 if (*++cp2
== '0') {
2067 } else if (toks
[toknum
= *cp2
- '1']) {
2068 char *cp3
= tp
[toknum
];
2070 while (cp3
!= te
[toknum
]) {
2077 /* intentional drop through */
2079 if ((len2
= mblen(cp2
, MB_CUR_MAX
)) <= 0)
2081 memcpy(cp1
, cp2
, len2
);
2096 setsunique(int argc
, char *argv
[])
2099 (void) printf("Store unique %s.\n", onoff(sunique
));
2105 setrunique(int argc
, char *argv
[])
2108 (void) printf("Receive unique %s.\n", onoff(runique
));
2114 setpassive(int argc
, char *argv
[])
2116 passivemode
= !passivemode
;
2117 (void) printf("Passive mode %s.\n", onoff(passivemode
));
2122 settcpwindow(int argc
, char *argv
[])
2124 int owindowsize
= tcpwindowsize
;
2127 (void) printf("usage: %s [size]\n", argv
[0]);
2136 window
= (int)strtol(argv
[1], &endp
, 10);
2137 if (errno
|| window
< 0 || *endp
!= '\0')
2138 (void) printf("%s: Invalid size `%s'\n",
2141 tcpwindowsize
= window
;
2143 if (tcpwindowsize
== 0) {
2144 if (owindowsize
== 0)
2145 (void) printf("No TCP window size defined\n");
2147 (void) printf("TCP window size cleared\n");
2149 (void) printf("TCP window size is set to %d\n", tcpwindowsize
);
2152 /* change directory to parent directory */
2155 cdup(int argc
, char *argv
[])
2157 (void) command("CDUP");
2161 macdef(int argc
, char *argv
[])
2167 (void) printf("Limit of 16 macros have already been defined\n");
2172 if (prompt_for_arg(line
, sizeof (line
), "macro name") == -1) {
2181 (void) printf("Usage: %s macro_name\n", argv
[0]);
2186 (void) printf("Enter macro line by line, terminating "
2187 "it with a null line\n");
2189 (void) strncpy(macros
[macnum
].mac_name
, argv
[1], 8);
2191 macros
[macnum
].mac_start
= macbuf
;
2193 macros
[macnum
].mac_start
= macros
[macnum
- 1].mac_end
+ 1;
2195 tmp
= macros
[macnum
].mac_start
;
2196 while (tmp
!= macbuf
+4096) {
2197 if ((c
= getchar()) == EOF
) {
2198 (void) printf("macdef:end of file encountered\n");
2202 if ((*tmp
= c
) == '\n') {
2203 if (tmp
== macros
[macnum
].mac_start
) {
2204 macros
[macnum
++].mac_end
= tmp
;
2208 if (*(tmp
-1) == '\0') {
2209 macros
[macnum
++].mac_end
= tmp
- 1;
2218 while ((c
= getchar()) != '\n' && c
!= EOF
)
2220 if (c
== EOF
|| getchar() == '\n') {
2222 "Macro not defined - 4k buffer exceeded\n");
2230 * The p_name strings are for the getlevel and setlevel commands.
2231 * The name strings for printing are in the arpa/ftp.h file in the
2232 * protnames[] array of strings.
2234 static struct levels
{
2239 { "clear", "C", PROT_C
},
2240 { "safe", "S", PROT_S
},
2241 { "private", "P", PROT_P
},
2246 * Return a pointer to a string which is the readable version of the
2247 * protection level, or NULL if the input level is not found.
2254 for (p
= levels
; (p
!= NULL
) && (p
->p_level
!= level
); p
++)
2256 return (p
? p
->p_name
: NULL
);
2259 static char *plevel
[] = {
2266 * Set control channel protection level.
2269 setclevel(int argc
, char *argv
[])
2278 (void) printf("usage: %s [", argv
[0]);
2280 for (p
= levels
; p
->p_name
; p
++) {
2281 (void) printf("%s%s", sep
, p
->p_name
);
2285 (void) printf(" ]\n");
2290 levelp
= getlevel(clevel
);
2291 (void) printf("Using %s protection level for commands.\n",
2292 levelp
? levelp
: "<unknown>");
2296 for (p
= levels
; (p
!= NULL
) && (p
->p_name
); p
++)
2297 if (strcmp(argv
[1], p
->p_name
) == 0)
2299 if (p
->p_name
== 0) {
2300 (void) printf("%s: unknown protection level\n", argv
[1]);
2304 if (auth_type
== AUTHTYPE_NONE
) {
2305 if (strcmp(p
->p_name
, "clear"))
2306 (void) printf("Cannot set protection level to %s\n",
2310 if (strcmp(p
->p_name
, "clear") == 0) {
2311 comret
= command("CCC");
2312 if (comret
== COMPLETE
)
2316 clevel
= p
->p_level
;
2317 (void) printf("Control channel protection level set to %s.\n",
2322 * Set data channel protection level.
2325 setdlevel(int argc
, char *argv
[])
2333 (void) printf("usage: %s [", argv
[0]);
2335 for (p
= levels
; p
->p_name
; p
++) {
2336 (void) printf("%s%s", sep
, p
->p_name
);
2340 (void) printf(" ]\n");
2344 for (p
= levels
; p
->p_name
; p
++)
2345 if (strcmp(argv
[1], p
->p_name
) == 0)
2347 if (p
->p_name
== 0) {
2348 (void) printf("%s: unknown protection level\n", argv
[1]);
2352 if (auth_type
== AUTHTYPE_NONE
) {
2353 if (strcmp(p
->p_name
, "clear"))
2354 (void) printf("Cannot set protection level to %s\n",
2358 /* Start with a PBSZ of 1 meg */
2359 if (p
->p_level
!= PROT_C
)
2361 comret
= command("PROT %s", p
->p_mode
);
2362 if (comret
== COMPLETE
)
2363 dlevel
= p
->p_level
;
2367 * Set clear command protection level.
2371 ccc(int argc
, char *argv
[])
2373 plevel
[1] = "clear";
2374 setclevel(2, plevel
);
2378 * Set clear data protection level.
2382 setclear(int argc
, char *argv
[])
2384 plevel
[1] = "clear";
2385 setdlevel(2, plevel
);
2389 * Set safe data protection level.
2393 setsafe(int argc
, char *argv
[])
2396 setdlevel(2, plevel
);
2400 * Set private data protection level.
2404 setprivate(int argc
, char *argv
[])
2406 plevel
[1] = "private";
2407 setdlevel(2, plevel
);
2411 * Set mechanism type
2414 setmech(int argc
, char *argv
[])
2416 char tempmech
[MECH_SZ
];
2419 if (prompt_for_arg(line
, sizeof (line
), "mech-type") == -1) {
2429 (void) printf("usage: %s [ mechanism type ]\n", argv
[0]);
2434 if ((strlcpy(tempmech
, argv
[1], MECH_SZ
) >= MECH_SZ
) ||
2435 __gss_mech_to_oid(tempmech
, (gss_OID
*)&mechoid
) !=
2437 (void) printf("%s: %s: not a valid security mechanism\n",
2442 (void) strlcpy(mechstr
, tempmech
, MECH_SZ
);
2443 (void) printf("Using %s mechanism type\n", mechstr
);