2 * Copyright (c) 1985, 1989 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 * FTP User Program -- Command Routines.
24 #include "pathnames.h"
27 static char sccsid
[] = "@(#)cmds.c 5.18 (Berkeley) 4/20/89";
32 static const char *remglob(const char *argv
[], int doswitch
);
34 extern off_t restart_point
;
35 extern char reply_string
[];
39 const char *dotrans(const char *name
);
40 const char *domap(const char *name
);
43 extern char *hostname
;
46 * Connect to peer server and
47 * auto-login, if possible.
49 void setpeer(int argc
, const char *argv
[])
54 printf("Already connected to %s, use close first.\n",
56 (void) fflush(stdout
);
61 (void) strcat(line
, " ");
63 (void) fflush(stdout
);
64 (void) gets(&line
[strlen(line
)]);
70 printf("usage: %s host-name [port]\n", argv
[0]);
71 (void) fflush(stdout
);
76 portnum
= atoi(argv
[2]);
78 printf("%s: bad port number-- %s\n", argv
[1], argv
[2]);
79 printf ("usage: %s host-name [port]\n", argv
[0]);
80 (void) fflush(stdout
);
84 portnum
= htons(portnum
);
86 host
= hookup(argv
[1], portnum
);
91 (void) login(argv
[1]);
97 if (command("SYST") == COMPLETE
&& overbose
) {
99 cp
= index(reply_string
+4, ' ');
101 cp
= index(reply_string
+4, '\r');
109 printf("Remote system type is %s.\n",
114 if (!strncmp(reply_string
, "215 UNIX Type: L8", 17)) {
116 /* allbinary = 1; this violates the RFC */
118 printf("Using %s mode to transfer files.\n",
120 } else if (overbose
&&
121 !strncmp(reply_string
, "215 TOPS20", 10)) {
123 "Remember to set tenex mode when transfering binary files from this machine.\n");
127 (void) fflush(stdout
);
136 { "ascii", "A", TYPE_A
, 0 },
137 { "binary", "I", TYPE_I
, 0 },
138 { "image", "I", TYPE_I
, 0 },
139 { "ebcdic", "E", TYPE_E
, 0 },
140 { "tenex", "L", TYPE_L
, bytename
},
147 void settype(int argc
, const char *argv
[])
149 register struct types
*p
;
155 printf("usage: %s [", argv
[0]);
157 for (p
= types
; p
->t_name
; p
++) {
158 printf("%s%s", sep
, p
->t_name
);
163 (void) fflush(stdout
);
168 printf("Using %s mode to transfer files.\n", typename
);
169 (void) fflush(stdout
);
173 for (p
= types
; p
->t_name
; p
++)
174 if (strcmp(argv
[1], p
->t_name
) == 0)
176 if (p
->t_name
== 0) {
177 printf("%s: unknown mode\n", argv
[1]);
178 (void) fflush(stdout
);
182 if ((p
->t_arg
!= NULL
) && (*(p
->t_arg
) != '\0'))
183 comret
= command ("TYPE %s %s", p
->t_mode
, p
->t_arg
);
185 comret
= command("TYPE %s", p
->t_mode
);
186 if (comret
== COMPLETE
) {
187 (void) strcpy(typename
, p
->t_name
);
192 const char *stype
[] = {
199 * Set binary transfer type.
202 void setbinary(int argc
, const char *argv
[])
209 * Set ascii transfer type.
212 void setascii(int argc
, const char *argv
[])
219 * Set tenex transfer type.
222 void settenex(int argc
, const char *argv
[])
229 * Set ebcdic transfer type.
239 * Set file transfer mode.
243 void fsetmode(int argc
, const char *argv
[])
246 printf("We only support %s mode, sorry.\n", modename
);
247 (void) fflush(stdout
);
253 * Set file transfer format.
256 void setform(int argc
, const char *argv
[])
259 printf("We only support %s format, sorry.\n", formname
);
260 (void) fflush(stdout
);
265 * Set file transfer structure.
268 void setstruct(int argc
, const char *argv
[])
271 printf("We only support %s structure, sorry.\n", structname
);
272 (void) fflush(stdout
);
277 * Send a single file.
279 void put(int argc
, const char *argv
[])
283 const char *oldargv1
, *oldargv2
;
291 (void) strcat(line
, " ");
292 printf("(local-file) ");
293 (void) fflush(stdout
);
294 (void) gets(&line
[strlen(line
)]);
301 printf("usage:%s local-file remote-file\n", argv
[0]);
302 (void) fflush(stdout
);
307 (void) strcat(line
, " ");
308 printf("(remote-file) ");
309 (void) fflush(stdout
);
310 (void) gets(&line
[strlen(line
)]);
319 if (!globulize(&argv
[1])) {
324 * If "globulize" modifies argv[1], and argv[2] is a copy of
325 * the old argv[1], make it a copy of the new argv[1].
327 if (argv
[1] != oldargv1
&& argv
[2] == oldargv1
) {
330 cmd
= (argv
[0][0] == 'a') ? "APPE" : ((sunique
) ? "STOU" : "STOR");
332 argv
[2] = dotrans(argv
[2]);
334 if (loc
&& mapflag
) {
335 argv
[2] = domap(argv
[2]);
337 sendrequest(cmd
, argv
[1], argv
[2],
338 argv
[1] != oldargv1
|| argv
[2] != oldargv2
);
342 * Send multiple files.
344 void mput(int argc
, const char *argv
[])
348 extern jmp_buf jabort
;
352 (void) strcat(line
, " ");
353 printf("(local-files) ");
354 (void) fflush(stdout
);
355 (void) gets(&line
[strlen(line
)]);
361 printf("usage:%s local-files\n", argv
[0]);
362 (void) fflush(stdout
);
368 // oldintr = signal(SIGINT, mabort);
369 (void) setjmp(jabort
);
372 char *tp2
, tmpbuf
[MAXPATHLEN
];
374 while ((cp
= remglob(argv
,0)) != NULL
) {
379 if (mflag
&& confirm(argv
[0], cp
)) {
382 while (*tp
&& !islower(*tp
)) {
388 while ((*tp2
= *tp
)) {
390 *tp2
= 'a' + *tp2
- 'A';
404 sendrequest((sunique
) ? "STOU" : "STOR",
405 cp
, tp
, cp
!= tp
|| !interactive
);
406 if (!mflag
&& fromatty
) {
407 ointer
= interactive
;
409 if (confirm("Continue with","mput")) {
412 interactive
= ointer
;
416 // (void) signal(SIGINT, oldintr);
420 for (i
= 1; i
< argc
; i
++) {
421 register char **cpp
, **gargs
;
424 if (mflag
&& confirm(argv
[0], argv
[i
])) {
425 tp
= (ntflag
) ? dotrans(argv
[i
]) : argv
[i
];
426 tp
= (mapflag
) ? domap(tp
) : tp
;
427 sendrequest((sunique
) ? "STOU" : "STOR",
428 argv
[i
], tp
, tp
!= argv
[i
] || !interactive
);
429 if (!mflag
&& fromatty
) {
430 ointer
= interactive
;
432 if (confirm("Continue with","mput")) {
435 interactive
= ointer
;
440 gargs
= glob(argv
[i
]);
441 if (globerr
!= NULL
) {
442 printf("%s\n", globerr
);
443 (void) fflush(stdout
);
450 for (cpp
= gargs
; cpp
&& *cpp
!= NULL
; cpp
++) {
451 if (mflag
&& confirm(argv
[0], *cpp
)) {
452 tp
= (ntflag
) ? dotrans(*cpp
) : *cpp
;
453 tp
= (mapflag
) ? domap(tp
) : tp
;
454 sendrequest((sunique
) ? "STOU" : "STOR",
455 *cpp
, tp
, *cpp
!= tp
|| !interactive
);
456 if (!mflag
&& fromatty
) {
457 ointer
= interactive
;
459 if (confirm("Continue with","mput")) {
462 interactive
= ointer
;
471 // (void) signal(SIGINT, oldintr);
475 void reget(int argc
, const char *argv
[])
477 (void) getit(argc
, argv
, 1, "r+w");
480 void get(int argc
, const char *argv
[])
482 (void) getit(argc
, argv
, 0, restart_point
? "r+w" : "w" );
488 int getit(int argc
, const char *argv
[], int restartit
, const char *mode
)
491 const char *oldargv1
, *oldargv2
;
499 (void) strcat(line
, " ");
500 printf("(remote-file) ");
501 (void) fflush(stdout
);
502 (void) gets(&line
[strlen(line
)]);
509 printf("usage: %s remote-file [ local-file ]\n", argv
[0]);
510 (void) fflush(stdout
);
515 (void) strcat(line
, " ");
516 printf("(local-file) ");
517 (void) fflush(stdout
);
518 (void) gets(&line
[strlen(line
)]);
527 if (!globulize(&argv
[2])) {
532 const char *tp
= argv
[1];
533 char *tp2
, tmpbuf
[MAXPATHLEN
];
535 while (*tp
&& !islower(*tp
)) {
541 while ((*tp2
= *tp
)) {
543 *tp2
= 'a' + *tp2
- 'A';
552 argv
[2] = dotrans(argv
[2]);
554 argv
[2] = domap(argv
[2]);
559 ret
= stat(argv
[2], &stbuf
);
560 if (restartit
== 1) {
565 restart_point
= stbuf
.st_size
;
573 if (command("MDTM %s", argv
[1]) == COMPLETE
) {
574 int yy
, mo
, day
, hour
, min
, sec
;
578 "%*s %04d%02d%02d%02d%02d%02d",
579 &yy
, &mo
, &day
, &hour
, &min
, &sec
);
580 tm
= gmtime(&stbuf
.st_mtime
);
582 if (tm
->tm_year
> yy
%100)
584 else if (tm
->tm_year
== yy
%100) {
587 } else if (tm
->tm_mon
== mo
) {
588 if (tm
->tm_mday
> day
)
590 } else if (tm
->tm_mday
== day
) {
591 if (tm
->tm_hour
> hour
)
593 } else if (tm
->tm_hour
== hour
) {
594 if (tm
->tm_min
> min
)
596 } else if (tm
->tm_min
== min
) {
597 if (tm
->tm_sec
> sec
)
601 printf("%s\n", reply_string
);
602 (void) fflush(stdout
);
610 recvrequest("RETR", argv
[2], argv
[1], mode
,
611 argv
[1] != oldargv1
|| argv
[2] != oldargv2
);
621 extern jmp_buf jabort
;
624 (void) fflush(stdout
);
625 if (mflag
&& fromatty
) {
626 ointer
= interactive
;
628 if (confirm("Continue with", mname
)) {
629 interactive
= ointer
;
632 interactive
= ointer
;
640 * Get multiple files.
642 void mget(int argc
, const char *argv
[])
645 char *tp2
, tmpbuf
[MAXPATHLEN
];
647 extern jmp_buf jabort
;
650 (void) strcat(line
, " ");
651 printf("(remote-files) ");
652 (void) fflush(stdout
);
653 (void) gets(&line
[strlen(line
)]);
659 printf("usage:%s remote-files\n", argv
[0]);
660 (void) fflush(stdout
);
666 // oldintr = signal(SIGINT,mabort);
667 (void) setjmp(jabort
);
668 while ((cp
= remglob(argv
,proxy
)) != NULL
) {
673 if (mflag
&& confirm(argv
[0], cp
)) {
676 while (*tp
&& !islower(*tp
)) {
682 while ((*tp2
= *tp
)) {
684 *tp2
= 'a' + *tp2
- 'A';
698 recvrequest("RETR", tp
, cp
, "w",
699 tp
!= cp
|| !interactive
);
700 if (!mflag
&& fromatty
) {
701 ointer
= interactive
;
703 if (confirm("Continue with","mget")) {
706 interactive
= ointer
;
710 // (void) signal(SIGINT,oldintr);
715 remglob(const char *argv
[], int doswitch
)
718 static char buf
[MAXPATHLEN
];
719 static FILE *ftemp
= NULL
;
720 static const char **args
;
721 int oldverbose
, oldhash
;
732 (void) fclose(ftemp
);
741 if ((cp
= *++args
) == NULL
)
746 (void) strcpy(temp
, _PATH_TMP
);
748 oldverbose
= verbose
, verbose
= 0;
749 oldhash
= hash
, hash
= 0;
753 for (mode
= "w"; *++argv
!= NULL
; mode
= "a")
754 recvrequest ("NLST", temp
, *argv
, mode
, 0);
758 verbose
= oldverbose
; hash
= oldhash
;
759 ftemp
= fopen(temp
, "r");
762 printf("can't find list of remote files, oops\n");
763 (void) fflush(stdout
);
767 if (fgets(buf
, sizeof (buf
), ftemp
) == NULL
) {
768 (void) fclose(ftemp
), ftemp
= NULL
;
771 if ((terminator
= index(buf
, '\n')) != NULL
)
779 return (bool ? "on" : "off");
786 void status(int argc
, const char *argv
[])
791 printf("Connected to %s.\n", hostname
);
793 printf("Not connected.\n");
797 printf("Connected for proxy commands to %s.\n", hostname
);
800 printf("No proxy connection.\n");
804 printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
805 modename
, typename
, formname
, structname
);
806 printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
807 onoff(verbose
), onoff(bell
), onoff(interactive
),
809 printf("Store unique: %s; Receive unique: %s\n", onoff(sunique
),
811 printf("Case: %s; CR stripping: %s\n",onoff(mcase
),onoff(crflag
));
813 printf("Ntrans: (in) %s (out) %s\n", ntin
,ntout
);
816 printf("Ntrans: off\n");
819 printf("Nmap: (in) %s (out) %s\n", mapin
, mapout
);
822 printf("Nmap: off\n");
824 printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
825 onoff(hash
), onoff(sendport
));
828 for (i
=0; i
<macnum
; i
++) {
829 printf("\t%s\n",macros
[i
].mac_name
);
832 (void) fflush(stdout
);
837 * Set beep on cmd completed mode.
840 void setbell(int argc
, const char *argv
[])
844 printf("Bell mode %s.\n", onoff(bell
));
845 (void) fflush(stdout
);
850 * Turn on packet tracing.
853 void settrace(int argc
, const char *argv
[])
857 printf("Packet tracing %s.\n", onoff(trace
));
858 (void) fflush(stdout
);
863 * Toggle hash mark printing during transfers.
866 void sethash(int argc
, const char *argv
[])
870 printf("Hash mark printing %s", onoff(hash
));
873 printf(" (%d bytes/hash mark)", 1024);
875 (void) fflush(stdout
);
879 * Turn on printing of server echo's.
882 void setverbose(int argc
, const char *argv
[])
886 printf("Verbose mode %s.\n", onoff(verbose
));
887 (void) fflush(stdout
);
892 * Toggle PORT cmd use before each data connection.
895 void setport(int argc
, const char *argv
[])
898 sendport
= !sendport
;
899 printf("Use of PORT cmds %s.\n", onoff(sendport
));
900 (void) fflush(stdout
);
905 * Turn on interactive prompting
906 * during mget, mput, and mdelete.
909 void setprompt(int argc
, const char *argv
[])
912 interactive
= !interactive
;
913 printf("Interactive mode %s.\n", onoff(interactive
));
914 (void) fflush(stdout
);
919 * Toggle metacharacter interpretation
920 * on local file names.
923 void setglob(int argc
, const char *argv
[])
927 printf("Globbing %s.\n", onoff(doglob
));
928 (void) fflush(stdout
);
933 * Set debugging mode on/off and/or
934 * set level of debugging.
937 void setdebug(int argc
, const char *argv
[])
944 printf("%s: bad debugging value.\n", argv
[1]);
945 (void) fflush(stdout
);
955 options
&= ~SO_DEBUG
;
956 printf("Debugging %s (debug=%d).\n", onoff(debug
), debug
);
957 (void) fflush(stdout
);
962 * Set current working directory
965 void cd(int argc
, const char *argv
[])
969 (void) strcat(line
, " ");
970 printf("(remote-directory) ");
971 (void) fflush(stdout
);
972 (void) gets(&line
[strlen(line
)]);
978 printf("usage:%s remote-directory\n", argv
[0]);
979 (void) fflush(stdout
);
983 if (command("CWD %s", argv
[1]) == ERROR
&& code
== 500) {
985 printf("CWD command not recognized, trying XCWD\n");
986 (void) fflush(stdout
);
988 (void) command("XCWD %s", argv
[1]);
993 * Set current working directory
996 void lcd(int argc
, const char *argv
[])
998 char buf
[MAXPATHLEN
];
1001 argc
++, argv
[1] = home
;
1003 printf("usage:%s local-directory\n", argv
[0]);
1004 (void) fflush(stdout
);
1008 if (!globulize(&argv
[1])) {
1012 if (chdir(argv
[1]) < 0) {
1017 printf("Local directory now %s\n", getcwd(buf
,sizeof(buf
)));
1018 (void) fflush(stdout
);
1023 * Delete a single file.
1025 void delete(int argc
, const char *argv
[])
1029 (void) strcat(line
, " ");
1030 printf("(remote-file) ");
1031 (void) fflush(stdout
);
1032 (void) gets(&line
[strlen(line
)]);
1038 printf("usage:%s remote-file\n", argv
[0]);
1039 (void) fflush(stdout
);
1043 (void) command("DELE %s", argv
[1]);
1047 * Delete multiple files.
1049 void mdelete(int argc
, const char *argv
[])
1053 extern jmp_buf jabort
;
1056 (void) strcat(line
, " ");
1057 printf("(remote-files) ");
1058 (void) fflush(stdout
);
1059 (void) gets(&line
[strlen(line
)]);
1065 printf("usage:%s remote-files\n", argv
[0]);
1066 (void) fflush(stdout
);
1072 // oldintr = signal(SIGINT, mabort);
1073 (void) setjmp(jabort
);
1074 while ((cp
= remglob(argv
,0)) != NULL
) {
1079 if (mflag
&& confirm(argv
[0], cp
)) {
1080 (void) command("DELE %s", cp
);
1081 if (!mflag
&& fromatty
) {
1082 ointer
= interactive
;
1084 if (confirm("Continue with", "mdelete")) {
1087 interactive
= ointer
;
1091 // (void) signal(SIGINT, oldintr);
1096 * Rename a remote file.
1098 void renamefile(int argc
, const char *argv
[])
1102 (void) strcat(line
, " ");
1103 printf("(from-name) ");
1104 (void) fflush(stdout
);
1105 (void) gets(&line
[strlen(line
)]);
1112 printf("%s from-name to-name\n", argv
[0]);
1113 (void) fflush(stdout
);
1118 (void) strcat(line
, " ");
1119 printf("(to-name) ");
1120 (void) fflush(stdout
);
1121 (void) gets(&line
[strlen(line
)]);
1128 if (command("RNFR %s", argv
[1]) == CONTINUE
)
1129 (void) command("RNTO %s", argv
[2]);
1133 * Get a directory listing
1136 void ls(int argc
, const char *argv
[])
1141 argc
++, argv
[1] = NULL
;
1143 argc
++, argv
[2] = "-";
1145 printf("usage: %s remote-directory local-file\n", argv
[0]);
1146 (void) fflush(stdout
);
1150 cmd
= argv
[0][0] == 'n' ? "NLST" : "LIST";
1151 // cmd = argv[0][0] == 'n' ? "NLST -CF" : "NLST -CF";
1152 if (strcmp(argv
[2], "-") && !globulize(&argv
[2])) {
1156 if (strcmp(argv
[2], "-") && *argv
[2] != '|')
1157 if (!globulize(&argv
[2]) || !confirm("output to local-file:", argv
[2])) {
1161 recvrequest(cmd
, argv
[2], argv
[1], "w", 0);
1165 * Get a directory listing
1166 * of multiple remote files.
1168 void mls(int argc
, const char *argv
[])
1170 const char *cmd
, *dest
;
1173 extern jmp_buf jabort
;
1176 (void) strcat(line
, " ");
1177 printf("(remote-files) ");
1178 (void) fflush(stdout
);
1179 (void) gets(&line
[strlen(line
)]);
1185 (void) strcat(line
, " ");
1186 printf("(local-file) ");
1187 (void) fflush(stdout
);
1188 (void) gets(&line
[strlen(line
)]);
1194 printf("usage:%s remote-files local-file\n", argv
[0]);
1195 (void) fflush(stdout
);
1199 dest
= argv
[argc
- 1];
1200 argv
[argc
- 1] = NULL
;
1201 if (strcmp(dest
, "-") && *dest
!= '|')
1202 if (!globulize(&dest
) || !confirm("output to local-file:", dest
)) {
1206 cmd
= argv
[0][1] == 'l' ? "NLST" : "LIST";
1209 // oldintr = signal(SIGINT, mabort);
1210 (void) setjmp(jabort
);
1211 for (i
= 1; mflag
&& i
< argc
-1; ++i
) {
1212 *mode
= (i
== 1) ? 'w' : 'a';
1213 recvrequest(cmd
, dest
, argv
[i
], mode
, 0);
1214 if (!mflag
&& fromatty
) {
1215 ointer
= interactive
;
1217 if (confirm("Continue with", argv
[0])) {
1220 interactive
= ointer
;
1223 // (void) signal(SIGINT, oldintr);
1231 void shell(int argc
, const char *argv
[])
1235 sig_t (*old1
)(), (*old2
)();
1236 char shellnam
[40], *shell
, *namep
;
1239 old1
= signal (SIGINT
, SIG_IGN
);
1240 old2
= signal (SIGQUIT
, SIG_IGN
);
1241 if ((pid
= fork()) == 0) {
1242 for (pid
= 3; pid
< 20; pid
++)
1244 (void) signal(SIGINT
, SIG_DFL
);
1245 (void) signal(SIGQUIT
, SIG_DFL
);
1246 shell
= getenv("SHELL");
1248 shell
= _PATH_BSHELL
;
1249 namep
= rindex(shell
,'/');
1252 (void) strcpy(shellnam
,"-");
1253 (void) strcat(shellnam
, ++namep
);
1254 if (strcmp(namep
, "sh") != 0)
1257 printf ("%s\n", shell
);
1258 (void) fflush (stdout
);
1261 execl(shell
,shellnam
,"-c",altarg
,(char *)0);
1264 execl(shell
,shellnam
,(char *)0);
1271 while (wait(&status
) != pid
)
1273 (void) signal(SIGINT
, old1
);
1274 (void) signal(SIGQUIT
, old2
);
1276 perror("Try again later");
1285 char ShellCmd
[MAX_PATH
];
1286 char CmdLine
[MAX_PATH
];
1288 PROCESS_INFORMATION ProcessInformation
;
1290 STARTUPINFO StartupInfo
;
1291 char ShellName
[] = "COMSPEC";
1294 NumBytes
= GetEnvironmentVariable( ShellName
, ShellCmd
, MAX_PATH
);
1302 strcpy( CmdLine
, ShellCmd
);
1306 strncat(CmdLine
, " /C", MAX_PATH
- strlen(CmdLine
) - 1);
1309 for (i
=1; i
<argc
; i
++)
1311 strncat(CmdLine
, " ", MAX_PATH
- strlen(CmdLine
) - 1);
1312 strncat(CmdLine
, argv
[i
], MAX_PATH
- strlen(CmdLine
) - 1);
1315 StartupInfo
.cb
= sizeof( StartupInfo
);
1316 StartupInfo
.lpReserved
= NULL
;
1317 StartupInfo
.lpDesktop
= NULL
;
1318 StartupInfo
.lpTitle
= NULL
;
1319 StartupInfo
.dwX
= 0;
1320 StartupInfo
.dwY
= 0;
1321 StartupInfo
.dwXSize
= 0;
1322 StartupInfo
.dwYSize
= 0;
1323 StartupInfo
.dwFlags
= 0;
1324 StartupInfo
.wShowWindow
= 0;
1325 StartupInfo
.cbReserved2
= 0;
1326 StartupInfo
.lpReserved2
= NULL
;
1328 Result
= CreateProcess( AppName
, // cmd name
1329 CmdLine
, // cmd line arguments
1331 NULL
, // security attributes
1332 FALSE
, // inherit flags
1333 0, // Creation flags
1334 NULL
, // Environment
1335 NULL
, // Current directory
1336 &StartupInfo
, // Startup info structure
1337 &ProcessInformation
); // processInfo structure
1341 WaitForSingleObject( ProcessInformation
.hProcess
, 0xffffffff);
1343 CloseHandle( ProcessInformation
.hProcess
);
1348 * Send new user information (re-login)
1350 void user(int argc
, const char *argv
[])
1352 char acct
[80], *getpass();
1356 (void) strcat(line
, " ");
1357 printf("(username) ");
1358 (void) fflush(stdout
);
1359 (void) gets(&line
[strlen(line
)]);
1365 printf("usage: %s username [password] [account]\n", argv
[0]);
1366 (void) fflush(stdout
);
1370 n
= command("USER %s", argv
[1]);
1371 if (n
== CONTINUE
) {
1373 argv
[2] = getpass("Password: "), argc
++;
1374 n
= command("PASS %s", argv
[2]);
1376 if (n
== CONTINUE
) {
1378 printf("Account: "); (void) fflush(stdout
);
1379 (void) fflush(stdout
);
1380 (void) fgets(acct
, sizeof(acct
) - 1, stdin
);
1381 acct
[strlen(acct
) - 1] = '\0';
1382 argv
[3] = acct
; argc
++;
1384 n
= command("ACCT %s", argv
[3]);
1387 if (n
!= COMPLETE
) {
1388 fprintf(stdout
, "Login failed.\n");
1389 (void) fflush(stdout
);
1392 if (!aflag
&& argc
== 4) {
1393 (void) command("ACCT %s", argv
[3]);
1398 * Print working directory.
1401 void pwd(int argc
, const char *argv
[])
1403 int oldverbose
= verbose
;
1406 * If we aren't verbose, this doesn't do anything!
1409 if (command("PWD") == ERROR
&& code
== 500) {
1410 printf("PWD command not recognized, trying XPWD\n");
1411 (void) fflush(stdout
);
1412 (void) command("XPWD");
1414 verbose
= oldverbose
;
1420 void makedir(int argc
, const char *argv
[])
1424 (void) strcat(line
, " ");
1425 printf("(directory-name) ");
1426 (void) fflush(stdout
);
1427 (void) gets(&line
[strlen(line
)]);
1433 printf("usage: %s directory-name\n", argv
[0]);
1434 (void) fflush(stdout
);
1438 if (command("MKD %s", argv
[1]) == ERROR
&& code
== 500) {
1440 printf("MKD command not recognized, trying XMKD\n");
1441 (void) fflush(stdout
);
1443 (void) command("XMKD %s", argv
[1]);
1448 * Remove a directory.
1450 void removedir(int argc
, const char *argv
[])
1454 (void) strcat(line
, " ");
1455 printf("(directory-name) ");
1456 (void) fflush(stdout
);
1457 (void) gets(&line
[strlen(line
)]);
1463 printf("usage: %s directory-name\n", argv
[0]);
1464 (void) fflush(stdout
);
1468 if (command("RMD %s", argv
[1]) == ERROR
&& code
== 500) {
1470 printf("RMD command not recognized, trying XRMD\n");
1471 (void) fflush(stdout
);
1473 (void) command("XRMD %s", argv
[1]);
1478 * Send a line, verbatim, to the remote machine.
1480 void quote(int argc
, const char *argv
[])
1486 (void) strcat(line
, " ");
1487 printf("(command line to send) ");
1488 (void) fflush(stdout
);
1489 (void) gets(&line
[strlen(line
)]);
1495 printf("usage: %s line-to-send\n", argv
[0]);
1496 (void) fflush(stdout
);
1500 (void) strcpy(buf
, argv
[1]);
1501 for (i
= 2; i
< argc
; i
++) {
1502 (void) strcat(buf
, " ");
1503 (void) strcat(buf
, argv
[i
]);
1505 if (command(buf
) == PRELIM
) {
1506 while (getreply(0) == PRELIM
);
1511 * Send a SITE command to the remote machine. The line
1512 * is sent almost verbatim to the remote machine, the
1513 * first argument is changed to SITE.
1515 void site(int argc
, const char *argv
[])
1521 (void) strcat(line
, " ");
1522 printf("(arguments to SITE command) ");
1523 (void) fflush(stdout
);
1524 (void) gets(&line
[strlen(line
)]);
1530 printf("usage: %s line-to-send\n", argv
[0]);
1531 (void) fflush(stdout
);
1535 (void) strcpy(buf
, "SITE ");
1536 (void) strcat(buf
, argv
[1]);
1537 for (i
= 2; i
< argc
; i
++) {
1538 (void) strcat(buf
, " ");
1539 (void) strcat(buf
, argv
[i
]);
1541 if (command(buf
) == PRELIM
) {
1542 while (getreply(0) == PRELIM
);
1546 void do_chmod(int argc
, const char *argv
[])
1549 printf("usage: %s mode file-name\n", argv
[0]);
1550 (void) fflush(stdout
);
1555 (void) strcat(line
, " ");
1556 printf("(mode and file-name) ");
1557 (void) fflush(stdout
);
1558 (void) gets(&line
[strlen(line
)]);
1564 printf("usage: %s mode file-name\n", argv
[0]);
1565 (void) fflush(stdout
);
1569 (void)command("SITE CHMOD %s %s", argv
[1], argv
[2]);
1572 void do_umask(int argc
, const char *argv
[])
1574 int oldverbose
= verbose
;
1577 (void) command(argc
== 1 ? "SITE UMASK" : "SITE UMASK %s", argv
[1]);
1578 verbose
= oldverbose
;
1581 void idle(int argc
, const char *argv
[])
1583 int oldverbose
= verbose
;
1586 (void) command(argc
== 1 ? "SITE IDLE" : "SITE IDLE %s", argv
[1]);
1587 verbose
= oldverbose
;
1591 * Ask the other side for help.
1593 void rmthelp(int argc
, const char *argv
[])
1595 int oldverbose
= verbose
;
1598 (void) command(argc
== 1 ? "HELP" : "HELP %s", argv
[1]);
1599 verbose
= oldverbose
;
1603 * Terminate session and exit.
1606 void quit(int argc
, const char *argv
[])
1609 disconnect(0, NULL
);
1612 disconnect(0, NULL
);
1618 * Terminate session, but don't exit.
1620 void disconnect(int argc
, const char *argv
[])
1627 (void) command("QUIT");
1636 int confirm(const char *cmd
, const char *file
)
1642 printf("%s %s? ", cmd
, file
);
1643 (void) fflush(stdout
);
1645 return (*line
!= 'n' && *line
!= 'N');
1649 static void fatal(const char *msg
)
1652 fprintf(stderr
, "ftp: %s\n", msg
);
1658 * Glob a local file name specification with
1659 * the expectation of a single return value.
1660 * Can't control multiple values being expanded
1661 * from the expression, we return only the first.
1663 int globulize(const char **cpp
)
1669 globbed
= glob(*cpp
);
1670 if (globerr
!= NULL
) {
1671 printf("%s: %s\n", *cpp
, globerr
);
1672 (void) fflush(stdout
);
1675 free((char *)globbed
);
1681 /* don't waste too much memory */
1684 free((char *)globbed
);
1690 void account(int argc
, const char *argv
[])
1692 char acct
[50], *getpass(), *ap
;
1697 (void) strncpy(acct
,*argv
,49);
1702 (void) strncat(acct
,*argv
, 49-strlen(acct
));
1707 ap
= getpass("Account:");
1709 (void) command("ACCT %s", ap
);
1730 longjmp(abortprox
,1);
1734 void doproxy(int argc
, const char *argv
[])
1736 register struct cmd
*c
;
1737 struct cmd
*getcmd();
1738 // extern struct cmd cmdtab[];
1739 extern jmp_buf abortprox
;
1742 (void) strcat(line
, " ");
1743 printf("(command) ");
1744 (void) fflush(stdout
);
1745 (void) gets(&line
[strlen(line
)]);
1751 printf("usage:%s command\n", argv
[0]);
1752 (void) fflush(stdout
);
1756 c
= getcmd(argv
[1]);
1757 if (c
== (struct cmd
*) -1) {
1758 printf("?Ambiguous command\n");
1759 (void) fflush(stdout
);
1764 printf("?Invalid command\n");
1765 (void) fflush(stdout
);
1770 printf("?Invalid proxy command\n");
1771 (void) fflush(stdout
);
1775 if (setjmp(abortprox
)) {
1779 // oldintr = signal(SIGINT, proxabort);
1781 if (c
->c_conn
&& !connected
) {
1782 printf("Not connected\n");
1783 (void) fflush(stdout
);
1785 // (void) signal(SIGINT, oldintr);
1789 (*c
->c_handler
)(argc
-1, argv
+1);
1797 // (void) signal(SIGINT, oldintr);
1800 void setcase(int argc
, const char *argv
[])
1803 printf("Case mapping %s.\n", onoff(mcase
));
1804 (void) fflush(stdout
);
1808 void setcr(int argc
, const char *argv
[])
1811 printf("Carriage Return stripping %s.\n", onoff(crflag
));
1812 (void) fflush(stdout
);
1816 void setntrans(int argc
, const char *argv
[])
1820 printf("Ntrans off.\n");
1821 (void) fflush(stdout
);
1827 (void) strncpy(ntin
, argv
[1], 16);
1833 (void) strncpy(ntout
, argv
[2], 16);
1838 dotrans(const char *name
)
1840 static char new[MAXPATHLEN
];
1843 register int i
, ostop
, found
;
1845 for (ostop
= 0; ostop
< 16 && *(ntout
+ ostop
); ostop
++);
1846 for (cp1
= name
; *cp1
; cp1
++) {
1848 for (i
= 0; i
< 16 && *(ntin
+ i
); i
++) {
1849 if (*cp1
== *(ntin
+ i
)) {
1852 *cp2
++ = *(ntout
+ i
);
1865 void setpassive(int argc
, const char *argv
[])
1867 passivemode
= !passivemode
;
1868 printf("Passive mode %s.\n", onoff(passivemode
));
1869 (void) fflush(stdout
);
1873 void setnmap(int argc
, const char *argv
[])
1879 printf("Nmap off.\n");
1880 (void) fflush(stdout
);
1885 (void) strcat(line
, " ");
1886 printf("(mapout) ");
1887 (void) fflush(stdout
);
1888 (void) gets(&line
[strlen(line
)]);
1894 printf("Usage: %s [mapin mapout]\n",argv
[0]);
1895 (void) fflush(stdout
);
1901 cp
= index(altarg
, ' ');
1903 while(*++cp
== ' ');
1905 cp
= index(altarg
, ' ');
1908 (void) strncpy(mapin
, altarg
, MAXPATHLEN
- 1);
1909 while (*++cp
== ' ');
1910 (void) strncpy(mapout
, cp
, MAXPATHLEN
- 1);
1914 domap(const char *name
)
1916 static char new[MAXPATHLEN
];
1917 const char *cp1
= name
;
1918 char *cpn
, *cp2
= mapin
;
1919 const char *tp
[9], *te
[9];
1920 int i
, toks
[9], toknum
= 0, match
= 1;
1922 for (i
=0; i
< 9; ++i
) {
1925 while (match
&& *cp1
&& *cp2
) {
1928 if (*++cp2
!= *cp1
) {
1933 if (*(cp2
+1) >= '1' && (*cp2
+1) <= '9') {
1934 if (*cp1
!= *(++cp2
+1)) {
1935 toks
[toknum
= *cp2
- '1']++;
1937 while (*++cp1
&& *(cp2
+1)
1951 if (match
&& *cp1
) {
1954 if (match
&& *cp2
) {
1958 if (!match
&& *cp1
) /* last token mismatch */
1976 if (*++cp2
== '$' && isdigit(*(cp2
+1))) {
1977 if (*++cp2
== '0') {
1978 const char *cp3
= name
;
1985 else if (toks
[toknum
= *cp2
- '1']) {
1986 const char *cp3
= tp
[toknum
];
1988 while (cp3
!= te
[toknum
]) {
1995 while (*cp2
&& *cp2
!= ',' &&
2000 else if (*cp2
== '$' &&
2001 isdigit(*(cp2
+1))) {
2002 if (*++cp2
== '0') {
2003 const char *cp3
= name
;
2009 else if (toks
[toknum
=
2011 const char *cp3
=tp
[toknum
];
2024 printf("nmap: unbalanced brackets\n");
2025 (void) fflush(stdout
);
2032 while (*++cp2
&& *cp2
!= ']') {
2033 if (*cp2
== '\\' && *(cp2
+ 1)) {
2038 printf("nmap: unbalanced brackets\n");
2039 (void) fflush(stdout
);
2055 if (isdigit(*(cp2
+ 1))) {
2056 if (*++cp2
== '0') {
2057 const char *cp3
= name
;
2063 else if (toks
[toknum
= *cp2
- '1']) {
2064 const char *cp3
= tp
[toknum
];
2066 while (cp3
!= te
[toknum
]) {
2072 /* intentional drop through */
2086 void setsunique(int argc
, const char *argv
[])
2089 printf("Store unique %s.\n", onoff(sunique
));
2090 (void) fflush(stdout
);
2094 void setrunique(int argc
, const char *argv
[])
2097 printf("Receive unique %s.\n", onoff(runique
));
2098 (void) fflush(stdout
);
2102 /* change directory to parent directory */
2103 void cdup(int argc
, const char *argv
[])
2105 if (command("CDUP") == ERROR
&& code
== 500) {
2107 printf("CDUP command not recognized, trying XCUP\n");
2108 (void) fflush(stdout
);
2110 (void) command("XCUP");
2114 /* restart transfer at specific point */
2115 void restart(int argc
, const char *argv
[])
2118 printf("restart: offset not specified\n");
2120 restart_point
= atol(argv
[1]);
2121 printf("restarting at %ld. %s\n", restart_point
,
2122 "execute get, put or append to initiate transfer");
2124 (void) fflush(stdout
);
2127 /* show remote system type */
2128 void syst(int argc
, const char *argv
[])
2130 (void) command("SYST");
2133 void macdef(int argc
, const char *argv
[])
2139 printf("Limit of 16 macros have already been defined\n");
2140 (void) fflush(stdout
);
2145 (void) strcat(line
, " ");
2146 printf("(macro name) ");
2147 (void) fflush(stdout
);
2148 (void) gets(&line
[strlen(line
)]);
2154 printf("Usage: %s macro_name\n",argv
[0]);
2155 (void) fflush(stdout
);
2160 printf("Enter macro line by line, terminating it with a null line\n");
2161 (void) fflush(stdout
);
2163 (void) strncpy(macros
[macnum
].mac_name
, argv
[1], 8);
2165 macros
[macnum
].mac_start
= macbuf
;
2168 macros
[macnum
].mac_start
= macros
[macnum
- 1].mac_end
+ 1;
2170 tmp
= macros
[macnum
].mac_start
;
2171 while (tmp
!= macbuf
+4096) {
2172 if ((c
= getchar()) == EOF
) {
2173 printf("macdef:end of file encountered\n");
2174 (void) fflush(stdout
);
2178 if ((*tmp
= c
) == '\n') {
2179 if (tmp
== macros
[macnum
].mac_start
) {
2180 macros
[macnum
++].mac_end
= tmp
;
2184 if (*(tmp
-1) == '\0') {
2185 macros
[macnum
++].mac_end
= tmp
- 1;
2194 while ((c
= getchar()) != '\n' && c
!= EOF
)
2196 if (c
== EOF
|| getchar() == '\n') {
2197 printf("Macro not defined - 4k buffer exceeded\n");
2198 (void) fflush(stdout
);
2206 * get size of file on remote machine
2208 void sizecmd(int argc
, const char *argv
[])
2212 (void) strcat(line
, " ");
2213 printf("(filename) ");
2214 (void) fflush(stdout
);
2215 (void) gets(&line
[strlen(line
)]);
2221 printf("usage:%s filename\n", argv
[0]);
2222 (void) fflush(stdout
);
2226 (void) command("SIZE %s", argv
[1]);
2230 * get last modification time of file on remote machine
2232 void modtime(int argc
, const char *argv
[])
2237 (void) strcat(line
, " ");
2238 printf("(filename) ");
2239 (void) fflush(stdout
);
2240 (void) gets(&line
[strlen(line
)]);
2246 printf("usage:%s filename\n", argv
[0]);
2247 (void) fflush(stdout
);
2254 if (command("MDTM %s", argv
[1]) == COMPLETE
) {
2255 int yy
, mo
, day
, hour
, min
, sec
;
2256 sscanf(reply_string
, "%*s %04d%02d%02d%02d%02d%02d", &yy
, &mo
,
2257 &day
, &hour
, &min
, &sec
);
2258 /* might want to print this in local time */
2259 printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv
[1],
2260 mo
, day
, yy
, hour
, min
, sec
);
2262 printf("%s\n", reply_string
);
2264 (void) fflush(stdout
);
2268 * show status on remote machine
2270 void rmtstatus(int argc
, const char *argv
[])
2272 (void) command(argc
> 1 ? "STAT %s" : "STAT" , argv
[1]);
2276 * get file if modtime is more recent than current file
2278 void newer(int argc
, const char *argv
[])
2280 if (getit(argc
, argv
, -1, "w")) {
2281 printf("Local file \"%s\" is newer than remote file \"%s\"\n",
2283 (void) fflush(stdout
);