📄 ftpcmd.y
字号:
if (log_commands) syslog(LOG_INFO, "SITE IDLE"); if ($2) reply(200, "Current IDLE time limit is %d seconds; max %d", timeout_idle, timeout_maxidle); } | SITE check_login SP IDLE SP NUMBER CRLF = { if (log_commands) syslog(LOG_INFO, "SITE IDLE %d", $6); if ($2) if ($6 < 30 || $6 > timeout_maxidle) { reply(501, "Maximum IDLE time must be between 30 and %d seconds", timeout_maxidle); } else { timeout_idle = $6; reply(200, "Maximum IDLE time set to %d seconds", timeout_idle); } } | SITE check_login SP GROUP SP username CRLF = {#ifndef NO_PRIVATE if (log_commands) syslog(LOG_INFO, "SITE GROUP %s", $6); if (!restricted_user && $2 && $6) priv_group($6); free($6);#endif /* !NO_PRIVATE */ } | SITE check_login SP GPASS SP password CRLF = {#ifndef NO_PRIVATE if (log_commands) syslog(LOG_INFO, "SITE GPASS password"); if (!restricted_user && $2 && $6) priv_gpass($6); free($6);#endif /* !NO_PRIVATE */ } | SITE check_login SP GPASS CRLF = {#ifndef NO_PRIVATE if (log_commands) syslog(LOG_INFO, "SITE GPASS"); if (!restricted_user && $2) priv_gpass(NULL);#endif /* !NO_PRIVATE */ } | SITE check_login SP NEWER SP STRING CRLF = { if (log_commands) syslog(LOG_INFO, "SITE NEWER %s", $6);#ifdef SITE_NEWER if ($2 && $6 && !restrict_check(".")) newer($6, ".", 0);#else reply(500, "Command no longer honored by this server");#endif free($6); } | SITE check_login SP NEWER SP STRING SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "SITE NEWER %s %s", $6, CHECKNULL($8));#ifdef SITE_NEWER if ($2 && $6 && $8 && !restrict_check($8)) newer($6, $8, 0);#else reply(500, "Command no longer honored by this server");#endif free($6); if ($8) free($8); } | SITE check_login SP MINFO SP STRING CRLF = { if (log_commands) syslog(LOG_INFO, "SITE MINFO %s", $6);#ifdef SITE_NEWER if ($2 && $6 && !restrict_check(".")) newer($6, ".", 1);#else reply(500, "Command no longer honored by this server");#endif free($6); } | SITE check_login SP MINFO SP STRING SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "SITE MINFO %s %s", $6, CHECKNULL($8));#ifdef SITE_NEWER if ($2 && $6 && $8 && !restrict_check($8)) newer($6, $8, 1);#else reply(500, "Command no longer honored by this server");#endif free($6); if ($8) free($8); } | SITE check_login SP INDEX SP STRING CRLF = { /* this is just for backward compatibility since we * thought of INDEX before we thought of EXEC */ if (!restricted_user && $2 != 0 && $6 != NULL) { char buf[MAXPATHLEN]; if (strlen($6) + 7 <= sizeof(buf)) { sprintf(buf, "index %s", (char *) $6); (void) site_exec(buf); } } if ($6 != NULL) free($6); } | SITE check_login SP EXEC SP STRING CRLF = { if (!restricted_user && $2 != 0 && $6 != NULL) { (void) site_exec((char *) $6); } if ($6 != NULL) free($6); } | STOU check_login SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "STOU %s", CHECKNULL($4)); if ($2 && $4 && !restrict_check($4)) store($4, "w", 1); if ($4 != NULL) free($4); } | SYST check_login CRLF = { if (log_commands) syslog(LOG_INFO, "SYST"); if ($2)#ifdef BSD reply(215, "UNIX Type: L%d Version: BSD-%d", NBBY, BSD);#else /* BSD */#if defined (unix) || defined (__unix__) reply(215, "UNIX Type: L%d", NBBY);#else /* unix */ reply(215, "UNKNOWN Type: L%d", NBBY);#endif /* unix */#endif /* BSD */ } /* * SIZE is not in RFC959, but Postel has blessed it and * it will be in the updated RFC. * * Return size of file in a format suitable for * using with RESTART (we just count bytes). */ | SIZE check_login SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "SIZE %s", CHECKNULL($4)); if ($2 && $4 && !restrict_check($4)) { sizecmd($4); } if ($4 != NULL) free($4); } /* * MDTM is not in RFC959, but Postel has blessed it and * it will be in the updated RFC. * * Return modification time of file as an ISO 3307 * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx * where xxx is the fractional second (of any precision, * not necessarily 3 digits) */ | MDTM check_login SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "MDTM %s", CHECKNULL($4)); if ($2 && $4 && !restrict_check($4)) { struct stat stbuf; if (stat($4, &stbuf) < 0) perror_reply(550, $4); else if ((stbuf.st_mode & S_IFMT) != S_IFREG) { reply(550, "%s: not a plain file.", $4); } else { register struct tm *t; t = gmtime(&stbuf.st_mtime); reply(213, "%04d%02d%02d%02d%02d%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); } } if ($4 != NULL) free($4); } | QUIT CRLF = { if (log_commands) syslog(LOG_INFO, "QUIT");#ifdef TRANSFER_COUNT if (logged_in) { lreply(221, "You have transferred %d bytes in %d files.", data_count_total, file_count_total); lreply(221, "Total traffic for this session was %d bytes in %d transfers.", byte_count_total, xfer_count_total); lreply(221, "Thank you for using the FTP service on %s.", hostname); }#endif /* TRANSFER_COUNT */ reply(221, "Goodbye."); dologout(0); } | error CRLF = { yyerrok; } ;rcmd: RNFR check_login SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "RNFR %s", CHECKNULL($4)); if ($2) restart_point = (off_t) 0; if ($2 && $4 && !restrict_check($4)) { fromname = renamefrom($4); } if (fromname == 0 && $4) free($4); } | REST check_login SP byte_size CRLF = { if (log_commands) syslog(LOG_INFO, "REST %d", (int) restart_point); if ($2) { fromname = 0; restart_point = $4; reply(350, "Restarting at %ld. %s", (long) restart_point, "Send STORE or RETRIEVE to initiate transfer."); } } | SITE check_login SP ALIAS CRLF = { if (log_commands) syslog(LOG_INFO, "SITE ALIAS"); if ($2) alias((char *) NULL); } | SITE check_login SP ALIAS SP STRING CRLF = { if (log_commands) syslog(LOG_INFO, "SITE ALIAS %s", $6); if ($2) alias($6); if ($6 != NULL) free($6); } | SITE check_login SP GROUPS CRLF = { if (log_commands) syslog(LOG_INFO, "SITE GROUPS"); if ($2) print_groups(); } | SITE check_login SP CDPATH CRLF = { if (log_commands) syslog(LOG_INFO, "SITE CDPATH"); if ($2) cdpath(); } | SITE check_login SP CHECKMETHOD SP method CRLF = { if (log_commands) syslog(LOG_INFO, "SITE CHECKMETHOD %s", CHECKNULL($6)); if (($2) && ($6 != NULL)) SetCheckMethod($6); if ($6 != NULL) free($6); } | SITE check_login SP CHECKMETHOD CRLF = { if (log_commands) syslog(LOG_INFO, "SITE CHECKMETHOD"); if ($2) ShowCheckMethod(); } | SITE check_login SP CHECKSUM SP pathname CRLF = { if (log_commands) syslog(LOG_INFO, "SITE CHECKSUM %s", CHECKNULL($6)); if (($2) && ($6 != NULL) && (!restrict_check($6))) CheckSum($6); if ($6 != NULL) free($6); } | SITE check_login SP CHECKSUM CRLF = { if (log_commands) syslog(LOG_INFO, "SITE CHECKSUM"); if ($2) CheckSumLastFile(); } ; username: STRING ;password: /* empty */ = { $$ = (char *) malloc(1); $$[0] = '\0'; } | STRING ;byte_size: NUMBER ;host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER = { register char *a, *p; a = (char *) &cliaddr; a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; p = (char *) &cliport; p[0] = $9; p[1] = $11; } ;form_code: N = { $$ = FORM_N; } | T = { $$ = FORM_T; } | C = { $$ = FORM_C; } ;type_code: A = { cmd_type = TYPE_A; cmd_form = FORM_N; } | A SP form_code = { cmd_type = TYPE_A; cmd_form = $3; } | E = { cmd_type = TYPE_E; cmd_form = FORM_N; } | E SP form_code = { cmd_type = TYPE_E; cmd_form = $3; } | I = { cmd_type = TYPE_I; } | L = { cmd_type = TYPE_L; cmd_bytesz = NBBY; } | L SP byte_size = { cmd_type = TYPE_L; cmd_bytesz = $3; } /* this is for a bug in the BBN ftp */ | L byte_size = { cmd_type = TYPE_L; cmd_bytesz = $2; } ;struct_code: F = { $$ = STRU_F; } | R = { $$ = STRU_R; } | P = { $$ = STRU_P; } ;mode_code: S = { $$ = MODE_S; } | B = { $$ = MODE_B; } | C = { $$ = MODE_C; } ;pathname: pathstring = { /* * Problem: this production is used for all pathname * processing, but only gives a 550 error reply. * This is a valid reply in some cases but not in others. */ if (restricted_user && logged_in && $1 && strncmp($1, "/", 1) == 0) { /* * This remaps the root so it is appearently at the user's home * rather than the real root/chroot. */ char **globlist; char *t = calloc(1 + strlen($1) + 1, sizeof(char)); if (t == NULL) { errno = EAGAIN; perror_reply(550, $1); $$ = NULL; } else { t[0] = '~'; t[1] = '\0'; if (strncmp($1, "/../", 4) == 0) strcpy(t + 1, $1 + 3); else if (strcmp($1, "/..") != 0) strcpy(t + 1, $1); globlist = ftpglob(t); if (globerr) { reply(550, "%s", globerr); $$ = NULL; if (globlist) { blkfree(globlist); free((char *) globlist); } } else if (globlist && *globlist) { $$ = *globlist; blkfree(&globlist[1]); free((char *) globlist); } else { if (globlist) { blkfree(globlist); free((char *) globlist); } errno = ENOENT; perror_reply(550, $1); $$ = NULL; } free(t); } free($1); } else if (logged_in && $1 && strncmp($1, "~", 1) == 0) { char **globlist; globlist = ftpglob($1); if (globerr) { reply(550, "%s", globerr); $$ = NULL; if (globlist) { blkfree(globlist); free((char *) globlist); } } else if (globlist && *globlist) { $$ = *globlist; blkfree(&globlist[1]); free((char *) globlist); } else { if (globlist) { blkfree(globlist); free((char *) globlist); } errno = ENOENT; perror_reply(550, $1); $$ = NULL; } free($1); } else $$ = $1; } ;pathstring: STRING ;method: STRING ;octal_number: NUMBER = { register int ret, dec, multby, digit; /* * Convert a number that was read as decimal number * to what it would be if it had been read as octal. */ dec = $1; multby = 1; ret = 0; while (dec) { digit = dec % 10; if (digit > 7) { ret = -1; break; } ret += digit * multby; multby *= 8; dec /= 10; } $$ = ret; } ;check_login: /* empty */ = { if (logged_in) $$ = 1; else { if (log_commands) syslog(LOG_INFO, "cmd failure - not logged in"); reply(530, "Please login with USER and PASS."); $$ = 0; yyerrorcalled = 1; } } ;%%extern jmp_buf errcatch;#define CMD 0 /* beginning of command */#define ARGS 1 /* expect miscellaneous arguments */#define STR1 2 /* expect SP followed by STRING */#define STR2 3 /* expect STRING */#define OSTR 4 /* optional SP then STRING */#define ZSTR1 5 /* SP then optional STRING */#define ZSTR2 6 /* optional STRING after SP */#define SITECMD 7 /* SITE command */#define NSTR 8 /* Number followed by a string */#define STR3 9 /* expect STRING followed by optional SP then STRING */struct tab cmdtab[] ={ /* In order defined in RFC 765 */ {"USER", USER, STR1, 1, "<sp> username"}, {"PASS", PASS, ZSTR1, 1, "<sp> password"}, {"ACCT", ACCT, STR1, 0, "(specify account)"}, {"SMNT", SMNT, ARGS, 0, "(structure mount)"}, {"REIN", REIN, ARGS, 0, "(reinitialize server state)"}, {"QUIT", QUIT, ARGS, 1, "(terminate service)",}, {"PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4, b5"}, {"PASV", PASV, ARGS, 1, "(set server in passive mode)"}, {"TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]"}, {"STRU", STRU, ARGS, 1, "(specify file structure)"}, {"MODE", MODE, ARGS, 1, "(specify transfer mode)"}, {"RETR", RETR, STR1, 1, "<sp> file-name"}, {"STOR", STOR, STR1, 1, "<sp> file-name"}, {"APPE", APPE, STR1, 1, "<sp> file-name"}, {"MLFL", MLFL, OSTR, 0, "(mail file)"}, {"MAIL", MAIL, OSTR, 0, "(mail to user)"}, {"MSND", MSND, OSTR, 0, "(mail send to terminal)"}, {"MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)"}, {"MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)"}, {"MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)"}, {"MRCP", MRCP, STR1, 0, "(mail recipient)"}, {"ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)"}, {"REST", REST, ARGS, 1, "(restart command)"}, {"RNFR", RNFR, STR1, 1, "<sp> file-name"}, {"RNTO", RNTO, STR1, 1, "<sp> file-name"}, {"ABOR", ABOR, ARGS, 1, "(abort operation)"}, {"DELE", DELE, STR1, 1, "<sp> file-name"}, {"CWD", CWD, OSTR, 1, "[ <sp> directory-name ]"}, {"XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]"}, {"LIST", LIST, OSTR, 1, "[ <sp> path-name ]"}, {"NLST", NLST, OSTR, 1, "[ <sp> path-name ]"}, {"SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]"}, {"SYST", SYST, ARGS, 1, "(get type of operating system)"}, {"STAT", STAT, OSTR, 1, "[ <sp> path-name ]"}, {"HELP", HELP, OSTR, 1, "[ <sp> <string> ]"}, {"NOOP", NOOP, ARGS, 1, ""}, {"MKD", MKD, STR1, 1, "<sp> path-name"}, {"XMKD", MKD, STR1, 1, "<sp> path-name"}, {"RMD", RMD, STR1, 1, "<sp> path-name"}, {"XRMD", RMD, STR1, 1, "<sp> path-name"}, {"PWD", PWD, ARGS, 1, "(return current directory)"}, {"XPWD", PWD, ARGS, 1, "(return current directory)"}, {"CDUP", CDUP, ARGS, 1, "(change to parent directory)"}, {"XCUP", CDUP, ARGS, 1, "(change to parent directory)"}, {"STOU", STOU, STR1, 1, "<sp> file-name"}, {"SIZE", SIZE, OSTR, 1, "<sp> path-name"}, {"MDTM", MDTM, OSTR, 1, "<sp> path-name"}, {NULL, 0, 0, 0, 0}};struct tab sitetab[] ={ {"UMASK", UMASK, ARGS, 1, "[ <sp> umask ]"}, {"IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]"}, {"CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name"}, {"HELP", HELP, OSTR, 1, "[ <sp> <string> ]"}, {"GROUP", GROUP, STR1, 1, "<sp> access-group"}, {"GPASS", GPASS, OSTR, 1, "<sp> access-password"}, {"NEWER", NEWER, STR3, 1, "<sp> YYYYMMDDHHMMSS [ <sp> path-name ]"}, {"MINFO", MINFO, STR3, 1, "<sp> YYYYMMDDHHMMSS [ <sp> path-name ]"}, {"INDEX", INDEX, STR1, 1, "<sp> pattern"}, {"EXEC", EXEC, STR1, 1, "<sp> command [ <sp> arguments ]"}, {"ALIAS", ALIAS, OSTR, 1, "[ <sp> alias ] "}, {"CDPATH", CDPATH, OSTR, 1, "[ <sp> ] "}, {"GROUPS", GROUPS, OSTR, 1, "[ <sp> ] "}, {"CHECKMETHOD", CHECKMETHOD, OSTR, 1, "[ <sp> method ]"}, {"CHECKSUM", CHECKSUM, OSTR, 1, "[ <sp> file-name ]"}, {NULL, 0, 0, 0, 0}};struct tab *lookup(register struct tab *p, char *cmd){ for (; p->name != NULL; p++) if (strcmp(cmd, p->name) == 0) return (p); return (0);}#include <arpa/telnet.h>/* * getline - a hacked up version of fgets to ignore TELNET escape codes. */char *wu_getline(char *s, int n, register FILE *iop){ register int c; register char *cs; char *passtxt = "PASS password\r\n"; cs = s;/* tmpline may contain saved command from urgent mode interruption */ for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) { *cs++ = tmpline[c]; if (tmpline[c] == '\n') { *cs++ = '\0'; if (debug) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -