📄 cmds.c
字号:
continue; } gargs = ftpglob(argv[i]); if (globerr != NULL) { printf("%s\n", globerr); if (gargs) { blkfree(gargs); free((char *)gargs); } continue; } for (cpp = gargs; cpp && *cpp != NULL; cpp++) { if (mflag && confirm(argv[0], *cpp)) { tp = (ntflag) ? dotrans(*cpp) : *cpp; tp = (mapflag) ? domap(tp) : tp; sendrequest((sunique) ? "STOU" : "STOR", *cpp, tp, *cpp != tp || !interactive); if (!mflag && fromatty) { ointer = interactive; interactive = 1; if (confirm("Continue with","mput")) { mflag++; } interactive = ointer; } } } if (gargs != NULL) { blkfree(gargs); free((char *)gargs); } } (void) signal(SIGINT, oldintr); mflag = 0;}voidreget(int argc, char *argv[]){ (void) getit(argc, argv, 1, "r+w");}voidget(int argc, char *argv[]){ (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );}/* * Receive one file. */static intgetit(int argc, char *argv[], int restartit, const char *modestr){ int loc = 0; char *oldargv1, *oldargv2; if (argc == 2) { argc++; /* * Protect the user from accidentally retrieving special * local names. */ argv[2] = pipeprotect(argv[1]); if (!argv[2]) { code = -1; return 0; } loc++; } if (argc < 2 && !another(&argc, &argv, "remote-file")) goto usage; if (argc < 3 && !another(&argc, &argv, "local-file")) {usage: printf("usage: %s remote-file [ local-file ]\n", argv[0]); code = -1; return (0); } oldargv1 = argv[1]; oldargv2 = argv[2]; argv[2] = globulize(argv[2]); if (!argv[2]) { code = -1; return (0); } if (loc && mcase) { char *tp = argv[1], *tp2, tmpbuf[PATH_MAX]; while (*tp && !islower(*tp)) { tp++; } if (!*tp) { tp = argv[2]; tp2 = tmpbuf; while ((*tp2 = *tp) != '\0') { if (isupper(*tp2)) { *tp2 = 'a' + *tp2 - 'A'; } tp++; tp2++; } argv[2] = tmpbuf; } } if (loc && ntflag) argv[2] = dotrans(argv[2]); if (loc && mapflag) argv[2] = domap(argv[2]); if (restartit) { struct stat stbuf; int ret; ret = stat(argv[2], &stbuf); if (restartit == 1) { if (ret < 0) { fprintf(stderr, "local: %s: %s\n", argv[2], strerror(errno)); return (0); } restart_point = stbuf.st_size; } else { if (ret == 0) { int overbose; overbose = verbose; if (debug == 0) verbose = -1; if (command("MDTM %s", argv[1]) == COMPLETE) { int yy, mo, day, hour, min, sec; struct tm *tm; verbose = overbose; sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, &day, &hour, &min, &sec); tm = gmtime(&stbuf.st_mtime); tm->tm_mon++;/* Indentation is misleading, but changes keep small. *//* * I think the indentation and braces are now correct. Whoever put this * in the way it was originally should be prohibited by law. */ if (tm->tm_year+1900 > yy) return (1); if (tm->tm_year+1900 == yy) { if (tm->tm_mon > mo) return (1); if (tm->tm_mon == mo) { if (tm->tm_mday > day) return (1); if (tm->tm_mday == day) { if (tm->tm_hour > hour) return (1); if (tm->tm_hour == hour) { if (tm->tm_min > min) return (1); if (tm->tm_min == min) { if (tm->tm_sec > sec) return (1); } } } } } } else { printf("%s\n", reply_string); verbose = overbose; return (0); } } } } recvrequest("RETR", argv[2], argv[1], modestr, argv[1] != oldargv1 || argv[2] != oldargv2); restart_point = 0; return (0);}voidmabort(int ignore){ int ointer; (void)ignore; printf("\n"); (void) fflush(stdout); if (mflag && fromatty) { ointer = interactive; interactive = 1; if (confirm("Continue with", mname)) { interactive = ointer; siglongjmp(jabort,0); } interactive = ointer; } mflag = 0; siglongjmp(jabort,0);}/* * Get multiple files. */voidmget(int argc, char **argv){ void (*oldintr)(int); int ointer; char *cp, *tp, *tp2, tmpbuf[PATH_MAX]; if (argc < 2 && !another(&argc, &argv, "remote-files")) { printf("usage: %s remote-files\n", argv[0]); code = -1; return; } mname = argv[0]; mflag = 1; oldintr = signal(SIGINT,mabort); (void) sigsetjmp(jabort, 1); while ((cp = remglob(argv,proxy)) != NULL) { if (*cp == '\0') { mflag = 0; continue; } if (mflag && confirm(argv[0], cp)) { tp = cp; if (mcase) { while (*tp && !islower(*tp)) { tp++; } if (!*tp) { tp = cp; tp2 = tmpbuf; while ((*tp2 = *tp) != '\0') { if (isupper(*tp2)) { *tp2 = 'a' + *tp2 - 'A'; } tp++; tp2++; } } tp = tmpbuf; } if (ntflag) { tp = dotrans(tp); } if (mapflag) { tp = domap(tp); } /* Reject embedded ".." */ tp = pathprotect(tp); /* Prepend ./ to "-" or "!*" or leading "/" */ tp = pipeprotect(tp); if (tp == NULL) { /* hmm... how best to handle this? */ mflag = 0; } else { recvrequest("RETR", tp, cp, "w", tp != cp || !interactive); } if (!mflag && fromatty) { ointer = interactive; interactive = 1; if (confirm("Continue with","mget")) { mflag++; } interactive = ointer; } } } (void) signal(SIGINT,oldintr); mflag = 0;}char *remglob(char *argv[], int doswitch){ char temp[16]; static char buf[PATH_MAX]; static FILE *ftemp = NULL; static char **args; int oldverbose, oldhash, badglob = 0; char *cp; if (!mflag) { if (!doglob) { args = NULL; } else { if (ftemp) { (void) fclose(ftemp); ftemp = NULL; } } return(NULL); } if (!doglob) { if (args == NULL) args = argv; if ((cp = *++args) == NULL) args = NULL; return (cp); } if (ftemp == NULL) { int oldumask, fd; (void) strcpy(temp, _PATH_TMP); /* libc 5.2.18 creates with mode 0666, which is dumb */ oldumask = umask(077); fd = mkstemp(temp); umask(oldumask); if (fd<0) { printf("Error creating temporary file, oops\n"); return NULL; } oldverbose = verbose, verbose = 0; oldhash = hash, hash = 0; if (doswitch) { pswitch(!proxy); } while (*++argv != NULL) { int dupfd = dup(fd); recvrequest ("NLST", temp, *argv, "a", 0); if (!checkglob(dupfd, *argv)) { badglob = 1; break; } } unlink(temp); if (doswitch) { pswitch(!proxy); } verbose = oldverbose; hash = oldhash; if (badglob) { printf("Refusing to handle insecure file list\n"); close(fd); return NULL; } ftemp = fdopen(fd, "r"); if (ftemp == NULL) { printf("fdopen failed, oops\n"); return NULL; } rewind(ftemp); } if (fgets(buf, sizeof (buf), ftemp) == NULL) { (void) fclose(ftemp), ftemp = NULL; return (NULL); } if ((cp = index(buf, '\n')) != NULL) *cp = '\0'; return (buf);}/* * Check whether given pattern matches `..' * We assume only a glob pattern starting with a dot will match * dot entries on the server. */static intisdotdotglob(const char *pattern){ int havedot = 0; char c; if (*pattern++ != '.') return 0; while ((c = *pattern++) != '\0' && c != '/') { if (c == '*' || c == '?') continue; if (c == '.' && havedot++) return 0; } return 1;}/* * This function makes sure the list of globbed files returned from * the server doesn't contain anything dangerous such as * /home/<yourname>/.forward, or ../.forward, * or |mail foe@doe </etc/passwd, etc. * Covered areas: * - returned name starts with / but glob pattern doesn't * - glob pattern starts with / but returned name doesn't * - returned name starts with | * - returned name contains .. in a position where glob * pattern doesn't match .. * I.e. foo/.* allows foo/../bar but not foo/.bar/../fly * * Note that globbed names starting with / should really be stored * under the current working directory; this is handled in mget above. * --okir */static intcheckglob(int fd, const char *pattern){ const char *sp; char buffer[MAXPATHLEN], dotdot[MAXPATHLEN]; int okay = 1, nrslash, initial, nr; FILE *fp; /* Find slashes in glob pattern, and verify whether component * matches `..' */ initial = (pattern[0] == '/'); for (sp = pattern, nrslash = 0; sp != 0; sp = strchr(sp, '/')) { while (*sp == '/') sp++; if (nrslash >= MAXPATHLEN) { printf("Incredible pattern: %s\n", pattern); return 0; } dotdot[nrslash++] = isdotdotglob(sp); } fp = fdopen(fd, "r"); while (okay && fgets(buffer, sizeof(buffer), fp) != NULL) { char *sp; if ((sp = strchr(buffer, '\n')) != 0) { *sp = '\0'; } else { printf("Extremely long filename from server: %s", buffer); okay = 0; break; } if (buffer[0] == '|' || (buffer[0] != '/' && initial) || (buffer[0] == '/' && !initial)) okay = 0; for (sp = buffer, nr = 0; sp; sp = strchr(sp, '/'), nr++) { while (*sp == '/') sp++; if (sp[0] == '.' && !strncmp(sp, "../", 3) && (nr >= nrslash || !dotdot[nr])) okay = 0; } } if (!okay) printf("Filename provided by server " "doesn't match pattern `%s': %s\n", pattern, buffer); fclose(fp); return okay;}static const char *onoff(int bool){ return (bool ? "on" : "off");}/* * Show status. */voidstatus(void){ int i; if (connected) printf("Connected to %s.\n", hostname); else printf("Not connected.\n"); if (!proxy) { pswitch(1); if (connected) { printf("Connected for proxy commands to %s.\n", hostname); } else { printf("No proxy connection.\n"); } pswitch(0); } printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", modename, typename, formname, structname); printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", onoff(verbose), onoff(bell), onoff(interactive), onoff(doglob)); printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), onoff(runique)); printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); if (ntflag) { printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); } else { printf("Ntrans: off\n"); } if (mapflag) { printf("Nmap: (in) %s (out) %s\n", mapin, mapout); } else { printf("Nmap: off\n"); } printf("Hash mark printing: %s; Use of PORT cmds: %s\n", onoff(hash), onoff(sendport)); printf("Tick counter printing: %s\n", onoff(tick)); if (macnum > 0) { printf("Macros:\n"); for (i=0; i<macnum; i++) { printf("\t%s\n",macros[i].mac_name); } } code = 0;}/* * Set beep on cmd completed mode. */voidsetbell(void){ bell = !bell; printf("Bell mode %s.\n", onoff(bell)); code = bell;}/* * Turn on packet tracing. */voidsettrace(void){ traceflag = !traceflag; printf("Packet tracing %s.\n", onoff(traceflag)); code = traceflag;}/* * Toggle hash mark printing during transfers. */voidsethash(void){ hash = !hash; if (hash && tick) settick(); printf("Hash mark printing %s", onoff(hash)); code = hash; if (hash) printf(" (%d bytes/hash mark)", 1024); printf(".\n");}/* * Toggle tick counter printing during transfers. */voidsettick(void){ tick = !tick; if (hash && tick) sethash(); printf("Tick counter printing %s", onoff(tick)); code = tick; if (tick) printf(" (%d bytes/tick increment)", TICKBYTES); printf(".\n");}/* * Turn on printing of server echos. */voidsetverbose(void){ verbose = !verbose; printf("Verbose mode %s.\n", onoff(verbose)); code = verbose;}/* * Toggle PORT cmd use before each data connection. */voidsetport(void){ sendport = !sendport; printf("Use of PORT cmds %s.\n", onoff(sendport)); code = sendport;}/* * Turn on interactive prompting * during mget, mput, and mdelete.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -