ReactOS 0.4.15-dev-7705-g2320c37
cmds.c
Go to the documentation of this file.
1/* cmds.c
2 *
3 * Copyright (c) 1992-2001 by Mike Gleason.
4 * All rights reserved.
5 *
6 */
7
8#include "syshdrs.h"
9#include "shell.h"
10#include "util.h"
11#include "ls.h"
12#include "bookmark.h"
13#include "cmds.h"
14#include "main.h"
15#include "trace.h"
16#include "log.h"
17#include "pref.h"
18#include "spool.h"
19#include "getline.h"
20#include "readln.h"
21#include "getopt.h"
22
23/* This was the directory path when the user logged in. For anonymous users,
24 * this should be "/", but for real users, it should be their home directory.
25 * This variable is used later when we want to calculate a relative path
26 * from the starting directory.
27 */
28char gStartDir[512];
29
30/* The pathname to the current working directory. This always needs to be
31 * current, so whenever a directory change is done this should be changed.
32 */
33char gRemoteCWD[512];
34
35/* Same, but the previous directory the user was in, or empty string if
36 * there is none.
37 */
39
40/* Another buffer we use just temporarily when switching directories. */
41char gScratchCWD[512];
42
43/* The only reason we do this is to get gcc/lint to shut up
44 * about unused parameters.
45 */
47#define ARGSUSED(x) x = (argc != 0) || (argv != 0) || (cmdp != 0) || (aip != 0)
48
49/* Used temporarily, but put it here because it's big. */
51
52/* If the user doesn't want to be prompted for a batch of files,
53 * they can tell us to answer this answer for each item in the batch.
54 */
56
57extern FTPLibraryInfo gLib;
59extern char gOurDirectoryPath[];
60extern Command gCommands[];
61extern char gVersion[];
62extern size_t gNumCommands;
64extern char *gOptArg;
65extern int gOptInd, gGotSig;
66extern int gFirstTimeUser;
67extern unsigned int gFirewallPort;
68extern int gFirewallType;
69extern char gFirewallHost[64];
70extern char gFirewallUser[32];
71extern char gFirewallPass[32];
72extern char gFirewallExceptionList[];
73extern char gPager[], gHome[], gShell[];
74extern char gOS[];
77extern Bookmark gBm;
80extern int gMayCancelJmp;
81#if defined(WIN32) || defined(_WINDOWS)
82#elif defined(HAVE_SIGSETJMP)
84#else /* HAVE_SIGSETJMP */
85extern jmp_buf gCancelJmp;
86#endif /* HAVE_SIGSETJMP */
87
88
89
90
91/* Open the users $PAGER, or just return stdout. Make sure to use
92 * ClosePager(), and not fclose/pclose directly.
93 */
94static FILE *
96{
97 FILE *fp;
98 char *pprog;
99
100 (void) fflush(stdout);
101 pprog = gPager;
102 fp = popen((pprog[0] == '\0') ? "more" : pprog, "w");
103 if (fp == NULL)
104 return (stdout);
105 return (fp);
106} /* OpenPager */
107
108
109
110
111/* Close (maybe) a file previously created by OpenPager. */
112static void
114{
115#ifdef SIGPIPE
116 sigproc_t osigpipe;
117#endif
118
119 if ((pagerfp != NULL) && (pagerfp != stdout)) {
120#ifdef SIGPIPE
121 osigpipe = (sigproc_t) NcSignal(SIGPIPE, SIG_IGN);
122#endif
123 (void) pclose(pagerfp);
124#ifdef SIGPIPE
125 (void) NcSignal(SIGPIPE, osigpipe);
126#endif
127 }
128} /* ClosePager */
129
130
131
132
133/* Fills in the bookmarkName field of the Bookmark. */
134int
136{
137 char dfltname[64];
138 char bmname[64];
139
140 DefaultBookmarkName(dfltname, sizeof(dfltname), gConn.host);
141 if (dfltname[0] == '\0') {
142 (void) printf("Enter a name for this bookmark: ");
143 } else {
144 (void) printf("Enter a name for this bookmark, or hit enter for \"%s\": ", dfltname);
145 }
146 fflush(stdin);
147 (void) FGets(bmname, sizeof(bmname), stdin);
148 if (bmname[0] != '\0') {
149 (void) STRNCPY(bmp->bookmarkName, bmname);
150 return (0);
151 } else if (dfltname[0] != '\0') {
152 (void) STRNCPY(bmp->bookmarkName, dfltname);
153 return (0);
154 }
155 return (-1);
156} /* PromptForBookmarkName */
157
158
159
160void
161CurrentURL(char *dst, size_t dsize, int showpass)
162{
163 Bookmark bm;
164 char dir[160];
165
166 memset(&bm, 0, sizeof(bm));
167 (void) STRNCPY(bm.name, gConn.host);
168 if ((gConn.user[0] != '\0') && (! STREQ(gConn.user, "anonymous")) && (! STREQ(gConn.user, "ftp"))) {
169 (void) STRNCPY(bm.user, gConn.user);
170 (void) STRNCPY(bm.pass, (showpass == 0) ? "PASSWORD" : gConn.pass);
171 (void) STRNCPY(bm.acct, gConn.acct);
172 }
173
174 bm.port = gConn.port;
175
176 /* We now save relative paths, because the pathname in URLs are
177 * relative by nature. This makes non-anonymous FTP URLs shorter
178 * because it doesn't have to include the pathname of their
179 * home directory.
180 */
183
184 BookmarkToURL(&bm, dst, dsize);
185} /* CurrentURL */
186
187
188
189
190/* Fills in the fields of the Bookmark structure, based on the FTP current
191 * session.
192 */
193void
195{
196 char dir[160];
197
198 (void) STRNCPY(bmp->name, gConn.host);
199 if ((STREQ(gConn.user, "anonymous")) || (STREQ(gConn.user, "ftp"))) {
200 bmp->user[0] = '\0';
201 bmp->pass[0] = '\0';
202 bmp->acct[0] = '\0';
203 } else {
204 (void) STRNCPY(bmp->user, gConn.user);
205 (void) STRNCPY(bmp->pass, gConn.pass);
206 (void) STRNCPY(bmp->acct, gConn.acct);
207 }
208
209 /* We now save relative paths, because the pathname in URLs are
210 * relative by nature. This makes non-anonymous FTP URLs shorter
211 * because it doesn't have to include the pathname of their
212 * home directory.
213 */
215 AbsoluteToRelative(bmp->dir, sizeof(bmp->dir), dir, gStartDir, strlen(gStartDir));
216 bmp->port = gConn.port;
217 (void) time(&bmp->lastCall);
218 bmp->hasSIZE = gConn.hasSIZE;
219 bmp->hasMDTM = gConn.hasMDTM;
220 bmp->hasPASV = gConn.hasPASV;
221 bmp->hasUTIME = gConn.hasUTIME;
223 (void) STRNCPY(bmp->lastIP, gConn.ip);
224} /* FillBookmarkInfo */
225
226
227
228
229/* Saves the current FTP session settings as a bookmark. */
230void
232{
233 int saveBm;
234 char ans[64];
235
236 /* gBm.bookmarkName must already be set. */
238
239 saveBm = gSavePasswords;
240 if (gLoadedBm != 0)
241 saveBm = 1;
242 if ((saveBm < 0) && (gBm.pass[0] != '\0')) {
243 (void) printf("\n\nYou logged into this site using a password.\nWould you like to save the password with this bookmark?\n\n");
244 (void) printf("Save? [no] ");
245 (void) memset(ans, 0, sizeof(ans));
246 fflush(stdin);
247 (void) fgets(ans, sizeof(ans) - 1, stdin);
248 if ((saveBm = StrToBool(ans)) == 0) {
249 (void) printf("\nNot saving the password.\n");
250 }
251 }
252 if (PutBookmark(&gBm, saveBm) < 0) {
253 (void) fprintf(stderr, "Could not save bookmark.\n");
254 } else {
255 /* Also marks whether we saved it. */
256 gLoadedBm = 1;
257 (void) printf("Bookmark \"%s\" saved.\n", gBm.bookmarkName);
258
260 }
261} /* SaveCurrentAsBookmark */
262
263
264
265
266/* If the user did not explicitly bookmark this site already, ask
267 * the user if they want to save one.
268 */
269void
271{
272 char url[256];
273 char ans[64];
274 int c;
275
276 if ((gConfirmClose != 0) && (gLoadedBm == 0) && (gOurDirectoryPath[0] != '\0')) {
278 BookmarkToURL(&gBm, url, sizeof(url));
279 (void) printf("\n\nYou have not saved a bookmark for this site.\n");
280 (void) sleep(1);
281 (void) printf("\nWould you like to save a bookmark to:\n\t%s\n\n", url);
282 for (;;) {
283 (void) printf("Save? (yes/no) ");
284 (void) memset(ans, 0, sizeof(ans));
285 fflush(stdin);
286 if (fgets(ans, sizeof(ans) - 1, stdin) == NULL) {
287 c = 'n';
288 break;
289 }
290 c = ans[0];
291 if ((c == 'n') || (c == 'y'))
292 break;
293 if (c == 'N') {
294 c = 'n';
295 break;
296 } else if (c == 'Y') {
297 c = 'y';
298 break;
299 }
300 }
301 if (c == 'n') {
302 (void) printf("Not saved. (If you don't want to be asked this, \"set confirm-close no\")\n\n\n");
303
304 } else if (PromptForBookmarkName(&gBm) < 0) {
305 (void) printf("Nevermind.\n");
306 } else {
308 }
309 } else if ((gLoadedBm == 1) && (gOurDirectoryPath[0] != '\0') && (strcmp(gOurDirectoryPath, gBm.dir) != 0)) {
310 /* Bookmark has changed. */
313 }
314 }
315} /* SaveUnsavedBookmark */
316
317
318
319/* Save the current host session settings for later as a "bookmark", which
320 * will be referred to by a bookmark abbreviation name.
321 */
322void
323BookmarkCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
324{
325 /* The only reason we do this is to get gcc/lint to shut up
326 * about unused parameters.
327 */
329
330 if (gOurDirectoryPath[0] == '\0') {
331 (void) printf("Sorry, configuration information is not saved for this user.\n");
332 } else if ((argc <= 1) || (argv[1][0] == '\0')) {
333 /* No name specified on the command line. */
334 if (gBm.bookmarkName[0] == '\0') {
335 /* Not previously bookmarked. */
336 if (PromptForBookmarkName(&gBm) < 0) {
337 (void) printf("Nevermind.\n");
338 } else {
340 }
341 } else {
342 /* User wants to update an existing bookmark. */
344 }
345 } else {
348 }
349} /* BookmarkCmd */
350
351
352
353
354/* Dump a remote file to the screen. */
355void
356CatCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
357{
358 int result;
359 int i;
360
362 for (i=1; i<argc; i++) {
365 }
366} /* CatCmd */
367
368
369
370static void
372{
373 LinePtr lp;
374 LineListPtr llp;
375
376 gUnusedArg = (cipUNUSED != NULL);
377 if ((rp->printMode & kResponseNoPrint) != 0)
378 return;
379 llp = &rp->msg;
380 for (lp = llp->first; lp != NULL; lp = lp->next) {
381 if ((lp == llp->first) && (rp->codeType == 2)) {
382 if (ISTRNCMP(lp->line, "CWD command", 11) == 0)
383 continue;
384 if (lp->line[0] == '"')
385 continue; /* "/pub/foo" is... */
386 }
387 (void) printf("%s\n", lp->line);
388 }
389} /* NcFTPCdResponseProc */
390
391
392
393
394/* Manually print a response obtained from the remote FTP user. */
395void
397{
398 LinePtr lp;
399
400 if (llp != NULL) {
401 for (lp = llp->first; lp != NULL; lp = lp->next) {
402 if ((lp == llp->first) && (ISTRNCMP(lp->line, "CWD command", 11) == 0))
403 continue;
404 (void) printf("%s\n", lp->line);
405 }
406 }
407} /* PrintResp */
408
409
410
411
412/* Do a chdir, and update our notion of the current directory.
413 * Some servers return it back as part of the CWD response,
414 * otherwise do a CWD command followed by a PWD.
415 */
416int
417nFTPChdirAndGetCWD(const FTPCIPtr cip, const char *cdCwd, const int quietMode)
418{
419 ResponsePtr rp;
420 size_t cdCwdLen;
421 int result;
422#ifdef USE_WHAT_SERVER_SAYS_IS_CWD
423 int foundcwd;
424 char *l, *r;
425#endif
426
427 if (cip == NULL)
428 return (kErrBadParameter);
429 if (strcmp(cip->magic, kLibraryMagic))
430 return (kErrBadMagic);
431
432 if ((cdCwd == NULL) || (cdCwd[0] == '\0')) {
435 } else {
436 rp = InitResponse();
437 if (rp == NULL) {
439 cip->errNo = kErrMallocFailed;
440 /* Error(cip, kDontPerror, "Malloc failed.\n"); */
441 } else {
442 cdCwdLen = strlen(cdCwd);
443 if (strcmp(cdCwd, "..") == 0) {
444 result = RCmd(cip, rp, "CDUP");
445 } else {
446 result = RCmd(cip, rp, "CWD %s", cdCwd);
447 }
448 if (result == 2) {
449#ifdef USE_WHAT_SERVER_SAYS_IS_CWD
451 foundcwd = 0;
452 if ((r = strrchr(rp->msg.first->line, '"')) != NULL) {
453 /* "xxxx" is current directory.
454 * Strip out just the xxxx to copy into the remote cwd.
455 *
456 * This is nice because we didn't have to do a PWD.
457 */
458 l = strchr(rp->msg.first->line, '"');
459 if ((l != NULL) && (l != r) && (l == rp->msg.first->line)) {
460 *r = '\0';
461 ++l;
462 (void) Strncpy(gRemoteCWD, l, sizeof(gRemoteCWD));
463 *r = '"'; /* Restore, so response prints correctly. */
464 foundcwd = 1;
465 result = kNoErr;
466 }
467 }
468 if (quietMode)
470 NcFTPCdResponseProc(cip, rp);
471 DoneWithResponse(cip, rp);
472 if (foundcwd == 0) {
473 result = FTPGetCWD(cip, gRemoteCWD, sizeof(gRemoteCWD));
474 if (result != kNoErr) {
475 PathCat(gRemoteCWD, sizeof(gRemoteCWD), gScratchCWD, cdCwd);
476 result = kNoErr;
477 }
478 }
479#else /* USE_CLIENT_SIDE_CALCULATED_CWD */
480 if (quietMode)
482 NcFTPCdResponseProc(cip, rp);
483 DoneWithResponse(cip, rp);
485 PathCat(gRemoteCWD, sizeof(gRemoteCWD), gScratchCWD, cdCwd);
486 result = kNoErr;
487#endif
488 } else if (result > 0) {
490 cip->errNo = kErrCWDFailed;
491 DoneWithResponse(cip, rp);
492 } else {
493 DoneWithResponse(cip, rp);
494 }
495 }
496 }
497 return (result);
498} /* nFTPChdirAndGetCWD */
499
500
501
502
503int
504Chdirs(FTPCIPtr cip, const char *const cdCwd)
505{
506 char *cp, *startcp;
507 int result;
508 int lastSubDir;
509
510 if (cip == NULL)
511 return (kErrBadParameter);
512 if (strcmp(cip->magic, kLibraryMagic))
513 return (kErrBadMagic);
514
515 if (cdCwd == NULL) {
518 return result;
519 }
520
521 if ((cdCwd[0] == '\0') || (strcmp(cdCwd, ".") == 0)) {
522 result = 0;
523 return (result);
524 }
525
526 cp = cip->buf;
527 cp[cip->bufSize - 2] = '\0';
528 if ((cdCwd[0] == '.') && (cdCwd[1] == '.') && ((cdCwd[2] == '\0') || IsLocalPathDelim(cdCwd[2]))) {
529 PathCat(cip->buf, cip->bufSize, gRemoteCWD, cdCwd);
530 } else {
531 (void) Strncpy(cip->buf, cdCwd, cip->bufSize);
532 }
533 if (cp[cip->bufSize - 2] != '\0')
534 return (kErrBadParameter);
535
537 do {
538 startcp = cp;
540 if (cp != NULL) {
541 *cp++ = '\0';
542 }
543 lastSubDir = (cp == NULL);
544 result = nFTPChdirAndGetCWD(cip, (*startcp != '\0') ? startcp : "/", lastSubDir ? 0 : 1);
545 if (result < 0) {
546 cip->errNo = result;
547 }
548 } while ((!lastSubDir) && (result == 0));
549
550 return (result);
551} /* Chdirs */
552
553
554
555
556/* Remote change of working directory command. */
557void
558ChdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
559{
560 int result;
561 LineList ll;
562 LinePtr lp;
563
565
566 if (argc <= 1) {
567 if (gStartDir[0] != '\0') {
570 if (result != kNoErr) {
571 /* State is incoherent if this happens! */
572 FTPPerror(&gConn, result, kErrCWDFailed, "Could not chdir to", gStartDir);
573 }
574 } else {
575 PrintCmdUsage(cmdp);
576 }
577 } else {
579 result = FTPRemoteGlob(&gConn, &ll, argv[1], (aip->noglobargv[1] != 0) ? kGlobNo: kGlobYes);
580 if (result < 0) {
582 } else {
583 lp = ll.first;
584 if ((lp != NULL) && (lp->line != NULL)) {
585 if ((strcmp(lp->line, "-") == 0) && (gPrevRemoteCWD[0] != '\0')) {
586 free(lp->line);
588 if (lp->line == NULL) {
591 } else {
593 result = Chdirs(&gConn, lp->line);
594 }
595 } else {
597 result = Chdirs(&gConn, lp->line);
598 }
599 if (result != kNoErr)
600 FTPPerror(&gConn, result, kErrCWDFailed, "Could not chdir to", lp->line);
601 }
602 }
604 }
605} /* ChdirCmd */
606
607
608
609
610/* Chmod files on the remote host, if it supports it. */
611void
612ChmodCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
613{
614 int i, result;
615
617 for (i=2; i<argc; i++) {
619 &gConn, argv[i], argv[1],
620 (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes
621 );
622 if (result < 0) {
624 /* but continue */
625 }
626 }
627
628 /* Really should just flush only the modified directories... */
629 FlushLsCache();
630} /* ChmodCmd */
631
632
633
634
635/* Close the current session to a remote FTP server. */
636void
637CloseCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
638{
640 if (gConn.connected == 0)
641 (void) printf("Already closed.\n");
642 else
643 CloseHost();
644} /* CloseCmd */
645
646
647
648/* User interface to the program's debug-mode setting. */
649void
650DebugCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
651{
653 if (argc > 1)
654 SetDebug(atoi(argv[1]));
655 else
657} /* DebugCmd */
658
659
660
661
662/* Delete files on the remote host. */
663void
664DeleteCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
665{
666 int result;
667 int i, c;
668 int recursive = kRecursiveNo;
669
671 GetoptReset();
672 while ((c = Getopt(argc, argv, "rf")) > 0) switch(c) {
673 case 'r':
674 recursive = kRecursiveYes;
675 break;
676 case 'f':
677 /* ignore */
678 break;
679 default:
680 PrintCmdUsage(cmdp);
681 return;
682 }
683
684 for (i=gOptInd; i<argc; i++) {
686 &gConn, argv[i], recursive,
687 (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes
688 );
689 if (result < 0) {
690 FTPPerror(&gConn, result, kErrDELEFailed, "delete", argv[i]);
691 /* but continue */
692 }
693 }
694
695 /* Really should just flush only the modified directories... */
696 FlushLsCache();
697} /* DeleteCmd */
698
699
700
701
702/* Command shell echo command. This is mostly useful for testing the command
703 * shell, as a sample command which prints some output.
704 */
705void
706EchoCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
707{
708 int i;
709 int result;
710 int np = 0;
711 LineList ll;
712 LinePtr lp;
713
715 for (i=1; i<argc; i++) {
717 result = FTPLocalGlob(&gConn, &ll, argv[i], (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
718 if (result < 0) {
719 FTPPerror(&gConn, result, kErrGlobFailed, "local glob", argv[i]);
720 } else {
721 for (lp = ll.first; lp != NULL; lp = lp->next) {
722 if (lp->line != NULL) {
723 if (np > 0)
724 (void) printf(" ");
725 (void) printf("%s", lp->line);
726 np++;
727 }
728 }
729 }
731 }
732 (void) printf("\n");
733} /* EchoCmd */
734
735
736
737
738static int
740 const char *volatile *localpath,
741 volatile longest_int localsize,
742 volatile time_t localmtime,
743 const char *volatile remotepath,
744 volatile longest_int remotesize,
745 volatile time_t remotemtime,
746 volatile longest_int *volatile startPoint)
747{
749 char tstr[80], ans[32];
750 static char newname[128]; /* arrggh... static. */
751
753 return (gResumeAnswerAll);
754
755 if (gAutoResume != 0)
757
758 tstr[sizeof(tstr) - 1] = '\0';
759 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &localmtime));
760 (void) printf(
761#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
762 "\nThe local file \"%s\" already exists.\n\tLocal: %12lld bytes, dated %s.\n",
763#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
764 "\nThe local file \"%s\" already exists.\n\tLocal: %12qd bytes, dated %s.\n",
765#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
766 "\nThe local file \"%s\" already exists.\n\tLocal: %12I64d bytes, dated %s.\n",
767#else
768 "\nThe local file \"%s\" already exists.\n\tLocal: %12ld bytes, dated %s.\n",
769#endif
770 *localpath,
771 localsize,
772 tstr
773 );
774
775 if ((remotemtime != kModTimeUnknown) && (remotesize != kSizeUnknown)) {
776 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &remotemtime));
777 (void) printf(
778#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
779 "\tRemote: %12lld bytes, dated %s.\n",
780#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
781 "\tRemote: %12qd bytes, dated %s.\n",
782#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
783 "\tRemote: %12I64d bytes, dated %s.\n",
784#else
785 "\tRemote: %12ld bytes, dated %s.\n",
786#endif
787 remotesize,
788 tstr
789 );
790 if ((remotemtime == localmtime) && (remotesize == localsize)) {
791 (void) printf("\t(Files are identical, skipped)\n\n");
793 }
794 } else if (remotesize != kSizeUnknown) {
795 (void) printf(
796#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
797 "\tRemote: %12lld bytes, date unknown.\n",
798#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
799 "\tRemote: %12qd bytes, date unknown.\n",
800#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
801 "\tRemote: %12I64d bytes, date unknown.\n",
802#else
803 "\tRemote: %12ld bytes, date unknown.\n",
804#endif
805 remotesize
806 );
807 } else if (remotemtime != kModTimeUnknown) {
808 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &remotemtime));
809 (void) printf(
810 "\tRemote: size unknown, dated %s.\n",
811 tstr
812 );
813 }
814
815 printf("\n");
816 (void) memset(ans, 0, sizeof(ans));
817 for (;;) {
818 (void) printf("\t[O]verwrite?");
819 if ((gConn.hasREST == kCommandAvailable) && (remotesize != kSizeUnknown) && (remotesize > localsize))
820 printf(" [R]esume?");
821 printf(" [A]ppend to? [S]kip? [N]ew Name?\n");
822 (void) printf("\t[O!]verwrite all?");
823 if ((gConn.hasREST == kCommandAvailable) && (remotesize != kSizeUnknown) && (remotesize > localsize))
824 printf(" [R!]esume all?");
825 printf(" [S!]kip all? [C]ancel > ");
826 fflush(stdin);
827 (void) fgets(ans, sizeof(ans) - 1, stdin);
828 switch ((int) ans[0]) {
829 case 'c':
830 case 'C':
831 ans[0] = 'C';
832 ans[1] = '\0';
834 break;
835 case 'o':
836 case 'O':
837 ans[0] = 'O';
839 break;
840 case 'r':
841 case 'R':
842 if ((gConn.hasREST != kCommandAvailable) || (remotesize == kSizeUnknown)) {
843 printf("\tResume is not available on this server.\n\n");
844 ans[0] = '\0';
845 break;
846 } else if (remotesize < localsize) {
847 printf("\tCannot resume when local file is already larger than the remote file.\n\n");
848 ans[0] = '\0';
849 break;
850 } else if (remotesize <= localsize) {
851 printf("\tLocal file is already the same size as the remote file.\n\n");
852 ans[0] = '\0';
853 break;
854 }
855 ans[0] = 'R';
856 *startPoint = localsize;
858 if (OneTimeMessage("auto-resume") != 0) {
859 printf("\n\tNOTE: If you want NcFTP to guess automatically, \"set auto-resume yes\"\n\n");
860 }
861 break;
862 case 's':
863 case 'S':
864 ans[0] = 'S';
866 break;
867 case 'n':
868 case 'N':
869 ans[0] = 'N';
870 ans[1] = '\0';
872 break;
873 case 'a':
874 case 'A':
875 ans[0] = 'A';
876 ans[1] = '\0';
878 break;
879 case 'g':
880 case 'G':
881 ans[0] = 'G';
883 break;
884 default:
885 ans[0] = '\0';
886 }
887 if (ans[0] != '\0')
888 break;
889 }
890
891 if (ans[0] == 'N') {
892 (void) memset(newname, 0, sizeof(newname));
893 printf("\tSave as: ");
894 fflush(stdin);
895 (void) fgets(newname, sizeof(newname) - 1, stdin);
896 newname[strlen(newname) - 1] = '\0';
897 if (newname[0] == '\0') {
898 /* Nevermind. */
899 printf("Skipped %s.\n", remotepath);
901 } else {
902 *localpath = newname;
903 }
904 }
905
906 if (ans[1] == '!')
907 gResumeAnswerAll = zaction;
908 return (zaction);
909} /* NcFTPConfirmResumeDownloadProc */
910
911
912
913
914/* Download files from the remote system. */
915void
916GetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
917{
918 int opt;
919 int renameMode = 0;
920 int recurseFlag = kRecursiveNo;
921 int appendFlag = kAppendNo;
922 int resumeFlag = kResumeYes;
923 int tarflag = kTarYes;
924 const char *dstdir = NULL;
925 int rc;
926 int i;
927 int doGlob;
928 int xtype = gBm.xferType;
929 int nD = 0;
930 int deleteFlag = kDeleteNo;
931 char pattern[256];
932 vsigproc_t osigint;
933 ConfirmResumeDownloadProc confirmProc;
934
935 confirmProc = NcFTPConfirmResumeDownloadProc;
936 gResumeAnswerAll = kConfirmResumeProcNotUsed; /* Ask at least once each time */
938 GetoptReset();
939 while ((opt = Getopt(argc, argv, "aAzfrRTD")) >= 0) switch (opt) {
940 case 'a':
941 xtype = kTypeAscii;
942 break;
943 case 'A':
944 /* Append to local files, instead of truncating
945 * them first.
946 */
947 appendFlag = kAppendYes;
948 break;
949 case 'f':
950 case 'Z':
951 /* Do not try to resume a download, even if it
952 * appeared that some of the file was transferred
953 * already.
954 */
955 resumeFlag = kResumeNo;
956 confirmProc = NoConfirmResumeDownloadProc;
957 break;
958 case 'z':
959 /* Special flag that lets you specify the
960 * destination file. Normally a "get" will
961 * write the file by the same name as the
962 * remote file's basename.
963 */
964 renameMode = 1;
965 break;
966 case 'r':
967 case 'R':
968 /* If the item is a directory, get the
969 * directory and all its contents.
970 */
971 recurseFlag = kRecursiveYes;
972 break;
973 case 'T':
974 /* If they said "-R", they may want to
975 * turn off TAR mode if they are trying
976 * to resume the whole directory.
977 * The disadvantage to TAR mode is that
978 * it always downloads the whole thing,
979 * which is why there is a flag to
980 * disable this.
981 */
982 tarflag = kTarNo;
983 break;
984 case 'D':
985 /* You can delete the remote file after
986 * you downloaded it successfully by using
987 * the -DD option. It requires two -D's
988 * to minimize the odds of accidentally
989 * using a single -D.
990 */
991 nD++;
992 break;
993 default:
994 PrintCmdUsage(cmdp);
995 return;
996 }
997
998 if (nD >= 2)
999 deleteFlag = kDeleteYes;
1000
1001 if (renameMode != 0) {
1002 if (gOptInd > argc - 2) {
1003 PrintCmdUsage(cmdp);
1004 (void) fprintf(stderr, "\nFor get with rename, try \"get -z remote-path-name local-path-name\".\n");
1005 return;
1006 }
1007 osigint = NcSignal(SIGINT, XferCanceller);
1008 rc = FTPGetOneFile3(&gConn, argv[gOptInd], argv[gOptInd + 1], xtype, (-1), resumeFlag, appendFlag, deleteFlag, NoConfirmResumeDownloadProc, 0);
1009 if (rc < 0)
1011 } else {
1012 osigint = NcSignal(SIGINT, XferCanceller);
1013 for (i=gOptInd; i<argc; i++) {
1014 doGlob = (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes;
1015 STRNCPY(pattern, argv[i]);
1017 rc = FTPGetFiles3(&gConn, pattern, dstdir, recurseFlag, doGlob, xtype, resumeFlag, appendFlag, deleteFlag, tarflag, confirmProc, 0);
1018 if (rc < 0)
1020 }
1021 }
1022 (void) NcSignal(SIGINT, osigint);
1023 (void) fflush(stdin);
1024
1025 if (deleteFlag == kDeleteYes) {
1026 /* Directory is now out of date */
1027 FlushLsCache();
1028 }
1029} /* GetCmd */
1030
1031
1032
1033
1034/* Display some brief help for specified commands, or a list of commands. */
1035void
1036HelpCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1037{
1038 CommandPtr c;
1039 int showall = 0, helpall = 0;
1040 int i, j, k, n;
1041 int nRows, nCols;
1042 int nCmds2Print;
1043 int screenColumns;
1044 int len, widestName;
1045 char *cp, spec[16];
1046 const char *cmdnames[64];
1047
1049 assert(gNumCommands < (sizeof(cmdnames) / sizeof(char *)));
1050 if (argc == 2) {
1051 showall = (strcmp(argv[1], "showall") == 0);
1052 helpall = (strcmp(argv[1], "helpall") == 0);
1053 }
1054 if (argc == 1 || showall) {
1055 (void) printf("\
1056Commands may be abbreviated. 'help showall' shows hidden and unsupported \n\
1057commands. 'help <command>' gives a brief description of <command>.\n\n");
1058
1059 /* First, see how many commands we will be printing to the screen.
1060 * Unless 'showall' was given, we won't be printing the hidden
1061 * (i.e. not very useful to the end-user) commands.
1062 */
1063 c = gCommands;
1064 nCmds2Print = 0;
1065 for (n = 0; n < (int) gNumCommands; c++, n++)
1066 if ((!iscntrl((int) c->name[0])) && (!(c->flags & kCmdHidden) || showall))
1067 nCmds2Print++;
1068
1069 (void) memset((char *) cmdnames, 0, sizeof(cmdnames));
1070
1071 /* Now form the list we'll be printing, and noting what the maximum
1072 * length of a command name was, so we can use that when determining
1073 * how to print in columns.
1074 */
1075 c = gCommands;
1076 i = 0;
1077 widestName = 0;
1078 for (n = 0; n < (int) gNumCommands; c++, n++) {
1079 if ((!iscntrl((int) c->name[0])) && (!(c->flags & kCmdHidden) || showall)) {
1080 cmdnames[i++] = c->name;
1081 len = (int) strlen(c->name);
1082 if (len > widestName)
1083 widestName = len;
1084 }
1085 }
1086
1087 if ((cp = (char *) getenv("COLUMNS")) == NULL)
1088 screenColumns = 80;
1089 else
1090 screenColumns = atoi(cp);
1091
1092 /* Leave an extra bit of whitespace for the margins between columns. */
1093 widestName += 2;
1094
1095 nCols = (screenColumns + 0) / widestName;
1096 nRows = nCmds2Print / nCols;
1097 if ((nCmds2Print % nCols) > 0)
1098 nRows++;
1099
1100 for (i = 0; i < nRows; i++) {
1101 for (j = 0; j < nCols; j++) {
1102 k = nRows * j + i;
1103 if (k < nCmds2Print) {
1104 (void) sprintf(spec, "%%-%ds",
1105 (j < nCols - 1) ? widestName : widestName - 2
1106 );
1107 (void) printf(spec, cmdnames[k]);
1108 }
1109 }
1110 (void) printf("\n");
1111 }
1112 } else if (helpall) {
1113 /* Really intended for me, so I can debug the help strings. */
1114 for (c = gCommands, n = 0; n < (int) gNumCommands; c++, n++) {
1115 PrintCmdHelp(c);
1117 }
1118 } else {
1119 /* For each command name specified, print its help stuff. */
1120 for (i=1; i<argc; i++) {
1121 c = GetCommandByName(argv[i], 0);
1122 if (c == kAmbiguousCommand) {
1123 (void) printf("%s: ambiguous command name.\n", argv[i]);
1124 } else if (c == kNoCommand) {
1125 (void) printf("%s: no such command.\n", argv[i]);
1126 } else {
1127 if (i > 1)
1128 (void) printf("\n");
1129 PrintCmdHelp(c);
1131 }
1132 }
1133 }
1134} /* HelpCmd */
1135
1136
1137
1138
1139/* Displays the list of saved bookmarks, so that the user can then choose
1140 * one by name.
1141 */
1142static int
1144{
1145 FILE *bookmarks;
1146 FILE *pager;
1147 int nbm = 0;
1148 Bookmark bm;
1149 char url[128];
1150#ifdef SIGPIPE
1151 sigproc_t osigpipe;
1152#endif
1153
1154 bookmarks = OpenBookmarkFile(NULL);
1155 if (bookmarks == NULL)
1156 return (0);
1157
1158#ifdef SIGPIPE
1159 osigpipe = (sigproc_t) NcSignal(SIGPIPE, SIG_IGN);
1160#endif
1161 pager = OpenPager();
1162
1163 while (GetNextBookmark(bookmarks, &bm) == 0) {
1164 nbm++;
1165 if (nbm == 1) {
1166 /* header */
1167 (void) fprintf(pager, "--BOOKMARK----------URL--------------------------------------------------------\n");
1168 }
1169 BookmarkToURL(&bm, url, sizeof(url));
1170 (void) fprintf(pager, " %-16s %s\n", bm.bookmarkName, url);
1171 }
1172
1173 ClosePager(pager);
1174 CloseBookmarkFile(bookmarks);
1175
1176#ifdef SIGPIPE
1177 (void) NcSignal(SIGPIPE, osigpipe);
1178#endif
1179 return (nbm);
1180} /* PrintHosts */
1181
1182
1183
1184
1185
1186static int
1187RunBookmarkEditor(char *selectedBmName, size_t dsize)
1188{
1189#if defined(WIN32) || defined(_WINDOWS)
1190 char ncftpbookmarks[260];
1191 const char *prog;
1192 int winExecResult;
1193 HANDLE hMailSlot;
1194 char msg[kNcFTPBookmarksMailslotMsgSize];
1195 DWORD dwRead;
1196 BOOL rc;
1197
1198 if (selectedBmName != NULL)
1199 memset(selectedBmName, 0, dsize);
1200 if (gOurInstallationPath[0] == '\0') {
1201 (void) fprintf(stderr, "Cannot find path to %s. Please re-run Setup.\n", "ncftpbookmarks.exe");
1202 return (-1);
1203 }
1204 prog = ncftpbookmarks;
1205 OurInstallationPath(ncftpbookmarks, sizeof(ncftpbookmarks), "ncftpbookmarks.exe");
1206
1207
1208 hMailSlot = CreateMailslot(kNcFTPBookmarksMailslot, kNcFTPBookmarksMailslotMsgSize, MAILSLOT_WAIT_FOREVER, NULL);
1209
1210 if (hMailSlot == INVALID_HANDLE_VALUE) {
1211 SysPerror("CreateMailslot");
1212 (void) fprintf(stderr, "Could not create communication channel with %s.\n", "ncftpbookmarks.exe");
1213 (void) fprintf(stderr, "%s", "This means if you select a bookmark to connect to that NcFTP\n");
1214 (void) fprintf(stderr, "%s", "will not get the message from %s.\n");
1215 }
1216
1217 winExecResult = WinExec(prog, SW_SHOWNORMAL);
1218 if (winExecResult <= 31) switch (winExecResult) {
1219 case ERROR_BAD_FORMAT:
1220 fprintf(stderr, "Could not run %s: %s\n", prog, "The .EXE file is invalid");
1221 return (-1);
1223 fprintf(stderr, "Could not run %s: %s\n", prog, "The specified file was not found.");
1224 return (-1);
1226 fprintf(stderr, "Could not run %s: %s\n", prog, "The specified path was not found.");
1227 return (-1);
1228 default:
1229 fprintf(stderr, "Could not run %s: Unknown error #%d.\n", prog, winExecResult);
1230 return (-1);
1231 }
1232
1233 if (hMailSlot != INVALID_HANDLE_VALUE) {
1234 fprintf(stdout, "Waiting for %s to exit...\n", "ncftpbookmarks.exe");
1235 ZeroMemory(msg, sizeof(msg));
1236 dwRead = 0;
1237 rc = ReadFile(
1238 hMailSlot,
1239 msg,
1240 sizeof(msg),
1241 &dwRead,
1242 NULL
1243 );
1244
1245 if (!rc) {
1246 SysPerror("ReadFile");
1247 } else {
1248 msg[sizeof(msg) - 1] = '\0';
1249 Strncpy(selectedBmName, msg, dsize);
1250 Trace(0, "Selected bookmark from editor: [%s]\n", selectedBmName);
1251 }
1252 CloseHandle(hMailSlot);
1253 }
1254 return (0);
1255
1256#else
1257#ifdef BINDIR
1258 char ncftpbookmarks[256];
1259 char *av[8];
1260 int pid;
1261 int status;
1262 char bmSelectionFile[256];
1263 char pidStr[32];
1264 FILE *fp;
1265
1266 if (selectedBmName != NULL)
1267 memset(selectedBmName, 0, dsize);
1268 STRNCPY(ncftpbookmarks, BINDIR);
1269 STRNCAT(ncftpbookmarks, "/");
1270 STRNCAT(ncftpbookmarks, "ncftpbookmarks");
1271
1272 STRNCPY(bmSelectionFile, "view");
1273 if ((selectedBmName != NULL) && (gOurDirectoryPath[0] != '\0')) {
1274 sprintf(pidStr, ".%u", (unsigned int) getpid());
1275 OurDirectoryPath(bmSelectionFile, sizeof(bmSelectionFile), kOpenSelectedBookmarkFileName);
1276 STRNCAT(bmSelectionFile, pidStr);
1277 }
1278
1279 if (access(ncftpbookmarks, X_OK) == 0) {
1280 pid = (int) fork();
1281 if (pid < 0) {
1282 return (-1);
1283 } else if (pid == 0) {
1284 /* child */
1285
1286 av[0] = (char *) "ncftpbookmarks";
1287 av[1] = bmSelectionFile;
1288 av[2] = NULL;
1289 execv(ncftpbookmarks, av);
1290 exit(1);
1291 } else {
1292 /* parent NcFTP */
1293 for (;;) {
1294#ifdef HAVE_WAITPID
1295 if ((waitpid(pid, &status, 0) < 0) && (errno != EINTR))
1296 break;
1297#else
1298 if ((wait(&status) < 0) && (errno != EINTR))
1299 break;
1300#endif
1301 if (WIFEXITED(status) || WIFSIGNALED(status))
1302 break; /* done */
1303 }
1304
1305 if (strcmp(bmSelectionFile, "view") != 0) {
1306 fp = fopen(bmSelectionFile, FOPEN_READ_TEXT);
1307 if (fp != NULL) {
1308 (void) FGets(selectedBmName, dsize, fp);
1309 (void) fclose(fp);
1310 (void) unlink(bmSelectionFile);
1311 Trace(0, "Selected bookmark from editor: [%s]\n", selectedBmName);
1312 }
1313 }
1314 return (0);
1315 }
1316 }
1317 return (-1);
1318#else /* BINDIR */
1319 /* Not installed. */
1320 return (-1);
1321#endif /* BINDIR */
1322#endif /* Windows */
1323} /* RunBookmarkEditor */
1324
1325
1326
1327/* This just shows the list of saved bookmarks. */
1328void
1329HostsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1330{
1331 const char *av[3];
1332 char bm[128];
1333
1335 /* Skip visual mode if "-l". */
1336 if ((argc == 1) && (RunBookmarkEditor(bm, sizeof(bm)) == 0)) {
1337 if (bm[0] != '\0') {
1338 av[0] = "open";
1339 av[1] = bm;
1340 av[2] = NULL;
1341 OpenCmd(2, av, (CommandPtr) 0, (ArgvInfoPtr) 0);
1342 }
1343 return;
1344 }
1345 if (PrintHosts() <= 0) {
1346 (void) printf("You haven't bookmarked any FTP sites.\n");
1347 (void) printf("Before closing a site, you can use the \"bookmark\" command to save the current\nhost and directory for next time.\n");
1348 } else {
1349 (void) printf("\nTo use a bookmark, use the \"open\" command with the name of the bookmark.\n");
1350 }
1351} /* HostsCmd */
1352
1353
1354
1355
1356/* Show active background ncftp (ncftpbatch) jobs. */
1357void
1358JobsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1359{
1361 Jobs();
1362} /* JobsCmd */
1363
1364
1365
1366
1367/* Do a "ls" on the remote system and display the directory contents to our
1368 * user. This command handles "dir" (ls -l), "ls", and "nlist" (ls -1).
1369 */
1370void
1371ListCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1372{
1373 volatile int i;
1374 int j;
1375 char options[32];
1376 char option[2];
1377 volatile int listmode;
1378 FILE *stream;
1379 volatile int paging;
1380#if defined(WIN32) || defined(_WINDOWS)
1381#else
1382 int sj;
1383 vsigproc_t osigpipe, osigint;
1384#endif
1385
1387 stream = stdout;
1388 paging = 0;
1389
1390 if (argv[0][0] == 'd') {
1391 /* dir */
1392 listmode = 'l';
1393 } else if (argv[0][0] == 'n') {
1394 /* nlist */
1395 listmode = '1';
1396 } else if (argv[0][0] == 'p') {
1397 /* pager */
1398 paging = 1;
1399
1400 if (argv[0][1] == 'd') {
1401 /* dir */
1402 listmode = 'l';
1403 } else if (argv[0][1] == 'n') {
1404 /* nlist */
1405 listmode = '1';
1406 } else {
1407 /* ls */
1408 listmode = 'C';
1409 }
1410 } else {
1411 /* ls */
1412 listmode = 'C';
1413 }
1414 options[0] = '\0';
1415 option[1] = '\0';
1416
1417 for (i=1; i<argc; i++) {
1418 if (argv[i][0] != '-')
1419 break;
1420 if (argv[i][1] == '-') {
1421 if (argv[i][2] == '\0') {
1422 /* end of options. */
1423 ++i;
1424 break;
1425 } else {
1426 /* GNU-esque long --option? */
1427 PrintCmdUsage(cmdp);
1428 }
1429 } else {
1430 for (j=1; ; j++) {
1431 option[0] = argv[i][j];
1432 if (argv[i][j] == '\0')
1433 break;
1434 switch (argv[i][j]) {
1435 case 'l':
1436 listmode = 'l';
1437 break;
1438 case '1':
1439 listmode = '1';
1440 break;
1441 case 'C':
1442 listmode = 'C';
1443 break;
1444 default:
1446 break;
1447 }
1448 }
1449 }
1450 }
1451
1452
1453 if (paging != 0) {
1454 stream = OpenPager();
1455 if (stream == NULL) {
1456 return;
1457 }
1458
1459#if defined(WIN32) || defined(_WINDOWS)
1460#elif defined(HAVE_SIGSETJMP)
1461 osigpipe = osigint = (sigproc_t) 0;
1462 sj = sigsetjmp(gCancelJmp, 1);
1463#else /* HAVE_SIGSETJMP */
1464 osigpipe = osigint = (sigproc_t) 0;
1465 sj = setjmp(gCancelJmp);
1466#endif /* HAVE_SIGSETJMP */
1467
1468#if defined(WIN32) || defined(_WINDOWS)
1469#else
1470 if (sj != 0) {
1471 /* Caught a signal. */
1474 (void) NcSignal(SIGPIPE, osigpipe);
1475 (void) NcSignal(SIGINT, osigint);
1476 Trace(0, "Canceled because of signal %d.\n", gGotSig);
1477 (void) fprintf(stderr, "Canceled.\n");
1478 gMayCancelJmp = 0;
1479 return;
1480 } else {
1481 osigpipe = NcSignal(SIGPIPE, Cancel);
1482 osigint = NcSignal(SIGINT, Cancel);
1483 gMayCancelJmp = 1;
1484 }
1485#endif
1486 }
1487
1488 if (argv[i] == NULL) {
1489 /* No directory specified, use cwd. */
1490 Ls(NULL, listmode, options, stream);
1491 } else {
1492 /* List each item. */
1493 for ( ; i<argc; i++) {
1494 Ls(argv[i], listmode, options, stream);
1495 }
1496 }
1497
1498 if (paging != 0) {
1500#if defined(WIN32) || defined(_WINDOWS)
1501#else
1502 (void) NcSignal(SIGPIPE, osigpipe);
1503 (void) NcSignal(SIGINT, osigint);
1504#endif
1505 }
1506 gMayCancelJmp = 0;
1507} /* ListCmd */
1508
1509
1510
1511
1512/* Does a change of working directory on the local host. */
1513void
1514LocalChdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1515{
1516 int result;
1517 const char *dir;
1518 char buf[512];
1519
1521 dir = ((argc < 2) ? gHome : argv[1]);
1522 if ((dir[0] == '-') && (dir[1] == '\0')) {
1523 if (gPrevLocalCWD[0] == '\0') {
1524 (void) fprintf(stderr, "No previous local working directory to switch to.\n");
1525 return;
1526 } else {
1528 }
1529 } else if (dir[0] == '~') {
1530 if (dir[1] == '\0') {
1531 dir = gHome;
1532 } else if (dir[1] == '/') {
1533 (void) STRNCPY(buf, gHome);
1534 dir = STRNCAT(buf, dir + 1);
1535 }
1536 }
1537 result = chdir(dir);
1538 if (result < 0) {
1539 perror(dir);
1540 } else {
1543
1544 }
1545} /* LocalChdirCmd */
1546
1547
1548
1549
1550/* Does directory listing on the local host. */
1551void
1552LocalListCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1553{
1554#if defined(WIN32) || defined(_WINDOWS)
1555 volatile int i;
1556 int j;
1557 char options[32];
1558 char option[2];
1559 volatile int listmode;
1560 FILE *stream;
1561 volatile int paging;
1562
1563
1565 stream = stdout;
1566 paging = 0;
1567
1568 if (argv[0][1] == 'd') {
1569 /* dir */
1570 listmode = 'l';
1571 } else if (argv[0][1] == 'n') {
1572 /* nlist */
1573 listmode = '1';
1574 } else {
1575 /* ls */
1576 listmode = 'C';
1577 }
1578 options[0] = '\0';
1579 option[1] = '\0';
1580
1581 for (i=1; i<argc; i++) {
1582 if (argv[i][0] != '-')
1583 break;
1584 if (argv[i][1] == '-') {
1585 if (argv[i][2] == '\0') {
1586 /* end of options. */
1587 ++i;
1588 break;
1589 } else {
1590 /* GNU-esque long --option? */
1591 PrintCmdUsage(cmdp);
1592 }
1593 } else {
1594 for (j=1; ; j++) {
1595 option[0] = argv[i][j];
1596 if (argv[i][j] == '\0')
1597 break;
1598 switch (argv[i][j]) {
1599 case 'l':
1600 listmode = 'l';
1601 break;
1602 case '1':
1603 listmode = '1';
1604 break;
1605 case 'C':
1606 listmode = 'C';
1607 break;
1608 default:
1610 break;
1611 }
1612 }
1613 }
1614 }
1615
1616
1617 if (argv[i] == NULL) {
1618 /* No directory specified, use cwd. */
1619 LLs(NULL, listmode, options, stream);
1620 } else {
1621 /* List each item. */
1622 for ( ; i<argc; i++) {
1623 LLs(argv[i], listmode, options, stream);
1624 }
1625 }
1626
1627#else
1628 FILE *volatile outfp;
1629 FILE *volatile infp;
1630 int i;
1631 int sj;
1632 int dashopts;
1633 char incmd[256];
1634 char line[256];
1635 vsigproc_t osigpipe, osigint;
1636
1638 (void) fflush(stdin);
1639 outfp = OpenPager();
1640
1641 (void) STRNCPY(incmd, "/bin/ls");
1642 for (i=1, dashopts=0; i<argc; i++) {
1643 (void) STRNCAT(incmd, " ");
1644 if (argv[i][0] == '-')
1645 dashopts++;
1646 (void) STRNCAT(incmd, argv[i]);
1647 }
1648
1649 if (dashopts == 0) {
1650 (void) STRNCPY(incmd, "/bin/ls -CF");
1651 for (i=1; i<argc; i++) {
1652 (void) STRNCAT(incmd, " ");
1653 (void) STRNCAT(incmd, argv[i]);
1654 }
1655 }
1656
1657 infp = popen(incmd, "r");
1658 if (infp == NULL) {
1659 ClosePager(outfp);
1660 return;
1661 }
1662
1663
1664#ifdef HAVE_SIGSETJMP
1665 sj = sigsetjmp(gCancelJmp, 1);
1666#else /* HAVE_SIGSETJMP */
1667 sj = setjmp(gCancelJmp);
1668#endif /* HAVE_SIGSETJMP */
1669
1670 if (sj != 0) {
1671 /* Caught a signal. */
1673 ClosePager(outfp);
1674 if (infp != NULL)
1675 (void) pclose(infp);
1676 (void) NcSignal(SIGPIPE, osigpipe);
1677 (void) NcSignal(SIGINT, osigint);
1678 (void) fprintf(stderr, "Canceled.\n");
1679 Trace(0, "Canceled because of signal %d.\n", gGotSig);
1680 gMayCancelJmp = 0;
1681 return;
1682 } else {
1683 osigpipe = NcSignal(SIGPIPE, Cancel);
1684 osigint = NcSignal(SIGINT, Cancel);
1685 gMayCancelJmp = 1;
1686 }
1687
1688 while (fgets(line, sizeof(line) - 1, infp) != NULL)
1689 (void) fputs(line, outfp);
1690 (void) fflush(outfp);
1691
1692 (void) pclose(infp);
1693 infp = NULL;
1694 ClosePager(outfp);
1695 outfp = NULL;
1696
1697 (void) NcSignal(SIGPIPE, osigpipe);
1698 (void) NcSignal(SIGINT, osigint);
1699 gMayCancelJmp = 0;
1700#endif
1701} /* LocalListCmd */
1702
1703
1704
1705
1706/* static void
1707Sys(const int argc, const char **const argv, const ArgvInfoPtr aip, const char *syscmd, int noDQuote)
1708{
1709 char cmd[256];
1710 int i;
1711
1712 (void) STRNCPY(cmd, syscmd);
1713 for (i = 1; i < argc; i++) {
1714 if (aip->noglobargv[i] != 0) {
1715 (void) STRNCAT(cmd, " '");
1716 (void) STRNCAT(cmd, argv[i]);
1717 (void) STRNCAT(cmd, "'");
1718 } else if (noDQuote != 0) {
1719 (void) STRNCAT(cmd, " ");
1720 (void) STRNCAT(cmd, argv[i]);
1721 } else {
1722 (void) STRNCAT(cmd, " \"");
1723 (void) STRNCAT(cmd, argv[i]);
1724 (void) STRNCAT(cmd, "\" ");
1725 }
1726 }
1727#if defined(WIN32) || defined(_WINDOWS)
1728 fprintf(stderr, "Cannot run command: %s\n", cmd);
1729#else
1730 Trace(0, "Sys: %s\n", cmd);
1731 (void) system(cmd);
1732#endif
1733}*/
1734
1735
1736
1737
1738#if defined(WIN32) || defined(_WINDOWS)
1739#else
1740void
1741LocalChmodCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1742{
1744 Sys(argc, argv, aip, "/bin/chmod", 1);
1745} /* LocalChmodCmd */
1746#endif
1747
1748
1749
1750void
1751LocalMkdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1752{
1753#if defined(WIN32) || defined(_WINDOWS)
1754 const char *arg;
1755 int i;
1756
1757 for (i = 1; i < argc; i++) {
1758 arg = argv[i];
1759 if (MkDirs(arg, 00755) < 0) {
1760 perror(arg);
1761 }
1762 }
1763#else
1765 Sys(argc, argv, aip, "/bin/mkdir", 0);
1766#endif
1767} /* LocalMkdirCmd */
1768
1769
1770
1771
1772#if defined(WIN32) || defined(_WINDOWS)
1773#else
1774void
1775LocalPageCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1776{
1778 Sys(argc, argv, aip, gPager, 0);
1779} /* LocalPageCmd */
1780#endif
1781
1782
1783
1784
1785void
1786LocalRenameCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1787{
1788#if defined(WIN32) || defined(_WINDOWS)
1789 if (rename(argv[1], argv[2]) < 0) {
1790 perror("rename");
1791 }
1792#else
1794 Sys(argc, argv, aip, "/bin/mv", 1);
1795#endif
1796} /* LocalRenameCmd */
1797
1798
1799
1800
1801void
1802LocalRmCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1803{
1804#if defined(WIN32) || defined(_WINDOWS)
1805 int i;
1806 int result;
1807 LineList ll;
1808 LinePtr lp;
1809
1811 for (i=1; i<argc; i++) {
1812 InitLineList(&ll);
1813 result = FTPLocalGlob(&gConn, &ll, argv[i], (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
1814 if (result < 0) {
1815 FTPPerror(&gConn, result, kErrGlobFailed, "local glob", argv[i]);
1816 } else {
1817 for (lp = ll.first; lp != NULL; lp = lp->next) {
1818 if (lp->line != NULL) {
1819 if (remove(lp->line) < 0)
1820 perror(lp->line);
1821 }
1822 }
1823 }
1825 }
1826#else
1828 Sys(argc, argv, aip, "/bin/rm", 1);
1829#endif
1830} /* LocalRmCmd */
1831
1832
1833
1834
1835void
1836LocalRmdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1837{
1838#if defined(WIN32) || defined(_WINDOWS)
1839 int i;
1840 int result;
1841 LineList ll;
1842 LinePtr lp;
1843
1845 for (i=1; i<argc; i++) {
1846 InitLineList(&ll);
1847 result = FTPLocalGlob(&gConn, &ll, argv[i], (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
1848 if (result < 0) {
1849 FTPPerror(&gConn, result, kErrGlobFailed, "local glob", argv[i]);
1850 } else {
1851 for (lp = ll.first; lp != NULL; lp = lp->next) {
1852 if (lp->line != NULL) {
1853 if (rmdir(lp->line) < 0)
1854 perror(lp->line);
1855 }
1856 }
1857 }
1859 }
1860#else
1862 Sys(argc, argv, aip, "/bin/rmdir", 1);
1863#endif
1864} /* LocalRmdirCmd */
1865
1866
1867
1868
1869/* Displays the current local working directory. */
1870void
1871LocalPwdCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1872{
1874 if (FTPGetLocalCWD(gLocalCWD, sizeof(gLocalCWD)) != NULL) {
1875 Trace(-1, "%s\n", gLocalCWD);
1876 }
1877} /* LocalPwdCmd */
1878
1879
1880
1881
1882/* This is a simple interface to name service. I prefer using this instead
1883 * of nslookup.
1884 */
1885void
1886LookupCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1887{
1888 int i, j;
1889 struct hostent *hp;
1890 const char *host;
1891 char **cpp;
1892 struct in_addr ip_address;
1893 int shortMode, opt;
1894 char ipStr[16];
1895
1897 shortMode = 1;
1898
1899 GetoptReset();
1900 while ((opt = Getopt(argc, argv, "v")) >= 0) {
1901 if (opt == 'v')
1902 shortMode = 0;
1903 else {
1904 PrintCmdUsage(cmdp);
1905 return;
1906 }
1907 }
1908
1909 for (i=gOptInd; i<argc; i++) {
1910 hp = GetHostEntry((host = argv[i]), &ip_address);
1911 if ((i > gOptInd) && (shortMode == 0))
1912 Trace(-1, "\n");
1913 if (hp == NULL) {
1914 Trace(-1, "Unable to get information about site %s.\n", host);
1915 } else if (shortMode) {
1916 MyInetAddr(ipStr, sizeof(ipStr), hp->h_addr_list, 0);
1917 Trace(-1, "%-40s %s\n", hp->h_name, ipStr);
1918 } else {
1919 Trace(-1, "%s:\n", host);
1920 Trace(-1, " Name: %s\n", hp->h_name);
1921 for (cpp = hp->h_aliases; *cpp != NULL; cpp++)
1922 Trace(-1, " Alias: %s\n", *cpp);
1923 for (j = 0, cpp = hp->h_addr_list; *cpp != NULL; cpp++, ++j) {
1924 MyInetAddr(ipStr, sizeof(ipStr), hp->h_addr_list, j);
1925 Trace(-1, " Address: %s\n", ipStr);
1926 }
1927 }
1928 }
1929} /* LookupCmd */
1930
1931
1932
1933/* Directory listing in a machine-readable format;
1934 * Mostly for debugging, since NcFTP uses MLSD automatically when it needs to.
1935 */
1936void
1937MlsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
1938{
1939 int i;
1940 int opt;
1941 LinePtr linePtr, nextLinePtr;
1942 int result;
1943 LineList dirContents;
1944 int mlsd = 1, x;
1945 const char *item;
1946
1948 GetoptReset();
1949 while ((opt = Getopt(argc, argv, "dt")) >= 0) {
1950 if ((opt == 'd') || (opt == 't')) {
1951 /* Use MLST instead of MLSD,
1952 * which is similar to using "ls -d" instead of "ls".
1953 */
1954 mlsd = 0;
1955 } else {
1956 PrintCmdUsage(cmdp);
1957 return;
1958 }
1959 }
1960
1961 i = gOptInd;
1962 if (i == argc) {
1963 /* No args, do current directory. */
1964 x = 1;
1965 item = "";
1966 if ((result = FTPListToMemory2(&gConn, item, &dirContents, (mlsd == 0) ? "-d" : "", 1, &x)) < 0) {
1967 if (mlsd != 0) {
1968 FTPPerror(&gConn, result, 0, "Could not MLSD", item);
1969 } else {
1970 FTPPerror(&gConn, result, 0, "Could not MLST", item);
1971 }
1972 } else {
1973 for (linePtr = dirContents.first;
1974 linePtr != NULL;
1975 linePtr = nextLinePtr)
1976 {
1977 nextLinePtr = linePtr->next;
1978 (void) fprintf(stdout, "%s\n", linePtr->line);
1979 Trace(0, "%s\n", linePtr->line);
1980 }
1981 }
1982 }
1983
1984 for ( ; i<argc; i++) {
1985 x = 1;
1986 item = argv[i];
1987 if ((result = FTPListToMemory2(&gConn, item, &dirContents, (mlsd == 0) ? "-d" : "", 1, &x)) < 0) {
1988 if (mlsd != 0) {
1989 FTPPerror(&gConn, result, 0, "Could not MLSD", item);
1990 } else {
1991 FTPPerror(&gConn, result, 0, "Could not MLST", item);
1992 }
1993 } else {
1994 for (linePtr = dirContents.first;
1995 linePtr != NULL;
1996 linePtr = nextLinePtr)
1997 {
1998 nextLinePtr = linePtr->next;
1999 (void) fprintf(stdout, "%s\n", linePtr->line);
2000 Trace(0, "%s\n", linePtr->line);
2001 }
2002 }
2003 }
2004} /* MlsCmd */
2005
2006
2007
2008
2009/* Create directories on the remote system. */
2010void
2011MkdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2012{
2013 int i;
2014 int opt;
2015 int result;
2016 int recurseFlag = kRecursiveNo;
2017
2019 GetoptReset();
2020 while ((opt = Getopt(argc, argv, "p")) >= 0) {
2021 if (opt == 'p') {
2022 /* Try creating intermediate directories if they
2023 * don't exist.
2024 *
2025 * For example if only /pub/stuff existed, and you
2026 * do a "mkdir -p /pub/stuff/a/b/c", the "a" and "b"
2027 * directories would also be created.
2028 */
2029 recurseFlag = kRecursiveYes;
2030 } else {
2031 PrintCmdUsage(cmdp);
2032 return;
2033 }
2034 }
2035
2036 for (i=gOptInd; i<argc; i++) {
2037 result = FTPMkdir(&gConn, argv[i], recurseFlag);
2038 if (result < 0)
2039 FTPPerror(&gConn, result, kErrMKDFailed, "Could not mkdir", argv[i]);
2040 }
2041
2042 /* Really should just flush only the modified directories... */
2043 FlushLsCache();
2044} /* MkdirCmd */
2045
2046
2047
2048/*VARARGS*/
2049static void
2050OpenMsg(const char *const fmt, ...)
2051{
2052 va_list ap;
2053 char buf[512];
2054 size_t len, padlim;
2055
2056 padlim = (size_t) gScreenColumns;
2057 if ((size_t) gScreenColumns > (sizeof(buf) - 1))
2058 padlim = sizeof(buf) - 1;
2059
2060 va_start(ap, fmt);
2061#ifdef HAVE_VSNPRINTF
2062 len = (size_t) vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
2063 va_end(ap);
2064 buf[sizeof(buf) - 1] = '\0';
2065#else
2066 (void) vsprintf(buf, fmt, ap);
2067 va_end(ap);
2068 len = strlen(buf);
2069#endif
2070 buf[len] = '\0';
2071 Trace(9, "%s\n", buf);
2072 for (; len < padlim; len++)
2073 buf[len] = ' ';
2074 buf[len] = '\0';
2075
2076#if 0
2077 (void) fprintf(stdout, "\r%s", buf);
2078#else
2079 (void) fprintf(stdout, "%s\r", buf);
2080#endif
2081 (void) fflush(stdout);
2082} /* OpenMsg */
2083
2084
2085
2086
2087static void
2089{
2090 gUnusedArg = (cipUNUSED != NULL);
2091 if ((rp->printMode & kResponseNoPrint) != 0)
2092 return;
2093#if 0
2094 if (rp->code == 331) /* Skip: "331 User name okay, need password." */
2095 return;
2096#else
2097 /* This is only used to print errors. */
2098 if (rp->code < 400)
2099 return;
2100#endif
2101 PrintResp(&rp->msg);
2102} /* NcFTPOpenPrintResponseProc */
2103
2104
2105
2106static void
2108{
2109 gUnusedArg = (cipUNUSED != NULL);
2110 (void) printf("\n");
2111 PrintResp(&rp->msg);
2112 OpenMsg("Logging in...");
2113} /* NcFTPOnConnectMessageProc */
2114
2115
2116
2117static void
2119{
2120 gUnusedArg = (cipUNUSED != NULL);
2121 (void) printf("\n");
2122 PrintResp(&rp->msg);
2123 OpenMsg("Logging in...");
2124} /* NcFTPOnLoginMessageProc */
2125
2126
2127
2128
2129static void
2130NcFTPRedialStatusProc(const FTPCIPtr cipUNUSED, int mode, int val)
2131{
2132 gUnusedArg = (cipUNUSED != NULL);
2133 if (mode == kRedialStatusDialing) {
2134 if (val > 0) {
2135 OpenMsg("Redialing (try %d)...", val);
2136 sleep(1); /* Give time for message to stay */
2137 }
2138 } else if (mode == kRedialStatusSleeping) {
2139 OpenMsg("Sleeping %d seconds...", val);
2140 }
2141} /* NcFTPRedialStatusProc */
2142
2143
2144
2145
2146static void
2147NcFTPGetPassphraseProc(const FTPCIPtr cip, LineListPtr pwPrompt, char *pass, size_t dsize)
2148{
2149 LinePtr lp;
2150
2151 (void) printf("\nPassword requested by %s for user \"%s\".\n\n",
2152 cip->host,
2153 cip->user
2154 );
2155
2156 for (lp = pwPrompt->first; lp != NULL; lp = lp->next) {
2157 (void) printf(" %s\n", lp->line);
2158 }
2159 (void) printf("\n");
2160 (void) gl_getpass("Password: ", pass, (int) dsize);
2161} /* NcFTPGetPassphraseProc */
2162
2163
2164
2165
2166/* Attempts to establish a new FTP connection to a remote host. */
2167int
2169{
2170 int result;
2171 char ipstr[128];
2172 char ohost[128];
2173#ifdef SIGALRM
2174 sigproc_t osigalrm;
2175#endif
2176 char prompt[256];
2177
2179 (void) STRNCPY(ohost, gConn.host);
2180 OpenMsg("Resolving %s...", ohost);
2181 if ((gLoadedBm != 0) && (gBm.lastIP[0] != '\0')) {
2182 result = GetHostByName(ipstr, sizeof(ipstr), ohost, 3);
2183 if (result < 0) {
2184 (void) STRNCPY(ipstr, gBm.lastIP);
2185 result = 0;
2186 } else {
2187 result = GetHostByName(ipstr, sizeof(ipstr), ohost, 7);
2188 }
2189 } else {
2190 result = GetHostByName(ipstr, sizeof(ipstr), ohost, 10);
2191 }
2192 if (result < 0) {
2193 (void) printf("\n");
2194 (void) printf("Unknown host \"%s\".\n", ohost);
2195 return (-1);
2196 }
2197 (void) STRNCPY(gConn.host, ipstr);
2198 OpenMsg("Connecting to %s...", ipstr);
2199 } else {
2200 OpenMsg("Connecting to %s via %s...", gConn.host, gConn.firewallHost);
2201 Trace(0, "Fw: %s Type: %d User: %s Pass: %s Port: %u\n",
2205 (gConn.firewallPass[0] == '\0') ? "(none)" : "********",
2207 );
2208 Trace(0, "FwExceptions: %s\n", gFirewallExceptionList);
2209 if (strchr(gLib.ourHostName, '.') == NULL) {
2210 Trace(0, "NOTE: Your domain name could not be detected.\n");
2212 Trace(0, " Make sure you manually add your domain name to firewall-exception-list.\n");
2213 }
2214 }
2215 }
2216
2217 if (gConn.firewallPass[0] == '\0') {
2218 switch (gConn.firewallType) {
2219 case kFirewallNotInUse:
2220 break;
2222 break;
2224 case kFirewallSiteSite:
2225 case kFirewallOpenSite:
2229 (void) printf("\n");
2230 (void) STRNCPY(prompt, "Password for firewall user \"");
2231 (void) STRNCAT(prompt, gConn.firewallUser);
2232 (void) STRNCAT(prompt, "\" at ");
2233 (void) STRNCAT(prompt, gConn.firewallHost);
2234 (void) STRNCAT(prompt, ": ");
2235 (void) gl_getpass(prompt, gConn.firewallPass, sizeof(gConn.firewallPass));
2236 break;
2237 }
2238 }
2239
2240 if ((gConn.user[0] != '\0') && (strcmp(gConn.user, "anonymous") != 0) && (strcmp(gConn.user, "ftp") != 0)) {
2242 }
2243
2244 /* Register our callbacks. */
2249
2250#ifdef SIGALRM
2251 osigalrm = NcSignal(SIGALRM, (FTPSigProc) SIG_IGN);
2253 (void) NcSignal(SIGALRM, osigalrm);
2254#else
2256#endif
2257
2259 (void) STRNCPY(gConn.host, ohost); /* Put it back. */
2260 if (result >= 0) {
2261 (void) time(&gBm.lastCall);
2263 OpenMsg("Logged in to %s.", gConn.host);
2264 (void) printf("\n");
2265
2266 /* Remove callback. */
2268
2269 /* Need to note what our "root" was before we change it. */
2271 (void) STRNCPY(gRemoteCWD, "/"); /* Guess! */
2272 } else {
2274 }
2276
2277 /* If the bookmark specified a remote directory, change to it now. */
2278 if ((gLoadedBm != 0) && (gBm.dir[0] != '\0')) {
2279 result = Chdirs(&gConn, gBm.dir);
2280 if (result < 0) {
2281 FTPPerror(&gConn, result, kErrCWDFailed, "Could not chdir to previous directory", gBm.dir);
2282 }
2283 Trace(-1, "Current remote directory is %s.\n", gRemoteCWD);
2284 }
2285
2286 /* If the bookmark specified a local directory, change to it now. */
2287 if ((gLoadedBm != 0) && (gBm.ldir[0] != '\0')) {
2288 (void) chdir(gBm.ldir);
2290 if (FTPGetLocalCWD(gLocalCWD, sizeof(gLocalCWD)) != NULL) {
2291 Trace(-1, "Current local directory is %s.\n", gLocalCWD);
2292 }
2293 }
2294
2295 /* Identify the FTP client type to the server. Most don't understand this yet. */
2297 (void) FTPCmd(&gConn, "CLNT NcFTP %.5s %s", gVersion + 11, gOS);
2298 return (0);
2299 } else {
2300 FTPPerror(&gConn, result, 0, "Could not open host", gConn.host);
2301 }
2302
2303 /* Remove callback. */
2305 (void) printf("\n");
2306 return (-1);
2307} /* Open */
2308
2309
2310
2311
2312/* Chooses a new remote system to connect to, and attempts to establish
2313 * a new FTP connection. This function is in charge of collecting the
2314 * information needed to do the open, and then doing it.
2315 */
2316void
2317OpenCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2318{
2319 int c;
2320 int opts = 0;
2321 int uOptInd = 0;
2322 int n;
2323 int rc;
2324 char url[256];
2325 char urlfile[128];
2326 int directoryURL = 0;
2327 LineList cdlist;
2328 LinePtr lp;
2329 char prompt[256];
2330
2332 FlushLsCache();
2333 CloseHost();
2334 gLoadedBm = 0;
2336
2337 /* Need to find the host argument first. */
2338 GetoptReset();
2339 while ((c = Getopt(argc, argv, "aP:u:p:J:rd:g:")) > 0) switch(c) {
2340 case 'u':
2341 uOptInd = gOptInd + 1;
2342 opts++;
2343 break;
2344 default:
2345 opts++;
2346 }
2347 if (gOptInd < argc) {
2350 } else if (uOptInd > argc) {
2351 /* Special hack for v2.4.2 compatibility */
2352 (void) STRNCPY(gConn.host, argv[argc - 1]);
2353 (void) STRNCPY(url, argv[argc - 1]);
2354 } else {
2355 /* No host arg */
2356 if (opts > 0) {
2357 PrintCmdUsage(cmdp);
2358 } else if (RunBookmarkEditor(gConn.host, sizeof(gConn.host)) == 0) {
2359 if (gConn.host[0] != '\0') {
2360 gLoadedBm = 1;
2361 /* okay, now fall through */
2362 } else {
2363 return;
2364 }
2365 } else if (PrintHosts() <= 0) {
2366 (void) printf("You haven't bookmarked any FTP sites.\n");
2367 (void) printf("Before closing a site, you can use the \"bookmark\" command to save the current\nhost and directory for next time.\n");
2368 return;
2369 } else {
2370 (void) printf("\nTo use a bookmark, use the \"open\" command with the name of the bookmark.\n");
2371 return;
2372 }
2373 }
2374
2375 InitLineList(&cdlist);
2376
2377 if (GetBookmark(gConn.host, &gBm) >= 0) {
2378 gLoadedBm = 1;
2386 gConn.port = gBm.port;
2387
2388 /* Note: Version 3 only goes off of the
2389 * global "gDataPortMode" setting instead of
2390 * setting the dataPortMode on a per-site
2391 * basis.
2392 */
2394 } else {
2396
2397 memcpy(&gTmpURLConn, &gConn, sizeof(gTmpURLConn));
2398 rc = DecodeDirectoryURL(&gTmpURLConn, url, &cdlist, urlfile, sizeof(urlfile));
2399 if (rc == kMalformedURL) {
2400 (void) fprintf(stdout, "Malformed URL: %s\n", url);
2401 DisposeLineListContents(&cdlist);
2402 return;
2403 } else if (rc == kNotURL) {
2404 directoryURL = 0;
2405 } else {
2406 /* It was a URL. */
2407 if (urlfile[0] != '\0') {
2408 /* It was obviously not a directory */
2409 (void) fprintf(stdout, "Use ncftpget or ncftpput to handle file URLs.\n");
2410 DisposeLineListContents(&cdlist);
2411 return;
2412 }
2413 memcpy(&gConn, &gTmpURLConn, sizeof(gConn));
2414 directoryURL = 1;
2415 }
2416 }
2417
2424 }
2425
2426 GetoptReset();
2427 while ((c = Getopt(argc, argv, "aP:u:p:J:j:rd:g:")) > 0) switch(c) {
2428 case 'J':
2429 case 'j':
2431 break;
2432 case 'a':
2433 (void) STRNCPY(gConn.user, "anonymous");
2434 (void) STRNCPY(gConn.pass, "");
2435 (void) STRNCPY(gConn.acct, "");
2436 break;
2437 case 'P':
2439 break;
2440 case 'u':
2441 if (uOptInd <= argc)
2443 break;
2444 case 'p':
2445 (void) STRNCPY(gConn.pass, gOptArg); /* Don't recommend doing this! */
2446 break;
2447 case 'r':
2448 /* redial is on by default */
2449 break;
2450 case 'g':
2451 n = atoi(gOptArg);
2452 gConn.maxDials = n;
2453 break;
2454 case 'd':
2455 n = atoi(gOptArg);
2456 if (n >= 10)
2458 break;
2459 default:
2460 PrintCmdUsage(cmdp);
2461 DisposeLineListContents(&cdlist);
2462 return;
2463 }
2464
2465 if (uOptInd > argc) {
2466 (void) STRNCPY(prompt, "Username at ");
2467 (void) STRNCAT(prompt, gConn.host);
2468 (void) STRNCAT(prompt, ": ");
2469 (void) gl_getpass(prompt, gConn.user, sizeof(gConn.user));
2470 }
2471
2472 rc = DoOpen();
2473 if ((rc >= 0) && (directoryURL != 0)) {
2474 for (lp = cdlist.first; lp != NULL; lp = lp->next) {
2475 rc = FTPChdir(&gConn, lp->line);
2476 if (rc != kNoErr) {
2477 FTPPerror(&gConn, rc, kErrCWDFailed, "Could not chdir to", lp->line);
2478 break;
2479 }
2480 }
2481 rc = FTPGetCWD(&gConn, gRemoteCWD, sizeof(gRemoteCWD));
2482 if (rc != kNoErr) {
2484 } else {
2485 (void) printf("Current remote directory is %s.\n", gRemoteCWD);
2486 }
2487 }
2488 DisposeLineListContents(&cdlist);
2489} /* OpenCmd */
2490
2491
2492
2493
2494/* View a remote file through the users $PAGER. */
2495void
2496PageCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2497{
2498 int result;
2499 int i;
2500 FILE *volatile stream;
2501#if defined(WIN32) || defined(_WINDOWS)
2502#else
2503 int sj;
2504 vsigproc_t osigpipe, osigint;
2505#endif
2506
2508 stream = OpenPager();
2509 if (stream == NULL) {
2510 return;
2511 }
2512
2513#if defined(WIN32) || defined(_WINDOWS)
2514#else
2515
2516#ifdef HAVE_SIGSETJMP
2517 osigpipe = osigint = (sigproc_t) 0;
2518 sj = sigsetjmp(gCancelJmp, 1);
2519#else /* HAVE_SIGSETJMP */
2520 osigpipe = osigint = (sigproc_t) 0;
2521 sj = setjmp(gCancelJmp);
2522#endif /* HAVE_SIGSETJMP */
2523
2524 if (sj != 0) {
2525 /* Caught a signal. */
2528 (void) NcSignal(SIGPIPE, osigpipe);
2529 (void) NcSignal(SIGINT, osigint);
2530 (void) fprintf(stderr, "Canceled.\n");
2531 Trace(0, "Canceled because of signal %d.\n", gGotSig);
2532 gMayCancelJmp = 0;
2533 return;
2534 } else {
2535 osigpipe = NcSignal(SIGPIPE, Cancel);
2536 osigint = NcSignal(SIGINT, Cancel);
2537 gMayCancelJmp = 1;
2538 }
2539
2540#endif
2541
2542 for (i=1; i<argc; i++) {
2544 if (result < 0) {
2545 if (errno != EPIPE) {
2547 stream = NULL;
2549 }
2550 break;
2551 }
2552 }
2553
2554#if defined(WIN32) || defined(_WINDOWS)
2556#else
2559 (void) NcSignal(SIGPIPE, osigpipe);
2560 (void) NcSignal(SIGINT, osigint);
2561#endif
2562 gMayCancelJmp = 0;
2563} /* PageCmd */
2564
2565
2566
2567
2568static int
2570 const char *volatile localpath,
2571 volatile longest_int localsize,
2572 volatile time_t localmtime,
2573 const char *volatile *remotepath,
2574 volatile longest_int remotesize,
2575 volatile time_t remotemtime,
2576 volatile longest_int *volatile startPoint)
2577{
2578 int zaction = kConfirmResumeProcSaidBestGuess;
2579 char tstr[80], ans[32];
2580 static char newname[128]; /* arrggh... static. */
2581
2583 return (gResumeAnswerAll);
2584
2585 if (gAutoResume != 0)
2587
2588 printf("\nThe remote file \"%s\" already exists.\n", *remotepath);
2589
2590 if ((localmtime != kModTimeUnknown) && (localsize != kSizeUnknown)) {
2591 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &localmtime));
2592 (void) printf(
2593#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
2594 "\tLocal: %12lld bytes, dated %s.\n",
2595#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
2596 "\tLocal: %12qd bytes, dated %s.\n",
2597#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
2598 "\tLocal: %12I64d bytes, dated %s.\n",
2599#else
2600 "\tLocal: %12ld bytes, dated %s.\n",
2601#endif
2602 localsize,
2603 tstr
2604 );
2605 if ((remotemtime == localmtime) && (remotesize == localsize)) {
2606 (void) printf("\t(Files are identical, skipped)\n\n");
2608 }
2609 } else if (localsize != kSizeUnknown) {
2610 (void) printf(
2611#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
2612 "\tLocal: %12lld bytes, date unknown.\n",
2613#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
2614 "\tLocal: %12qd bytes, date unknown.\n",
2615#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
2616 "\tLocal: %12I64d bytes, date unknown.\n",
2617#else
2618 "\tLocal: %12ld bytes, date unknown.\n",
2619#endif
2620 localsize
2621 );
2622 } else if (localmtime != kModTimeUnknown) {
2623 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &localmtime));
2624 (void) printf(
2625 "\tLocal: size unknown, dated %s.\n",
2626 tstr
2627 );
2628 }
2629
2630 tstr[sizeof(tstr) - 1] = '\0';
2631 if ((remotemtime != kModTimeUnknown) && (remotesize != kSizeUnknown)) {
2632 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &remotemtime));
2633 (void) printf(
2634#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
2635 "\tRemote: %12lld bytes, dated %s.\n",
2636#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
2637 "\tRemote: %12qd bytes, dated %s.\n",
2638#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
2639 "\tRemote: %12I64d bytes, dated %s.\n",
2640#else
2641 "\tRemote: %12ld bytes, dated %s.\n",
2642#endif
2643 remotesize,
2644 tstr
2645 );
2646 } else if (remotesize != kSizeUnknown) {
2647 (void) printf(
2648#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
2649 "\tRemote: %12lld bytes, date unknown.\n",
2650#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
2651 "\tRemote: %12qd bytes, date unknown.\n",
2652#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
2653 "\tRemote: %12I64d bytes, date unknown.\n",
2654#else
2655 "\tRemote: %12ld bytes, date unknown.\n",
2656#endif
2657 remotesize
2658 );
2659 } else if (remotemtime != kModTimeUnknown) {
2660 (void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &remotemtime));
2661 (void) printf(
2662 "\tRemote: size unknown, dated %s.\n",
2663 tstr
2664 );
2665 }
2666
2667 printf("\n");
2668 fflush(stdin);
2669 (void) memset(ans, 0, sizeof(ans));
2670 for (;;) {
2671 (void) printf("\t[O]verwrite?");
2672 if ((gConn.hasREST == kCommandAvailable) && (remotesize < localsize))
2673 printf(" [R]esume?");
2674 printf(" [A]ppend to? [S]kip? [N]ew Name?\n");
2675 (void) printf("\t[O!]verwrite all?");
2676 if ((gConn.hasREST == kCommandAvailable) && (remotesize < localsize))
2677 printf(" [R!]esume all?");
2678 printf(" [S!]kip all? [C]ancel > ");
2679 (void) fgets(ans, sizeof(ans) - 1, stdin);
2680 switch ((int) ans[0]) {
2681 case 'c':
2682 case 'C':
2683 ans[0] = 'C';
2684 ans[1] = '\0';
2686 break;
2687 case 'o':
2688 case 'O':
2689 ans[0] = 'O';
2691 break;
2692 case 'r':
2693 case 'R':
2695 printf("\tResume is not available on this server.\n\n");
2696 ans[0] = '\0';
2697 break;
2698 } else if (remotesize > localsize) {
2699 printf("\tCannot resume when remote file is already larger than the local file.\n\n");
2700 ans[0] = '\0';
2701 break;
2702 } else if (remotesize == localsize) {
2703 printf("\tRemote file is already the same size as the local file.\n\n");
2704 ans[0] = '\0';
2705 break;
2706 }
2707 ans[0] = 'R';
2708 *startPoint = remotesize;
2710 if (OneTimeMessage("auto-resume") != 0) {
2711 printf("\n\tNOTE: If you want NcFTP to guess automatically, \"set auto-resume yes\"\n\n");
2712 }
2713 break;
2714 case 's':
2715 case 'S':
2716 ans[0] = 'S';
2718 break;
2719 case 'n':
2720 case 'N':
2721 ans[0] = 'N';
2722 ans[1] = '\0';
2724 break;
2725 case 'a':
2726 case 'A':
2727 ans[0] = 'A';
2728 ans[1] = '\0';
2730 break;
2731 case 'g':
2732 case 'G':
2733 ans[0] = 'G';
2735 break;
2736 default:
2737 ans[0] = '\0';
2738 }
2739 if (ans[0] != '\0')
2740 break;
2741 }
2742
2743 if (ans[0] == 'N') {
2744 (void) memset(newname, 0, sizeof(newname));
2745 printf("\tSave as: ");
2746 fflush(stdin);
2747 (void) fgets(newname, sizeof(newname) - 1, stdin);
2748 newname[strlen(newname) - 1] = '\0';
2749 if (newname[0] == '\0') {
2750 /* Nevermind. */
2751 printf("Skipped %s.\n", localpath);
2753 } else {
2754 *remotepath = newname;
2755 }
2756 }
2757
2758 if (ans[1] == '!')
2759 gResumeAnswerAll = zaction;
2760 return (zaction);
2761} /* NcFTPConfirmResumeUploadProc */
2762
2763
2764
2765
2766/* Upload files to the remote system, permissions permitting. */
2767void
2768PutCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2769{
2770 int opt;
2771 int renameMode = 0;
2772 int recurseFlag = kRecursiveNo;
2773 int appendFlag = kAppendNo;
2774 const char *dstdir = NULL;
2775 int rc;
2776 int i;
2777 int doGlob;
2778 int xtype = gBm.xferType;
2779 int nD = 0;
2780 int deleteFlag = kDeleteNo;
2781 int resumeFlag = kResumeYes;
2782 char pattern[256];
2783 vsigproc_t osigint;
2784 ConfirmResumeUploadProc confirmProc;
2785
2786 confirmProc = NcFTPConfirmResumeUploadProc;
2787 gResumeAnswerAll = kConfirmResumeProcNotUsed; /* Ask at least once each time */
2789 GetoptReset();
2790 while ((opt = Getopt(argc, argv, "AafZzrRD")) >= 0) switch (opt) {
2791 case 'a':
2792 xtype = kTypeAscii;
2793 break;
2794 case 'A':
2795 /* Append to remote files, instead of truncating
2796 * them first.
2797 */
2798 appendFlag = kAppendYes;
2799 break;
2800 case 'f':
2801 case 'Z':
2802 /* Do not try to resume a download, even if it
2803 * appeared that some of the file was transferred
2804 * already.
2805 */
2806 resumeFlag = kResumeNo;
2807 confirmProc = NoConfirmResumeUploadProc;
2808 break;
2809 case 'z':
2810 /* Special flag that lets you specify the
2811 * destination file. Normally a "put" will
2812 * write the file by the same name as the
2813 * local file's basename.
2814 */
2815 renameMode = 1;
2816 break;
2817 case 'r':
2818 case 'R':
2819 recurseFlag = kRecursiveYes;
2820 /* If the item is a directory, get the
2821 * directory and all its contents.
2822 */
2823 recurseFlag = kRecursiveYes;
2824 break;
2825 case 'D':
2826 /* You can delete the local file after
2827 * you uploaded it successfully by using
2828 * the -DD option. It requires two -D's
2829 * to minimize the odds of accidentally
2830 * using a single -D.
2831 */
2832 nD++;
2833 break;
2834 default:
2835 PrintCmdUsage(cmdp);
2836 return;
2837 }
2838
2839 if (nD >= 2)
2840 deleteFlag = kDeleteYes;
2841
2842 if (renameMode != 0) {
2843 if (gOptInd > (argc - 2)) {
2844 PrintCmdUsage(cmdp);
2845 (void) fprintf(stderr, "\nFor put with rename, try \"put -z local-path-name remote-path-name\".\n");
2846 return;
2847 }
2848 osigint = NcSignal(SIGINT, XferCanceller);
2849 rc = FTPPutOneFile3(&gConn, argv[gOptInd], argv[gOptInd + 1], xtype, (-1), appendFlag, NULL, NULL, resumeFlag, deleteFlag, confirmProc, 0);
2850 if (rc < 0)
2852 } else {
2853 osigint = NcSignal(SIGINT, XferCanceller);
2854 for (i=gOptInd; i<argc; i++) {
2855 doGlob = (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes;
2856 STRNCPY(pattern, argv[i]);
2858 rc = FTPPutFiles3(&gConn, pattern, dstdir, recurseFlag, doGlob, xtype, appendFlag, NULL, NULL, resumeFlag, deleteFlag, confirmProc, 0);
2859 if (rc < 0)
2861 }
2862 }
2863
2864 /* Really should just flush only the modified directories... */
2865 FlushLsCache();
2866
2867 (void) NcSignal(SIGINT, osigint);
2868 (void) fflush(stdin);
2869} /* PutCmd */
2870
2871
2872
2873
2874/* Displays the current remote working directory path. */
2875void
2876PwdCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2877{
2878 int result;
2879 char url[256];
2880 char olddir[256];
2881
2883#ifdef USE_WHAT_SERVER_SAYS_IS_CWD
2885 CurrentURL(url, sizeof(url), 0);
2886 if (result < 0) {
2887 FTPPerror(&gConn, result, kErrPWDFailed, "Could not get remote working directory", NULL);
2888 } else {
2889 Trace(-1, "%s\n", url);
2890 }
2891#else /* USE_CLIENT_SIDE_CALCULATED_CWD */
2892
2893 /* Display the current working directory, as
2894 * maintained by us.
2895 */
2896 CurrentURL(url, sizeof(url), 0);
2897 Trace(-1, " %s\n", url);
2898 olddir[sizeof(olddir) - 2] = '\0';
2899 STRNCPY(olddir, gRemoteCWD);
2900
2901 /* Now see what the server reports as the CWD.
2902 * Because of symlinks, it could be different
2903 * from what we are using.
2904 */
2906 if ((result == kNoErr) && (strcmp(gRemoteCWD, olddir) != 0)) {
2907 Trace(-1, "This URL is also valid on this server:\n");
2908 CurrentURL(url, sizeof(url), 0);
2909 Trace(-1, " %s\n", url);
2910 if (olddir[sizeof(olddir) - 2] == '\0') {
2911 /* Go back to using the non-resolved version. */
2912 STRNCPY(gRemoteCWD, olddir);
2913 }
2914 }
2915#endif
2916} /* PwdCmd */
2917
2918
2919
2920
2921/* Sets a flag so that the command shell exits. */
2922void
2923QuitCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2924{
2926 gDoneApplication = 1;
2927} /* QuitCmd */
2928
2929
2930
2931
2932/* Send a command string to the FTP server, verbatim. */
2933void
2934QuoteCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2935{
2936 char cmdbuf[256];
2937 int i;
2938
2940 (void) STRNCPY(cmdbuf, argv[1]);
2941 for (i=2; i<argc; i++) {
2942 (void) STRNCAT(cmdbuf, " ");
2943 (void) STRNCAT(cmdbuf, argv[i]);
2944 }
2945 (void) FTPCmd(&gConn, "%s", cmdbuf);
2947} /* QuoteCmd */
2948
2949
2950
2951
2952/* Expands a remote regex. Mostly a debugging command. */
2953void
2954RGlobCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2955{
2956 int i;
2957 int result;
2958 int np = 0;
2959 LineList ll;
2960 LinePtr lp;
2961
2963 for (i=1; i<argc; i++) {
2964 InitLineList(&ll);
2965 result = FTPRemoteGlob(&gConn, &ll, argv[i], (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
2966 if (result < 0) {
2967 FTPPerror(&gConn, result, kErrGlobFailed, "remote glob", argv[i]);
2968 } else {
2969 for (lp = ll.first; lp != NULL; lp = lp->next) {
2970 if (lp->line != NULL) {
2971 if (np > 0)
2972 (void) printf(" ");
2973 (void) printf("%s", lp->line);
2974 np++;
2975 }
2976 }
2977 }
2979 }
2980 (void) printf("\n");
2981} /* RGlobCmd */
2982
2983
2984
2985
2986/* Renames a remote file. */
2987void
2988RenameCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
2989{
2990 int result;
2991
2993 result = FTPRename(&gConn, argv[1], argv[2]);
2994 if (result < 0)
2995 FTPPerror(&gConn, result, kErrRenameFailed, "rename", argv[1]);
2996 else {
2997 /* Really should just flush only the modified directories... */
2998 FlushLsCache();
2999 }
3000} /* RenameCmd */
3001
3002
3003
3004
3005/* Removes a directory on the remote host. */
3006void
3007RmdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3008{
3009 int result;
3010 int i, c;
3011 int recursive = kRecursiveNo;
3012
3014 GetoptReset();
3015 while ((c = Getopt(argc, argv, "rf")) > 0) switch(c) {
3016 case 'r':
3017 recursive = kRecursiveYes;
3018 break;
3019 case 'f':
3020 /* ignore */
3021 break;
3022 default:
3023 PrintCmdUsage(cmdp);
3024 return;
3025 }
3026 for (i=gOptInd; i<argc; i++) {
3027 result = FTPRmdir(&gConn, argv[i], recursive, (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
3028 if (result < 0)
3029 FTPPerror(&gConn, result, kErrRMDFailed, "rmdir", argv[i]);
3030 }
3031
3032 /* Really should just flush only the modified directories... */
3033 FlushLsCache();
3034} /* RmdirCmd */
3035
3036
3037
3038
3039/* Asks the remote server for help on how to use its server. */
3040void
3041RmtHelpCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3042{
3043 int i, result;
3044 LineList ll;
3045 LinePtr lp;
3046
3048 if (argc == 1) {
3050 if (result < 0)
3051 FTPPerror(&gConn, result, kErrHELPFailed, "HELP failed", NULL);
3052 else {
3053 for (lp = ll.first; lp != NULL; lp = lp->next)
3054 (void) printf("%s\n", lp->line);
3055 }
3057 } else {
3058 for (i=1; i<argc; i++) {
3060 if (result < 0)
3061 FTPPerror(&gConn, result, kErrHELPFailed, "HELP failed for", argv[i]);
3062 else {
3063 for (lp = ll.first; lp != NULL; lp = lp->next)
3064 (void) printf("%s\n", lp->line);
3065 }
3067 }
3068 }
3069} /* RmtHelpCmd */
3070
3071
3072
3073
3074/* Show and/or change customizable program settings. These changes are saved
3075 * at the end of the program's run.
3076 */
3077void
3078SetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3079{
3081 if (argc < 2)
3082 Set(NULL, NULL);
3083 else if (argc == 2)
3084 Set(argv[1], NULL);
3085 else
3086 Set(argv[1], argv[2]);
3087} /* SetCmd */
3088
3089
3090
3091
3092/* Local shell escape. */
3093void
3094ShellCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3095{
3096#if defined(WIN32) || defined(_WINDOWS)
3097#else
3098 const char *cp;
3099 pid_t pid;
3100 int status;
3101 vsigproc_t osigint;
3102
3103 osigint = NcSignal(SIGINT, (FTPSigProc) SIG_IGN);
3105 pid = fork();
3106 if (pid < (pid_t) 0) {
3107 perror("fork");
3108 } else if (pid == 0) {
3109 cp = strrchr(gShell, '/');
3110 if (cp == NULL)
3111 cp = gShell; /* bug */
3112 else
3113 cp++;
3114 if (argc == 1) {
3115 execl(gShell, cp, NULL);
3116 perror(gShell);
3117 exit(1);
3118 } else {
3119 execvp(argv[1], (char **) argv + 1);
3120 perror(gShell);
3121 exit(1);
3122 }
3123 } else {
3124 /* parent */
3125 for (;;) {
3126#ifdef HAVE_WAITPID
3127 if ((waitpid(pid, &status, 0) < 0) && (errno != EINTR))
3128 break;
3129#else
3130 if ((wait(&status) < 0) && (errno != EINTR))
3131 break;
3132#endif
3133 if (WIFEXITED(status) || WIFSIGNALED(status))
3134 break; /* done */
3135 }
3136 }
3137 (void) NcSignal(SIGINT, osigint);
3138#endif
3139} /* ShellCmd */
3140
3141
3142
3143
3144/* Send a command string to the FTP server, verbatim. */
3145void
3146SiteCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3147{
3148 char cmdbuf[256];
3149 int i;
3150
3152 (void) STRNCPY(cmdbuf, "SITE");
3153 for (i=1; i<argc; i++) {
3154 (void) STRNCAT(cmdbuf, " ");
3155 (void) STRNCAT(cmdbuf, argv[i]);
3156 }
3157 (void) FTPCmd(&gConn, "%s", cmdbuf);
3159} /* SiteCmd */
3160
3161
3162
3163
3164static time_t
3166{
3167 char *cp;
3168 char s2[64];
3169 time_t now, when;
3170 int toff, n, c, hr, min;
3171 struct tm lt, *ltp;
3172
3173 STRNCPY(s2, s);
3174 cp = strchr(s2, ':');
3175 if ((s2[0] == 'n') || (s2[0] == '+')) {
3176 /* "now + XX hours" or
3177 * "+ XX hours"
3178 */
3179 cp = strchr(s2, '+');
3180 if (cp == NULL)
3181 return ((time_t) -1);
3182 ++cp;
3183 toff = 0;
3184 n = 0;
3185 (void) sscanf(cp, "%d%n", &toff, &n);
3186 if ((n <= 0) || (toff <= 0))
3187 return ((time_t) -1);
3188 cp += n;
3189 while ((*cp != '\0') && (!isalpha(*cp)))
3190 cp++;
3191 c = *cp;
3192 if (isupper(c))
3193 c = tolower(c);
3194 if (c == 's') {
3195 /* seconds */
3196 } else if (c == 'm') {
3197 /* minutes */
3198 toff *= 60;
3199 } else if (c == 'h') {
3200 /* hours */
3201 toff *= 3600;
3202 } else if (c == 'd') {
3203 /* days */
3204 toff *= 86400;
3205 } else {
3206 /* unrecognized unit */
3207 return ((time_t) -1);
3208 }
3209 time(&now);
3210 when = now + (time_t) toff;
3211 } else if (cp != NULL) {
3212 /* HH:MM, as in "23:38" */
3213 time(&now);
3214 ltp = localtime(&now);
3215 if (ltp == NULL)
3216 return ((time_t) -1); /* impossible */
3217 lt = *ltp;
3218 *cp = ' ';
3219 hr = -1;
3220 min = -1;
3221 (void) sscanf(s2, "%d%d", &hr, &min);
3222 if ((hr < 0) || (min < 0))
3223 return ((time_t) -1);
3224 lt.tm_hour = hr;
3225 lt.tm_min = min;
3226 when = mktime(&lt);
3227 if ((when == (time_t) -1) || (when == (time_t) 0))
3228 return (when);
3229 if (when < now)
3230 when += (time_t) 86400;
3231 } else {
3232 when = UnDate(s2);
3233 }
3234 return (when);
3235} /* GetStartSpoolDate */
3236
3237
3238
3239static int
3241{
3242 if (CanSpool() < 0) {
3243#if defined(WIN32) || defined(_WINDOWS)
3244 (void) printf("Sorry, spooling isn't allowed until you run Setup.exe.\n");
3245#else
3246 (void) printf("Sorry, spooling isn't allowed because this user requires that the NCFTPDIR\nenvironment variable be set to a directory to write datafiles to.\n");
3247#endif
3248 return (-1);
3249 } else if (HaveSpool() == 0) {
3250#if defined(WIN32) || defined(_WINDOWS)
3251 (void) printf("Sorry, the \"ncftpbatch\" program could not be found.\nPlease re-run Setup to correct this problem.\n");
3252#else
3253 (void) printf("Sorry, the \"ncftpbatch\" program could not be found.\nThis program must be installed and in your PATH in order to use this feature.\n");
3254#endif
3255 return (-1);
3256 }
3257 return (0);
3258} /* SpoolCheck */
3259
3260
3261
3262/* Show and/or change customizable program settings. These changes are saved
3263 * at the end of the program's run.
3264 */
3265void
3266BGStartCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3267{
3268 int i, n;
3269
3271 if (SpoolCheck() < 0)
3272 return;
3273
3274 if ((argc < 2) || ((n = atoi(argv[1])) < 2)) {
3275 RunBatch(0, &gConn);
3276 (void) printf("Background process started.\n");
3277#if defined(WIN32) || defined(_WINDOWS)
3278#else
3279 (void) printf("Watch the \"%s/batchlog\" file to see how it is progressing.\n", gOurDirectoryPath);
3280#endif
3281 } else {
3282 for (i=0; i<n; i++)
3283 RunBatch(0, &gConn);
3284 (void) printf("Background processes started.\n");
3285#if defined(WIN32) || defined(_WINDOWS)
3286#else
3287 (void) printf("Watch the \"%s/batchlog\" file to see how it is progressing.\n", gOurDirectoryPath);
3288#endif
3289 }
3290} /* BGStart */
3291
3292
3293
3294
3295/* This commands lets the user change the umask, if the server supports it. */
3296/* (bgget) */
3297void
3298SpoolGetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3299{
3300 int opt;
3301 int renameMode = 0;
3302 int recurseFlag = kRecursiveNo;
3303 int rc;
3304 int i;
3305 int xtype = gBm.xferType;
3306 int nD = 0;
3307 int deleteFlag = kDeleteNo;
3308 time_t when = 0;
3309 char ldir[256];
3310 char pattern[256];
3311 char *lname;
3312 LineList ll;
3313 LinePtr lp;
3314
3316
3317 if ((gSavePasswords <= 0) && ((strcmp(gConn.user, "anonymous") != 0) && (strcmp(gConn.user, "ftp") != 0))) {
3318 (void) printf("Sorry, spooling isn't allowed when you're not logged in anonymously, because\nthe spool files would need to save your password.\n\nYou can override this by doing a \"set save-passwords yes\" if you're willing\nto live with the consequences.\n");
3319 return;
3320 } else if (SpoolCheck() < 0) {
3321 return;
3322 }
3323
3324 GetoptReset();
3325 while ((opt = Getopt(argc, argv, "@:azfrRD")) >= 0) switch (opt) {
3326 case '@':
3327 when = GetStartSpoolDate(gOptArg);
3328 if ((when == (time_t) -1) || (when == (time_t) 0)) {
3329 (void) fprintf(stderr, "Bad date. It must be expressed as one of the following:\n\tYYYYMMDDHHMMSS\t\n\t\"now + N hours|min|sec|days\"\n\tHH:MM\n\nNote: Do not forget to quote the entire argument for the offset option.\nExample: bgget -@ \"now + 15 min\" ...\n");
3330 return;
3331 }
3332 break;
3333 case 'a':
3334 xtype = kTypeAscii;
3335 break;
3336 case 'z':
3337 /* Special flag that lets you specify the
3338 * destination file. Normally a "get" will
3339 * write the file by the same name as the
3340 * remote file's basename.
3341 */
3342 renameMode = 1;
3343 break;
3344 case 'r':
3345 case 'R':
3346 /* If the item is a directory, get the
3347 * directory and all its contents.
3348 */
3349 recurseFlag = kRecursiveYes;
3350 break;
3351 case 'D':
3352 /* You can delete the remote file after
3353 * you downloaded it successfully by using
3354 * the -DD option. It requires two -D's
3355 * to minimize the odds of accidentally
3356 * using a single -D.
3357 */
3358 nD++;
3359 break;
3360 default:
3361 PrintCmdUsage(cmdp);
3362 return;
3363 }
3364
3365 if (nD >= 2)
3366 deleteFlag = kDeleteYes;
3367
3368 if (FTPGetLocalCWD(ldir, sizeof(ldir)) == NULL) {
3369 perror("could not get current local directory");
3370 return;
3371 }
3372
3373 if (renameMode != 0) {
3374 if (gOptInd > argc - 2) {
3375 PrintCmdUsage(cmdp);
3376 return;
3377 }
3378 rc = SpoolX(
3379 "get",
3380 argv[gOptInd],
3381 gRemoteCWD,
3382 argv[gOptInd + 1],
3383 ldir,
3384 gConn.host,
3385 gConn.ip,
3386 gConn.port,
3387 gConn.user,
3388 gConn.pass,
3389 xtype,
3390 recurseFlag,
3391 deleteFlag,
3393 NULL,
3394 NULL,
3395 NULL,
3396 when
3397 );
3398 if (rc == 0) {
3399 Trace(-1, " + Spooled: get %s as %s\n", argv[gOptInd], argv[gOptInd]);
3400 }
3401 } else {
3402 for (i=gOptInd; i<argc; i++) {
3403 STRNCPY(pattern, argv[i]);
3405 InitLineList(&ll);
3406 rc = FTPRemoteGlob(&gConn, &ll, pattern, (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
3407 if (rc < 0) {
3409 } else {
3410 for (lp = ll.first; lp != NULL; lp = lp->next) {
3411 if (lp->line != NULL) {
3412 lname = strrchr(lp->line, '/');
3413 if (lname == NULL)
3414 lname = lp->line;
3415 else
3416 lname++;
3417 rc = SpoolX(
3418 "get",
3419 lp->line,
3420 gRemoteCWD,
3421 lname,
3422 ldir,
3423 gConn.host,
3424 gConn.ip,
3425 gConn.port,
3426 gConn.user,
3427 gConn.pass,
3428 xtype,
3429 recurseFlag,
3430 deleteFlag,
3432 NULL,
3433 NULL,
3434 NULL,
3435 when
3436 );
3437 if (rc == 0) {
3438 Trace(-1, " + Spooled: get %s\n", lp->line);
3439 }
3440 }
3441 }
3442 }
3444 }
3445 }
3446} /* SpoolGetCmd */
3447
3448
3449
3450
3451/* This commands lets the user change the umask, if the server supports it. */
3452/* (bgput) */
3453void
3454SpoolPutCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3455{
3456 int opt;
3457 int renameMode = 0;
3458 int recurseFlag = kRecursiveNo;
3459 int rc;
3460 int i;
3461 int xtype = gBm.xferType;
3462 int nD = 0;
3463 int deleteFlag = kDeleteNo;
3464 time_t when = 0;
3465 char ldir[256];
3466 char pattern[256];
3467 LineList ll;
3468 LinePtr lp;
3469 char *rname;
3470
3472
3473 if ((gSavePasswords <= 0) && ((strcmp(gConn.user, "anonymous") != 0) && (strcmp(gConn.user, "ftp") != 0))) {
3474 (void) printf("Sorry, spooling isn't allowed when you're not logged in anonymously, because\nthe spool files would need to save your password.\n\nYou can override this by doing a \"set save-passwords yes\" if you're willing\nto live with the consequences.\n");
3475 return;
3476 } else if (SpoolCheck() < 0) {
3477 return;
3478 }
3479
3480 GetoptReset();
3481 while ((opt = Getopt(argc, argv, "@:azrRD")) >= 0) switch (opt) {
3482 case '@':
3483 when = GetStartSpoolDate(gOptArg);
3484 if ((when == (time_t) -1) || (when == (time_t) 0)) {
3485 (void) fprintf(stderr, "Bad date. It must be expressed as one of the following:\n\tYYYYMMDDHHMMSS\t\n\t\"now + N hours|min|sec|days\"\n\tHH:MM\n\nNote: Do not forget to quote the entire argument for the offset option.\nExample: bgget -@ \"now + 15 min\" ...\n");
3486 return;
3487 }
3488 break;
3489 case 'a':
3490 xtype = kTypeAscii;
3491 break;
3492 case 'z':
3493 /* Special flag that lets you specify the
3494 * destination file. Normally a "get" will
3495 * write the file by the same name as the
3496 * remote file's basename.
3497 */
3498 renameMode = 1;
3499 break;
3500 case 'r':
3501 case 'R':
3502 /* If the item is a directory, get the
3503 * directory and all its contents.
3504 */
3505 recurseFlag = kRecursiveYes;
3506 break;
3507 case 'D':
3508 /* You can delete the remote file after
3509 * you downloaded it successfully by using
3510 * the -DD option. It requires two -D's
3511 * to minimize the odds of accidentally
3512 * using a single -D.
3513 */
3514 nD++;
3515 break;
3516 default:
3517 PrintCmdUsage(cmdp);
3518 return;
3519 }
3520
3521 if (nD >= 2)
3522 deleteFlag = kDeleteYes;
3523
3524 if (FTPGetLocalCWD(ldir, sizeof(ldir)) == NULL) {
3525 perror("could not get current local directory");
3526 return;
3527 }
3528
3529 if (renameMode != 0) {
3530 if (gOptInd > argc - 2) {
3531 PrintCmdUsage(cmdp);
3532 return;
3533 }
3534 rc = SpoolX(
3535 "put",
3536 argv[gOptInd + 1],
3537 gRemoteCWD,
3538 argv[gOptInd + 0],
3539 ldir,
3540 gConn.host,
3541 gConn.ip,
3542 gConn.port,
3543 gConn.user,
3544 gConn.pass,
3545 xtype,
3546 recurseFlag,
3547 deleteFlag,
3549 NULL,
3550 NULL,
3551 NULL,
3552 when
3553 );
3554 if (rc == 0) {
3555 Trace(-1, " + Spooled: put %s as %s\n", argv[gOptInd], argv[gOptInd]);
3556 }
3557 } else {
3558 for (i=gOptInd; i<argc; i++) {
3559 STRNCPY(pattern, argv[i]);
3561 InitLineList(&ll);
3562 rc = FTPLocalGlob(&gConn, &ll, pattern, (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
3563 if (rc < 0) {
3564 FTPPerror(&gConn, rc, kErrGlobFailed, "local glob", pattern);
3565 } else {
3566 for (lp = ll.first; lp != NULL; lp = lp->next) {
3567 if (lp->line != NULL) {
3568 rname = strrchr(lp->line, '/');
3569 if (rname == NULL)
3570 rname = lp->line;
3571 else
3572 rname++;
3573 rc = SpoolX(
3574 "put",
3575 rname,
3576 gRemoteCWD,
3577 lp->line,
3578 ldir,
3579 gConn.host,
3580 gConn.ip,
3581 gConn.port,
3582 gConn.user,
3583 gConn.pass,
3584 xtype,
3585 recurseFlag,
3586 deleteFlag,
3588 NULL,
3589 NULL,
3590 NULL,
3591 when
3592 );
3593 if (rc == 0) {
3594 Trace(-1, " + Spooled: put %s\n", lp->line);
3595 }
3596 }
3597 }
3598 }
3600 }
3601 }
3602} /* SpoolGetCmd */
3603
3604
3605
3606
3607/* This commands lets the user change the umask, if the server supports it. */
3608void
3609SymlinkCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3610{
3611 int result;
3612
3614 result = FTPSymlink(&gConn, argv[1], argv[2]);
3615 if (result < 0)
3616 FTPPerror(&gConn, result, kErrSYMLINKFailed, "symlink", argv[1]);
3617
3618 /* Really should just flush only the modified directories... */
3619 FlushLsCache();
3620} /* SymlinkCmd */
3621
3622
3623
3624
3625/* This commands lets the user change the transfer type to use. */
3626void
3627TypeCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3628{
3629 int c;
3630 int result;
3631 const char *cs;
3632
3634 if (argc < 2) {
3635 c = argv[0][0];
3636 if (c == 't') {
3637 if (gBm.xferType == kTypeAscii) {
3638 c = kTypeAscii;
3639 cs = "ASCII";
3640 } else if (gBm.xferType == kTypeEbcdic) {
3641 c = kTypeEbcdic;
3642 cs = "EBCDIC";
3643 } else {
3644 c = kTypeBinary;
3645 cs = "binary/image";
3646 }
3647 Trace(-1, "Type is %c (%s).\n", c, cs);
3648 } else {
3650 if (result < 0) {
3651 FTPPerror(&gConn, result, kErrTYPEFailed, "Type", argv[1]);
3652 } else {
3654 }
3655 }
3656 } else {
3657 c = argv[1][0];
3659 if (result < 0) {
3660 FTPPerror(&gConn, result, kErrTYPEFailed, "Type", argv[1]);
3661 } else {
3663 }
3664 }
3665} /* TypeCmd */
3666
3667
3668
3669
3670/* This commands lets the user change the umask, if the server supports it. */
3671void
3672UmaskCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3673{
3674 int result;
3675
3677 result = FTPUmask(&gConn, argv[1]);
3678 if (result < 0)
3679 FTPPerror(&gConn, result, kErrUmaskFailed, "umask", argv[1]);
3680} /* UmaskCmd */
3681
3682
3683
3684
3685/* Show the version information. */
3686void
3687VersionCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
3688{
3690 (void) printf("Version: %s\n", gVersion + 5);
3691 (void) printf("Author: Mike Gleason (ncftp@ncftp.com)\n");
3692#ifndef BETA
3693 (void) printf("Archived at: ftp://ftp.ncftp.com/ncftp/\n");
3694#endif
3695 (void) printf("Library Version: %s\n", gLibNcFTPVersion + 5);
3696#ifdef __DATE__
3697 (void) printf("Compile Date: %s\n", __DATE__);
3698#endif
3699 if (gOS[0] != '\0')
3700 (void) printf("Platform: %s\n", gOS);
3701} /* VersionCmd */
static int argc
Definition: ServiceArgs.c:12
#define STRNCAT(d, s)
Definition: Strn.h:48
char * Strncpy(char *const, const char *const, const size_t)
Definition: Strncpy.c:11
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define isalpha(c)
Definition: acclib.h:74
#define EINTR
Definition: acclib.h:80
#define EPIPE
Definition: acclib.h:91
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define isupper(c)
Definition: acclib.h:71
int tolower(int c)
Definition: utclib.c:902
char * strchr(const char *String, int ch)
Definition: utclib.c:501
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
unsigned int dir
Definition: maze.c:112
int nRows
Definition: appswitch.c:56
int nCols
Definition: appswitch.c:56
#define msg(x)
Definition: auth_time.c:54
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
void CloseBookmarkFile(FILE *fp)
Definition: bookmark.c:246
int GetNextBookmark(FILE *fp, Bookmark *bmp)
Definition: bookmark.c:257
FILE * OpenBookmarkFile(int *numBookmarks0)
Definition: bookmark.c:275
void SetBookmarkDefaults(BookmarkPtr bmp)
Definition: bookmark.c:74
int GetBookmark(const char *const bmabbr, Bookmark *bmp)
Definition: bookmark.c:387
void DefaultBookmarkName(char *dst, size_t siz, char *src)
Definition: bookmark.c:817
int PutBookmark(Bookmark *bmp, int savePassword)
Definition: bookmark.c:748
void BookmarkToURL(BookmarkPtr bmp, char *url, size_t urlsize)
Definition: bookmark.c:36
w ll
Definition: byte_order.h:167
r l[0]
Definition: byte_order.h:168
#define setjmp
Definition: setjmp.h:209
_JBTYPE jmp_buf[_JBLEN]
Definition: setjmp.h:186
#define SIGINT
Definition: signal.h:23
#define SIGPIPE
Definition: signal.h:35
#define SIG_IGN
Definition: signal.h:48
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
DWORD pid_t
Definition: types.h:91
#define CloseHandle
Definition: compat.h:739
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define Trace(x)
Definition: inflate.c:42
UINT WINAPI DECLSPEC_HOTPATCH WinExec(LPCSTR lpCmdLine, UINT uCmdShow)
Definition: proc.c:4773
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
__kernel_size_t size_t
Definition: linux.h:237
__kernel_time_t time_t
Definition: linux.h:252
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
#define printf
Definition: freeldr.h:94
void MyInetAddr(char *, size_t, char **, int)
Definition: util.c:185
char * gl_getpass(const char *const prompt, char *const pass, int dsize)
Definition: getline.c:2051
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLubyte * pattern
Definition: glext.h:7787
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
int FTPLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
Definition: glob.c:1580
int FTPRemoteGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob)
Definition: glob.c:1341
#define cs
Definition: i386-dis.c:442
_Check_return_ _CRTIMP int __cdecl iscntrl(_In_ int _C)
#define stdout
Definition: stdio.h:99
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
_Check_return_ _CRTIMP int __cdecl _fileno(_In_ FILE *_File)
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fputs(_In_z_ const char *_Str, _Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
#define stdin
Definition: stdio.h:98
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
char * prog
Definition: isohybrid.c:47
#define c
Definition: ke_i.h:80
#define unlink
Definition: syshdrs.h:54
#define sleep
Definition: syshdrs.h:37
#define HAVE_LONG_LONG
Definition: wincfg.h:29
void InitLineList(LineListPtr list)
Definition: linelist.c:54
void DisposeLineListContents(LineListPtr list)
Definition: linelist.c:33
void FlushLsCache(void)
Definition: ls.c:94
void Ls(const char *const item, int listmode, const char *const options, FILE *stream)
Definition: ls.c:465
void LLs(const char *const, int, const char *const, FILE *)
POINT cp
Definition: magnifier.c:59
struct S2 s2
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int FTPRmdir(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob)
Definition: cmds.c:784
int FTPSymlink(const FTPCIPtr cip, const char *const lfrom, const char *const lto)
Definition: cmds.c:1585
int FTPMkdir(const FTPCIPtr cip, const char *const newDir, const int recurse)
Definition: cmds.c:641
int FTPChmod(const FTPCIPtr cip, const char *const pattern, const char *const mode, const int doGlob)
Definition: cmds.c:46
int FTPUmask(const FTPCIPtr cip, const char *const umsk)
Definition: cmds.c:1602
int FTPDelete(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob)
Definition: cmds.c:195
int FTPRemoteHelp(const FTPCIPtr cip, const char *const pattern, const LineListPtr llp)
Definition: cmds.c:739
int FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize)
Definition: cmds.c:254
int FTPRename(const FTPCIPtr cip, const char *const oldname, const char *const newname)
Definition: cmds.c:703
int FTPChdir(const FTPCIPtr cip, const char *const cdCwd)
Definition: cmds.c:11
int FTPSetTransferType(const FTPCIPtr cip, int type)
Definition: cmds.c:836
void FTPPerror(const FTPCIPtr cip, const int err, const int eerr, const char *const s1, const char *const s2)
Definition: errno.c:134
char gLibNcFTPVersion[64]
Definition: ftp.c:11
static struct hostent * GetHostEntry(char *host, struct in_addr *ip_address)
Definition: ftp.c:53
int FTPGetFiles3(const FTPCIPtr cip, const char *pattern1, const char *const dstdir1, const int recurse, int doGlob, const int xtype, const int resumeflag, int appendflag, const int deleteflag, const int tarflag, const ConfirmResumeDownloadProc resumeProc, int UNUSED(reserved))
Definition: io.c:2486
int FTPListToMemory2(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags, const int blankLines, int *const tryMLSD)
Definition: io.c:366
int FTPGetOneFile3(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int resumeflag, const int appendflag, const int deleteflag, const ConfirmResumeDownloadProc resumeProc, int UNUSED(reserved))
Definition: io.c:2451
int FTPPutFiles3(const FTPCIPtr cip, const char *const pattern, const char *const dstdir1, const int recurse, const int doGlob, const int xtype, int appendflag, const char *const tmppfx, const char *const tmpsfx, const int resumeflag, const int deleteflag, const ConfirmResumeUploadProc resumeProc, int UNUSED(reserved))
Definition: io.c:1298
int FTPPutOneFile3(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int appendflag, const char *const tmppfx, const char *const tmpsfx, const int resumeflag, const int deleteflag, const ConfirmResumeUploadProc resumeProc, int UNUSED(reserved))
Definition: io.c:1262
int FTPGetOneFile2(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int resumeflag, const int appendflag)
Definition: io.c:2721
#define ISTRNCMP
Definition: util.h:29
#define STREQ(a, b)
Definition: util.h:20
void HostsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1329
void LocalPwdCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1871
void EchoCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:706
static void NcFTPRedialStatusProc(const FTPCIPtr cipUNUSED, int mode, int val)
Definition: cmds.c:2130
FTPConnectionInfo gConn
Definition: main.c:37
void GetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:916
unsigned int gFirewallPort
Definition: preffw.c:22
size_t gNumCommands
Definition: cmdlist.c:525
static void NcFTPGetPassphraseProc(const FTPCIPtr cip, LineListPtr pwPrompt, char *pass, size_t dsize)
Definition: cmds.c:2147
void ChdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:558
void BookmarkCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:323
char gPrevLocalCWD[512]
Definition: cmds.c:79
void ChmodCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:612
void SiteCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:3146
static int PrintHosts(void)
Definition: cmds.c:1143
int gScreenColumns
Definition: cmds.c:78
char gFirewallHost[64]
Definition: preffw.c:18
char gOS[]
Definition: trace.c:23
void SpoolGetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:3298
void PrintResp(LineListPtr llp)
Definition: cmds.c:396
int gGotSig
Definition: cmds.c:65
void SaveUnsavedBookmark(void)
Definition: cmds.c:270
void SpoolPutCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:3454
char gOurInstallationPath[]
Definition: cmds.c:79
void RenameCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:2988
void PageCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:2496
int gOptInd
Definition: getopt.c:14
void LocalListCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1552
void LookupCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1886
void RGlobCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:2954
int gAutoResume
Definition: pref.c:30
void UmaskCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:3672
void PwdCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:2876
char gShell[]
Definition: cmds.c:73
static int RunBookmarkEditor(char *selectedBmName, size_t dsize)
Definition: cmds.c:1187
char * gOptArg
Definition: getopt.c:16
char gHome[]
Definition: cmds.c:73
FTPLibraryInfo gLib
Definition: main.c:36
char gFirewallExceptionList[]
Definition: preffw.c:21
void SymlinkCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:3609
jmp_buf gCancelJmp
Definition: shell.c:45
void SetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:3078
void JobsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1358
void LocalMkdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1751
void MlsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: cmds.c:1937
void ShellCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
Definition: