diff -ur betaftpd-0.0.8pre17/cmds.c betaftpd-new/cmds.c --- betaftpd-0.0.8pre17/cmds.c Sat Sep 30 15:42:50 2000 +++ betaftpd-new/cmds.c Sat Jun 21 08:57:42 2003 @@ -234,8 +234,7 @@ #if WANT_NONROOT if (nr_check_permission(c->uid, temp, 1, 1, NULL) == -1) { - numeric(c, 550, "Permission denied"); - return -1; + return numeric(c, 550, "Permission denied"); } #endif @@ -247,11 +246,10 @@ } if (strncmp(chd, c->root_dir, strlen(c->root_dir)) != 0) { - numeric(c, 550, "No such file or directory."); - return -1; + return numeric(c, 550, "No such file or directory."); } - return 0; + return 1; } /* @@ -268,12 +266,13 @@ strcpy(c->username, "ftp"); } if (strcasecmp(c->username, "ftp") == 0) { - numeric(c, 331, "Login OK, send password (your e-mail)."); c->auth = 1; + return numeric(c, 331, "Login OK, send password (your e-mail)."); } else { - numeric(c, 331, "Password required for %s.", c->username); c->auth = 2; + return numeric(c, 331, "Password required for %s.", c->username); } + /*notreached*/ return 1; } @@ -334,14 +333,15 @@ c->auth = 0; } if (c->auth == 0) { - numeric(c, 530, "Login incorrect."); + return numeric(c, 530, "Login incorrect."); } else { #if WANT_MESSAGE chdir(c->curr_dir); dump_file(c, 230, "welcome.msg"); #endif - numeric(c, 230, "User logged in."); + return numeric(c, 230, "User logged in."); } + /*notreached*/ return 1; } @@ -358,8 +358,7 @@ */ int cmd_acct(struct conn * const c) { - numeric(c, 202, "ACCT ignored OK -- not applicable on this system."); - return 1; + return numeric(c, 202, "ACCT ignored OK -- not applicable on this system."); } /* @@ -377,8 +376,7 @@ struct sockaddr_in sin; if ((c->transfer != NULL) && (c->transfer->state >= 4)) { - numeric(c, 500, "Sorry, only one transfer at a time."); - return 1; + return numeric(c, 500, "Sorry, only one transfer at a time."); } sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -389,7 +387,7 @@ i = sscanf(c->recv_buf, "%3hu,%3hu,%3hu,%3hu,%3hu,%3hu", &a0, &a1, &a2, &a3, &p0, &p1); if (i < 6) { - numeric(c, 501, "Parse error."); + return numeric(c, 501, "Parse error."); } else { const int one = 1; int tmp; @@ -400,7 +398,8 @@ TRAP_ERROR(err == -1, 500, return 1); sin.sin_port = FTP_PORT - 1; - numeric(c, 200, "PORT command OK."); + if (!numeric(c, 200, "PORT command OK.")) + return 0; /* note that bind() might well fail, so we don't error check */ #if !WANT_NONROOT @@ -442,8 +441,7 @@ struct sockaddr_in addr; if ((c->transfer != NULL) && (c->transfer->state >= 4)) { - numeric(c, 503, "Sorry, only one transfer at once."); - return 1; + return numeric(c, 503, "Sorry, only one transfer at once."); } destroy_ftran(c->transfer); @@ -473,14 +471,13 @@ TRAP_ERROR(err == -1, 500, return 1); f->state = 1; - numeric(c, 227, "Entering passive mode (%u,%u,%u,%u,%u,%u)", + return numeric(c, 227, "Entering passive mode (%u,%u,%u,%u,%u,%u)", (htonl(addr.sin_addr.s_addr) & 0xff000000) >> 24, (htonl(addr.sin_addr.s_addr) & 0x00ff0000) >> 16, (htonl(addr.sin_addr.s_addr) & 0x0000ff00) >> 8, (htonl(addr.sin_addr.s_addr) & 0x000000ff), (htons(addr.sin_port) & 0xff00) >> 8, (htons(addr.sin_port) & 0x00ff)); - return 1; } /* @@ -497,7 +494,7 @@ cdir = do_pwd(c, temp, c->curr_dir); if (cdir != NULL) { - numeric(c, 257, "\"%s\" is current working directory.", cdir); + return numeric(c, 257, "\"%s\" is current working directory.", cdir); } return 1; } @@ -535,8 +532,7 @@ */ int cmd_cwd(struct conn * const c) { - cmd_cwd_internal(c, c->recv_buf); - return 1; + return cmd_cwd_internal(c, c->recv_buf); } /* @@ -551,8 +547,7 @@ */ int cmd_cdup(struct conn * const c) { - cmd_cwd_internal(c, ".."); - return 1; + return cmd_cwd_internal(c, ".."); } /* @@ -561,25 +556,28 @@ * space and have clearer code). Mostly, it just uses do_chdir(), * and sees where that takes us. It adds a trailing slash if needed. */ -void cmd_cwd_internal(struct conn * const c, const char * const newd) +int cmd_cwd_internal(struct conn * const c, const char * const newd) { - if (do_chdir(c, newd) != -1) { - int i; + int i; + int status; - getcwd(c->curr_dir, 254); - i = strlen(c->curr_dir); - if (c->curr_dir[i - 1] != '/') { - c->curr_dir[i++] = '/'; - c->curr_dir[i] = '\0'; - } + status = do_chdir(c, newd); + if (status != 1) + return status; + + getcwd(c->curr_dir, 254); + i = strlen(c->curr_dir); + if (c->curr_dir[i - 1] != '/') { + c->curr_dir[i++] = '/'; + c->curr_dir[i] = '\0'; + } #if WANT_MESSAGE - dump_file(c, 250, ".message"); - list_readmes(c); + dump_file(c, 250, ".message"); + list_readmes(c); #endif - numeric(c, 250, "CWD successful."); - } + return numeric(c, 250, "CWD successful."); } /* @@ -590,8 +588,7 @@ int cmd_rest(struct conn * const c) { c->rest_pos = abs(atoi(c->recv_buf)); - numeric(c, 350, "Setting resume at %u bytes.", c->rest_pos); - return 1; + return numeric(c, 350, "Setting resume at %u bytes.", c->rest_pos); } /* @@ -603,17 +600,16 @@ */ int cmd_retr(struct conn * const c) { + int ok=1; struct ftran *f = c->transfer; if ((f == NULL) || ((f->state != 1) && (f->state != 3))) { - numeric(c, 425, "No data connection set up; please use PASV or PORT."); - return 1; + return numeric(c, 425, "No data connection set up; please use PASV or PORT."); } #if WANT_ASCII if ((c->rest_pos > 0) && (c->ascii_mode == 1)) { - numeric(c, 500, "Cannot resume while in ASCII mode."); - return 1; + return numeric(c, 500, "Cannot resume while in ASCII mode."); } #endif @@ -625,7 +621,7 @@ f->dir_listing = 0; if (f->local_file == -1) { - numeric(f->owner, 550, strerror(errno)); + ok = numeric(f->owner, 550, strerror(errno)); destroy_ftran(f); } else if (f->local_file == -2) { f->local_file = -1; @@ -636,7 +632,7 @@ #endif prepare_for_transfer(f); } - return 1; + return ok; } #if WANT_UPLOAD @@ -646,8 +642,7 @@ */ int cmd_stor(struct conn * const c) { - do_store(c, 0); - return 1; + return do_store(c, 0); } /* @@ -656,27 +651,24 @@ */ int cmd_appe(struct conn * const c) { - do_store(c, 1); - return 1; + return do_store(c, 1); } /* * do_store(): Initiate an upload. Most of the comments to do_retr() * (above) apply to this one as well. */ -void do_store(struct conn * const c, const int append) +int do_store(struct conn * const c, const int append) { struct ftran *f = c->transfer; if ((f == NULL) || ((f->state != 1) && (f->state != 3))) { - numeric(c, 425, "No data connection set up; please use PASV or PORT."); - return; + return numeric(c, 425, "No data connection set up; please use PASV or PORT."); } #if WANT_ASCII if ((c->rest_pos > 0) && (c->ascii_mode == 1)) { - numeric(c, 500, "Cannot resume while in ASCII mode."); - return; + return numeric(c, 500, "Cannot resume while in ASCII mode."); } #endif @@ -689,7 +681,7 @@ f->dir_listing = 0; if (f->local_file == -1) { - numeric(f->owner, 550, strerror(errno)); + return numeric(f->owner, 550, strerror(errno)); } else if (f->local_file == -2) { f->local_file = -1; } else { @@ -700,6 +692,7 @@ #endif prepare_for_transfer(f); } + return 1; } #endif /* WANT_UPLOAD */ @@ -718,18 +711,19 @@ { #if WANT_ASCII if (c->ascii_mode) { - numeric(c, 550, "SIZE not available in ASCII mode."); - return 1; + return numeric(c, 550, "SIZE not available in ASCII mode."); } #endif { - const char * const fname = translate_path(c, c->recv_buf); struct stat buf; + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; TRAP_ERROR(fname == NULL || lstat(fname, &buf) == -1, 550, return 1); - numeric(c, 213, "%lu", (unsigned long)(buf.st_size)); - return 1; + return numeric(c, 213, "%lu", (unsigned long)(buf.st_size)); } } @@ -740,16 +734,18 @@ */ int cmd_mdtm(struct conn * const c) { - const char * const fname = translate_path(c, c->recv_buf); struct stat buf; struct tm *m; + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; TRAP_ERROR(fname == NULL || lstat(fname, &buf) == -1, 550, return 1); m = gmtime(&(buf.st_mtime)); /* at least wu-ftpd does it in GMT */ - numeric(c, 213, "%u%02u%02u%02u%02u%02u", m->tm_year + 1900, + return numeric(c, 213, "%u%02u%02u%02u%02u%02u", m->tm_year + 1900, m->tm_mon + 1, m->tm_mday, m->tm_hour, m->tm_min, m->tm_sec); - return 1; } /* @@ -759,11 +755,11 @@ int cmd_abor(struct conn * const c) { if (c->transfer != NULL) { - numeric(c, 426, "File transfer aborted."); + if (!numeric(c, 426, "File transfer aborted.")) + return 0; destroy_ftran(c->transfer); } - numeric(c, 226, "ABOR command processed OK."); - return 1; + return numeric(c, 226, "ABOR command processed OK."); } /* @@ -771,11 +767,13 @@ */ int cmd_dele(struct conn * const c) { - const char * const fname = translate_path(c, c->recv_buf); + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; TRAP_ERROR(fname == NULL || unlink(fname) == -1, 550, return 1); - numeric(c, 250, "File deleted OK."); - return 1; + return numeric(c, 250, "File deleted OK."); } /* @@ -783,9 +781,12 @@ */ int cmd_rnfr(struct conn * const c) { - const char * const fname = translate_path(c, c->recv_buf); char cwd[256]; struct stat buf; + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; c->rename_from[0] = '\0'; if (fname == NULL) return 1; @@ -796,8 +797,7 @@ /* Just check that the file exists. */ TRAP_ERROR(lstat(c->rename_from, &buf) == -1, 550, c->rename_from[0] = '\0'; return 1); - numeric(c, 350, "File exists, send RNTO."); - return 1; + return numeric(c, 350, "File exists, send RNTO."); } /* @@ -805,19 +805,20 @@ */ int cmd_rnto(struct conn * const c) { - const char * const fname = translate_path(c, c->recv_buf); + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; if (fname == NULL) return 1; if (c->rename_from[0] == '\0') { - numeric(c, 503, "Please send RNFR first."); - return 1; + return numeric(c, 503, "Please send RNFR first."); } TRAP_ERROR(rename(c->rename_from, fname) == -1, 550, c->rename_from[0] = '\0'; return 1); c->rename_from[0] = '\0'; - numeric(c, 250, "File renamed successfully."); - return 1; + return numeric(c, 250, "File renamed successfully."); } /* @@ -836,9 +837,12 @@ */ int cmd_mkd(struct conn * const c) { - const char * const fname = translate_path(c, c->recv_buf); char temp[512], temp2[1024], *cdir; int i, j; + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; TRAP_ERROR(fname == NULL || mkdir(fname, 0755) == -1, 550, return 1); @@ -853,8 +857,7 @@ temp2[++j] = '"'; } } - numeric(c, 257, "\"%s\" created.", temp2); - return 1; + return numeric(c, 257, "\"%s\" created.", temp2); } /* @@ -863,11 +866,13 @@ */ int cmd_rmd(struct conn * const c) { - const char * const fname = translate_path(c, c->recv_buf); + int status; + const char * const fname = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; TRAP_ERROR(fname == NULL || rmdir(fname) == -1, 550, return 1); - numeric(c, 250, "Directory deleted."); - return 1; + return numeric(c, 250, "Directory deleted."); } /* @@ -883,8 +888,7 @@ */ int cmd_allo(struct conn * const c) { - numeric(c, 202, "No storage allocation necessary."); - return 1; + return numeric(c, 202, "No storage allocation necessary."); } /* @@ -947,7 +951,7 @@ return 0; } #else - numeric(c, 502, "STAT command disabled for security reasons."); + return numeric(c, 502, "STAT command disabled for security reasons."); #endif return 1; } @@ -1107,8 +1111,7 @@ lo.long_listing = 1; lo.classify = 0; - do_listing(c, &lo); - return 1; + return do_listing(c, &lo); } /* @@ -1126,8 +1129,7 @@ lo.long_listing = 0; lo.classify = 0; - do_listing(c, &lo); - return 1; + return do_listing(c, &lo); } /* @@ -1138,9 +1140,9 @@ * If the directory listing cache is enabled, the cache * is checked first, to see if we still have a valid entry. */ -void do_listing(struct conn * const c, struct list_options * const lo) +int do_listing(struct conn * const c, struct list_options * const lo) { - int i; + int status; char *ptr; #if HAVE_MMAP int size; @@ -1155,11 +1157,11 @@ #warning No nonroot checking for list_core() yet #endif - i = prepare_for_listing(c, &ptr, lo); - if (i == -1) { + status = prepare_for_listing(c, &ptr, lo); + if (status == -1) destroy_ftran(c->transfer); - return; - } + if (status != 1) + return status; #if WANT_DCACHE getcwd(cwd, 256); @@ -1181,24 +1183,30 @@ f->pos = 0; prepare_for_transfer(f); - return; + return 1; } } #endif #if HAVE_MMAP { - int num_files = get_num_files(c, ptr, lo); - if (num_files == -1) return; + int num_files = get_num_files(c, ptr, lo, &status); + if (status != 1) + return status; size = num_files * 160; f->file_data = malloc(size + 1); - TRAP_ERROR(f->file_data == NULL, 550, return); - list_core(c, ptr, "", lo, size, 0); + TRAP_ERROR(f->file_data == NULL, 550, return -1); + list_core(c, ptr, "", lo, &status, size, 0); + /* FIXME: say, weren't we supposed to use the return value of list_core? */ } #else - list_core(c, ptr, "", lo); + list_core(c, ptr, "", lo, &status); #endif + if (status == -1) + destroy_ftran(c->transfer); + if (status != 1) + return status; #if WANT_DCACHE populate_dcache(f, cwd, ptr, lo); @@ -1208,6 +1216,7 @@ f->pos = 0; #endif prepare_for_transfer(f); + return 1; } /* @@ -1216,7 +1225,7 @@ * a pattern). Note that c is needed for TRAP_ERROR. */ int get_num_files(struct conn * const c, const char * const pathname, - struct list_options * const lo) + struct list_options * const lo, int *pstatus) { int num_files; glob_t pglob; @@ -1228,14 +1237,16 @@ switch (glob(pathname, 0, NULL, &pglob)) { #ifdef GLOB_NOMATCH case GLOB_NOMATCH: + *pstatus = -1; return 0; #endif case 0: + *pstatus = 1; num_files = pglob.gl_pathc; break; default: - numeric(c, 550, strerror(EACCES)); - return -1; + *pstatus = numeric(c, 550, strerror(EACCES)); + return 0; } if (lo->recursive) { @@ -1247,8 +1258,10 @@ lstat(temp, &buf); if (S_ISDIR(buf.st_mode)) { chdir(temp); - num_files += get_num_files(c, "*", lo); + num_files += get_num_files(c, "*", lo, pstatus); chdir(".."); + if (*pstatus != 1) + break; } } } @@ -1274,7 +1287,8 @@ * This function is rather long. */ int list_core(struct conn * const c, const char * const pathname, - char * const disp_pathname, struct list_options * const lo + char * const disp_pathname, struct list_options * const lo, + int *pstatus #if HAVE_MMAP , const int size, int pos #endif @@ -1284,6 +1298,9 @@ glob_t pglob; struct ftran * const f = c->transfer; + /* ok status until we hit an error */ + *pstatus = 1; + /* * glob() fails to set errno correctly, so we simply guess on * `permission denied'... The others are far less likely to happen. @@ -1295,7 +1312,7 @@ #endif break; /* note: break, not return */ default: - numeric(c, 550, strerror(EACCES)); + *pstatus = numeric(c, 550, strerror(EACCES)); #if HAVE_MMAP return pos; #else @@ -1389,11 +1406,13 @@ } chdir(temp); - pos = list_core(c, "*", tmp2, lo, + pos = list_core(c, "*", tmp2, lo, pstatus, #if HAVE_MMAP size, pos); #endif chdir(".."); + if (*pstatus != 1) + return 0; /* caller will destroy_ftran if *pstatus is -1 */ } } } @@ -1418,8 +1437,7 @@ */ int cmd_noop(struct conn * const c) { - numeric(c, 200, "NOOP command successful."); - return 1; + return numeric(c, 200, "NOOP command successful."); } /* @@ -1427,8 +1445,7 @@ */ int cmd_syst(struct conn * const c) { - numeric(c, 215, "UNIX Type: L%u", NBBY); - return 1; + return numeric(c, 215, "UNIX Type: L%u", NBBY); } /* @@ -1440,16 +1457,17 @@ c->recv_buf[0] &= (255-32); /* convert to upper case */ if (c->recv_buf[0] == 'A') { c->ascii_mode = 1; - numeric(c, 200, "Type is ASCII."); + return numeric(c, 200, "Type is ASCII."); } else if (c->recv_buf[0] == 'I') { c->ascii_mode = 0; - numeric(c, 200, "Type is IMAGE."); + return numeric(c, 200, "Type is IMAGE."); } else { - numeric(c, 504, "Unknown type."); + return numeric(c, 504, "Unknown type."); } #else - numeric(c, 200, "TYPE ignored (always I)"); + return numeric(c, 200, "TYPE ignored (always I)"); #endif + /*notreached*/ return 1; } @@ -1460,10 +1478,11 @@ { c->recv_buf[0] &= (255-32); /* convert to upper case */ if (c->recv_buf[0] == 'S') { - numeric(c, 200, "Mode is STREAM."); + return numeric(c, 200, "Mode is STREAM."); } else { - numeric(c, 504, "Unknown mode."); + return numeric(c, 504, "Unknown mode."); } + /*notreached*/ return 1; } @@ -1474,10 +1493,11 @@ { c->recv_buf[0] &= (255-32); /* convert to upper case */ if (c->recv_buf[0] == 'F') { - numeric(c, 200, "Structure is FILE."); + return numeric(c, 200, "Structure is FILE."); } else { - numeric(c, 504, "Unknown structure."); + return numeric(c, 504, "Unknown structure."); } + /*notreached*/ return 1; } @@ -1500,8 +1520,7 @@ */ int cmd_help(struct conn * const c) { - numeric(c, 414, "Sorry, no detailed help; use standard FTP commands."); - return 1; + return numeric(c, 414, "Sorry, no detailed help; use standard FTP commands."); } /* @@ -1510,8 +1529,8 @@ */ int cmd_quit(struct conn * const c) { - numeric(c, 221, "Have a nice day!"); - destroy_conn(c); + if (numeric(c, 221, "Have a nice day!")) + destroy_conn(c); return 0; } @@ -1535,9 +1554,7 @@ #endif time(&(c->last_transfer)); - numeric(c, 220, "BetaFTPD " VERSION " ready."); - - return 1; + return numeric(c, 220, "BetaFTPD " VERSION " ready."); } #if DOING_PROFILING @@ -1594,7 +1611,8 @@ if ((cmlen >= (strlen(h->cmd_name) + h->add_cmlen)) && (strncasecmp(c->recv_buf, h->cmd_name, strlen(h->cmd_name)) == 0)) { if (c->auth < h->min_auth) { - numeric(c, 503, "Please login with USER and PASS."); + if (!numeric(c, 503, "Please login with USER and PASS.")) + return; while (c->recv_buf[0] != '\n') remove_bytes(c, 1); } else { char schar; @@ -1630,8 +1648,8 @@ } } while ((++h)->callback != NULL); - numeric(c, 500, "Sorry, no such command."); - remove_bytes(c, cmlen); + if (numeric(c, 500, "Sorry, no such command.")) + remove_bytes(c, cmlen); } /* @@ -1707,8 +1725,12 @@ * Note that `path' will be _changed_, and used as a return pointer * base. Do not attempt to free the result from this function -- * if you need to, free path instead. + * + * Since this calls do_chdir, it might destroy c. + * On exit, it will set *pstatus to the return value of do_chdir, + * i.e. -1 if path bad, 0 if c destroyed, 1 on success. */ -char *translate_path(struct conn * const c, char * const path) +char *translate_path(struct conn * const c, char * const path, int *pstatus) { char *ptr = NULL; @@ -1719,13 +1741,13 @@ if (ptr != NULL) { char save_char = ptr[0]; ptr[0] = 0; - - if (do_chdir(c, path) == -1) { - return NULL; - } + *pstatus = do_chdir(c, path); ptr[0] = save_char; + if (*pstatus != 1) + return NULL; ptr++; } else { + *pstatus = 1; ptr = path; } return ptr; @@ -1753,6 +1775,7 @@ { char *ptr; struct stat buf; + int status; #if WANT_NONROOT if (nr_check_permission(c->uid, path, check_permission, 0, NULL) == -1) { @@ -1760,14 +1783,16 @@ } #endif - ptr = translate_path(c, c->recv_buf); - if (ptr == NULL) return -1; + ptr = translate_path(c, c->recv_buf, &status); + if (status != 1) + return status; #if WANT_UPLOAD if ((flags & O_CREAT) == 0) { #endif TRAP_ERROR(stat(ptr, &buf) == -1, 550, return -2); if (!S_ISREG(buf.st_mode)) { + /*FIXME: could destroy c*/ numeric(c, 550, "Not a plain file.", ptr); return -2; } @@ -1804,8 +1829,7 @@ #endif if ((f == NULL) || ((f->state != 1) && (f->state != 3))) { - numeric(c, 425, "No data connection set up; please use PASV or PORT."); - return -1; + return numeric(c, 425, "No data connection set up; please use PASV or PORT."); } /* @@ -1847,8 +1871,11 @@ /* then we chdir to the dir in fptr (if any) */ tmp = fptr ? strrchr(fptr, '/') : NULL; if (tmp != NULL) { + int status; tmp[0] = 0; - if (do_chdir(c, fptr) == -1) return -1; + status = do_chdir(c, fptr); + if (status != 1) + return status; fptr = tmp + 1; } else { /* current directory */ @@ -1871,8 +1898,7 @@ #if WANT_NONROOT getcwd(chd, 512); if (nr_check_permission(c->uid, chd, 4, 1, NULL) == -1) { - numeric(c, 550, "Permission denied"); - return -1; + return numeric(c, 550, "Permission denied"); } #endif @@ -1895,7 +1921,7 @@ f->upload = 0; #endif - return 0; + return 1; } /* diff -ur betaftpd-0.0.8pre17/cmds.h betaftpd-new/cmds.h --- betaftpd-0.0.8pre17/cmds.h Sat Sep 30 15:42:50 2000 +++ betaftpd-new/cmds.h Sat Jun 21 08:33:10 2003 @@ -97,11 +97,11 @@ CMD_PROTO(exit); #endif -void cmd_cwd_internal(struct conn * const c, const char * const newd); +int cmd_cwd_internal(struct conn * const c, const char * const newd); void parse_command(struct conn *c); void prepare_for_transfer(struct ftran *f); char decode_mode(mode_t mode); -char *translate_path(struct conn * const c, char * const path); +char *translate_path(struct conn * const c, char * const path, int *pstatus); int do_openfile(struct conn * const c, char * const path, char * const filename, const int flags #if WANT_NONROOT @@ -110,11 +110,12 @@ ); int prepare_for_listing(struct conn * const c, char ** const ptr, struct list_options * const lo); -void do_listing(struct conn * const c, struct list_options * const lo); +int do_listing(struct conn * const c, struct list_options * const lo); int get_num_files(struct conn * const c, const char * const pathname, - struct list_options * const lo); + struct list_options * const lo, int *pstatus); int list_core(struct conn * const c, const char * const pathname, - char * const disp_pathname, struct list_options * const lo + char * const disp_pathname, struct list_options * const lo, + int *pstatus #if HAVE_MMAP , const int size, int pos #endif diff -ur betaftpd-0.0.8pre17/ftpd.c betaftpd-new/ftpd.c --- betaftpd-0.0.8pre17/ftpd.c Sat Sep 30 15:42:50 2000 +++ betaftpd-new/ftpd.c Fri Jun 20 16:53:23 2003 @@ -359,6 +359,9 @@ if (c == NULL) return c; + c->prev_conn = NULL; + c->next_conn = NULL; + if (sock != -1) { ioctl(sock, FIONBIO, &one); if (add_fd(sock, POLLIN) != 0) { @@ -414,11 +417,9 @@ struct ftran *f = (struct ftran *)(malloc(sizeof(struct ftran))); if (f == NULL) return f; - if (c == NULL) { - /* this is the bogus head of the list */ - f->next_ftran = NULL; - f->prev_ftran = NULL; - } else { + f->next_ftran = NULL; + f->prev_ftran = NULL; + if (c != NULL) { add_to_linked_list((struct list_element *)first_ftran, (struct list_element *)f); } @@ -565,17 +566,19 @@ /* overrun = disconnect */ if (c->buf_len + bytes_avail > 254) { - numeric(c, 503, "Buffer overrun; disconnecting."); - destroy_conn(c); + if (numeric(c, 503, "Buffer overrun; disconnecting.")) + destroy_conn(c); continue; } c->buf_len += bytes_avail; parse_command(c); + /* FIXME: c could be invalid here, as parse_command can destroy it if (fds[c->sock].revents & (POLLERR|POLLHUP|POLLNVAL)) { destroy_conn(c); } + */ } return checked_through; } @@ -660,7 +663,8 @@ if (do_download(f)) continue; /* do_{upload,download} returned 0, the transfer is complete */ - numeric(f->owner, 226, "Transfer complete."); + if (!numeric(f->owner, 226, "Transfer complete.")) + continue; time(&(f->owner->last_transfer)); #if WANT_XFERLOG @@ -1090,10 +1094,12 @@ struct conn * const c = alloc_new_conn(tempsock); num_err = 0; if (c != NULL) { - numeric(c, 220, "BetaFTPD " VERSION " ready."); + if (numeric(c, 220, "BetaFTPD " VERSION " ready.")) { #if WANT_STAT - memcpy(&(c->addr), &tempaddr, sizeof(struct sockaddr)); + memcpy(&(c->addr), &tempaddr, sizeof(struct sockaddr)); #endif + ; + } } } } @@ -1136,8 +1142,8 @@ if ((c->transfer == NULL || c->transfer->state != 5) && (now - c->last_transfer > TIMEOUT_SECS)) { /* RFC violation? */ - numeric(c, 421, "Timeout (%u minutes): Closing control connection.", TIMEOUT_SECS/60); - destroy_conn(c); + if (numeric(c, 421, "Timeout (%u minutes): Closing control connection.", TIMEOUT_SECS/60)) + destroy_conn(c); } } } @@ -1165,8 +1171,11 @@ * you can use this command much the same way as you * would use a printf() (with all the normal %s, %d, * etc.), since it actually uses printf() internally. + * + * Returns 0 if connection was destroyed, 1 on success. + * This is so cmd_* callers can just do "return numeric(...)" on error. */ -void numeric(struct conn * const c, const int numeric, const char * const format, ...) +int numeric(struct conn * const c, const int numeric, const char * const format, ...) { char buf[256], fmt[256]; va_list args; @@ -1181,7 +1190,9 @@ err = send(c->sock, buf, i, 0); if (err == -1 && errno == EPIPE) { destroy_conn(c); + return 0; } + return 1; } /* @@ -1277,7 +1288,8 @@ if (f->dir_listing) { /* include size? */ - numeric(f->owner, 150, "Opening ASCII mode data connection for directory listing."); + if (!numeric(f->owner, 150, "Opening ASCII mode data connection for directory listing.")) + return; } else { /* * slightly kludged -- perhaps we should kill the second arm, @@ -1290,20 +1302,24 @@ || f->upload #endif /* WANT_UPLOAD */ ) { - numeric(f->owner, 150, "Opening %s mode data connection for '%s'", - (f->ascii_mode) ? "ASCII" : "BINARY", f->filename); + if (!numeric(f->owner, 150, "Opening %s mode data connection for '%s'", + (f->ascii_mode) ? "ASCII" : "BINARY", f->filename)) + return; } else { - numeric(f->owner, 150, "Opening %s mode data connection for '%s' (%u bytes)", + if (!numeric(f->owner, 150, "Opening %s mode data connection for '%s' (%u bytes)", (f->ascii_mode) ? "ASCII" : "BINARY", f->filename, - f->size); + f->size)) + return; } #else /* !WANT_ASCII */ #if WANT_UPLOAD if (f->upload) { - numeric(f->owner, 150, "Opening BINARY mode data connection for '%s'", f->filename); + if (!numeric(f->owner, 150, "Opening BINARY mode data connection for '%s'", f->filename)) + return; } else #endif /* WANT_UPLOAD */ - numeric(f->owner, 150, "Opening BINARY mode data connection for '%s' (%u bytes)", f->filename, f->size); + if (!numeric(f->owner, 150, "Opening BINARY mode data connection for '%s' (%u bytes)", f->filename, f->size)) + return; #endif /* !WANT_ASCII */ } diff -ur betaftpd-0.0.8pre17/ftpd.h betaftpd-new/ftpd.h --- betaftpd-0.0.8pre17/ftpd.h Sat Jun 21 08:40:24 2003 +++ betaftpd-new/ftpd.h Fri Jun 20 16:25:27 2003 @@ -203,7 +203,7 @@ void time_out_sockets(); void remove_bytes(struct conn * const c, const int i); -void numeric(struct conn * const c, const int numeric, const char * const format, ...); +int numeric(struct conn * const c, const int numeric, const char * const format, ...); void init_file_transfer(struct ftran * const f); int create_server_socket();