diff -crN publicfile-0.52/CHANGES qftpd-0.20/CHANGES *** publicfile-0.52/CHANGES Tue Nov 9 02:23:46 1999 --- qftpd-0.20/CHANGES Mon Apr 23 14:36:44 2001 *************** *** 21,23 **** --- 21,32 ---- internal: separated pathdecode.c. internal: added utime; rts now covers modification times. version: publicfile 0.52, alpha. + 20010321 + version: patch to qftpd 0.10, pre-pre-pre-pre-alpha + 20010404 + internal: eliminated // style comments (for all you purists) + internal: changed auth.ftpd.c back to stralloc + internal: eliminated user/pass mangling/fixed length handling + ui: started BADFILES support + 20010423 + version: patch to qftpd 0.20, pre-pre-pre-alpha diff -crN publicfile-0.52/CREDITS qftpd-0.20/CREDITS *** publicfile-0.52/CREDITS Wed Dec 31 19:00:00 1969 --- qftpd-0.20/CREDITS Tue Apr 17 21:24:34 2001 *************** *** 0 **** --- 1,6 ---- + These are people who have helped to bring you qftpd. + + + Goldblatt, Aaron + Jarc, Paul + Wierdl, Mate diff -crN publicfile-0.52/Makefile qftpd-0.20/Makefile *** publicfile-0.52/Makefile Tue Nov 9 02:23:46 1999 --- qftpd-0.20/Makefile Tue Apr 17 21:24:46 2001 *************** *** 16,21 **** --- 16,38 ---- compile alloc_re.c alloc.h byte.h ./compile alloc_re.c + auth.ftpd: \ + load auth.ftpd.o prot.o file.o ip.o \ + timeoutread.o timeoutwrite.o timeoutconn.o timeoutaccept.o ndelay.a \ + env.a sig.a substdio.a stralloc.a alloc.a error.a open.a case.a str.a wait.a\ + fs.a socket.lib + ./load auth.ftpd prot.o file.o ip.o \ + timeoutread.o timeoutwrite.o timeoutconn.o timeoutaccept.o \ + ndelay.a env.a sig.a substdio.a stralloc.a alloc.a error.a \ + wait.a open.a case.a str.a fs.a `cat socket.lib` + + auth.ftpd.o: \ + compile auth.ftpd.c timeoutconn.h timeoutaccept.h timeoutread.h \ + timeoutwrite.h substdio.h stralloc.h gen_alloc.h str.h \ + file.h tai.h uint64.h sig.h tai.h str.h error.h case.h \ + byte.h env.h fmt.h scan.h ip.h config.h wait.h + ./compile auth.ftpd.c + auto-str: \ load auto-str.o substdio.a error.a str.a ./load auto-str substdio.a error.a str.a *************** *** 147,158 **** fetch.o: \ compile fetch.c substdio.h timeoutwrite.h error.h exit.h direntry.h \ ! fmt.h fetch.h ./compile fetch.c file.o: \ compile file.c subfd.h substdio.h error.h file.h tai.h uint64.h \ ! byte.h str.h tai.h env.h ./compile file.c filetype.o: \ --- 164,175 ---- fetch.o: \ compile fetch.c substdio.h timeoutwrite.h error.h exit.h direntry.h \ ! fmt.h fetch.h config.h server.h ./compile fetch.c file.o: \ compile file.c subfd.h substdio.h error.h file.h tai.h uint64.h \ ! byte.h str.h tai.h env.h config.h server.h stralloc.h ./compile file.c filetype.o: \ *************** *** 194,200 **** compile ftpd.c timeoutconn.h timeoutaccept.h timeoutread.h \ timeoutwrite.h substdio.h fetch.h pathdecode.h stralloc.h gen_alloc.h \ file.h tai.h uint64.h sig.h tai.h stralloc.h str.h error.h case.h \ ! byte.h env.h fmt.h scan.h ip.h ./compile ftpd.c getln.a: \ --- 211,217 ---- compile ftpd.c timeoutconn.h timeoutaccept.h timeoutread.h \ timeoutwrite.h substdio.h fetch.h pathdecode.h stralloc.h gen_alloc.h \ file.h tai.h uint64.h sig.h tai.h stralloc.h str.h error.h case.h \ ! byte.h env.h fmt.h scan.h ip.h config.h server.h ./compile ftpd.c getln.a: \ *************** *** 312,318 **** chmod 755 load main.o: \ ! compile main.c env.h exit.h scan.h ./compile main.c makelib: \ --- 329,335 ---- chmod 755 load main.o: \ ! compile main.c env.h exit.h scan.h config.h ./compile main.c makelib: \ *************** *** 359,365 **** ./compile open_trunc.c pathdecode.o: \ ! compile pathdecode.c pathdecode.h stralloc.h gen_alloc.h ./compile pathdecode.c percent.o: \ --- 376,382 ---- ./compile open_trunc.c pathdecode.o: \ ! compile pathdecode.c pathdecode.h stralloc.h gen_alloc.h config.h server.h ./compile pathdecode.c percent.o: \ *************** *** 367,373 **** ./compile percent.c prog: \ ! configure httpd ftpd rts utime prot.o: \ compile prot.c hasshsgr.h prot.h --- 384,390 ---- ./compile percent.c prog: \ ! configure ftpd rts utime auth.ftpd prot.o: \ compile prot.c hasshsgr.h prot.h *************** *** 580,582 **** --- 597,611 ---- utime.o: \ compile utime.c scan.h exit.h ./compile utime.c + + wait.a: \ + makelib wait_pid.o wait_nohang.o + ./makelib wait.a wait_pid.o wait_nohang.o + + wait_nohang.o: \ + compile wait_nohang.c haswaitp.h + ./compile wait_nohang.c + + wait_pid.o: \ + compile wait_pid.c error.h haswaitp.h + ./compile wait_pid.c diff -crN publicfile-0.52/TARGETS qftpd-0.20/TARGETS *** publicfile-0.52/TARGETS Tue Nov 9 02:23:46 1999 --- qftpd-0.20/TARGETS Mon Apr 23 14:55:36 2001 *************** *** 119,121 **** --- 119,127 ---- it setup check + auth.ftpd + auth.ftpd.o + utime + utime.o + wait_nohang.o + wait_pid.o diff -crN publicfile-0.52/auth.ftpd.c qftpd-0.20/auth.ftpd.c *** publicfile-0.52/auth.ftpd.c Wed Dec 31 19:00:00 1969 --- qftpd-0.20/auth.ftpd.c Mon Apr 23 14:49:51 2001 *************** *** 0 **** --- 1,235 ---- + #include + #include + #include + #include + #include + #include "timeoutconn.h" + #include "timeoutaccept.h" + #include "timeoutread.h" + #include "timeoutwrite.h" + #include "substdio.h" + #include "file.h" + #include "sig.h" + #include "tai.h" + #include "str.h" + #include "error.h" + #include "case.h" + #include "byte.h" + #include "env.h" + #include "fmt.h" + #include "scan.h" + #include "ip.h" + #include "config.h" + #include "readwrite.h" + #include "wait.h" + #include "stralloc.h" + #include "str.h" + + int safewrite(int fd,char *buf,int len) + { + int r; + r = timeoutwrite(DEFAULT_TIMEOUT_WRITE,fd,buf,len); + if (r <= 0) _exit(ERR_TIME); + return r; + } + + char outbuf[256]; + substdio out = SUBSTDIO_FDBUF(safewrite,1,outbuf,sizeof outbuf); + + void out_flush(void) + { + substdio_flush(&out); + } + + void out_put(char *s,int len) + { + while (len > 0) { + substdio_put(&out,s,1); + if (*s == (char) 255) substdio_put(&out,s,1); + ++s; + --len; + } + } + + void out_puts(char *s) + { + out_put(s,str_len(s)); + } + + int saferead(int fd,char *buf,int len) + { + int r; + out_flush(); + r = timeoutread(DEFAULT_TIMEOUT_READ,fd,buf,len); + if (r <= 0) _exit(ERR_TIME); + return r; + } + + char inbuf[256]; + substdio in = SUBSTDIO_FDBUF(saferead,0,inbuf,sizeof inbuf); + + void in_get(char *ch) + { + for (;;) { + substdio_get(&in,ch,1); + if (*ch != (char) 255) return; + substdio_get(&in,ch,1); + if (*ch == (char) 255) return; + + if ((*ch == (char) 254) || (*ch == (char) 252)) + substdio_get(&in,ch,1); + else if (*ch == (char) 253) { + substdio_get(&in,ch,1); + substdio_put(&out,"\377\374",2); + substdio_put(&out,ch,1); + } + else if (*ch == (char) 251) { + substdio_get(&in,ch,1); + substdio_put(&out,"\377\376",2); + substdio_put(&out,ch,1); + } + } + } + + int fd_copy(to,from) + int to; + int from; + { + if (to == from) return 0; + if (fcntl(from,F_GETFL,0) == -1) return -1; + close(to); + if (fcntl(from,F_DUPFD,to) == -1) return -1; + return 0; + } + + stralloc user = {0}; + stralloc pass = {0}; + stralloc line = {0}; + char **childargs; + substdio ssup; + char upbuf[256]; + + void doanddie() + { + int child; + int wstat; + int pi[2]; + #ifdef BADBOY_LOGIN + sleep(BADBOY_LDELAY); + #endif + if (fd_copy(2,1) == -1) _exit(ERR_PIPE); + close(3); + if (pipe(pi) == -1) _exit(ERR_PIPE); + if (pi[0] != 3) _exit(ERR_PIPE); + switch(child = fork()) { + case -1: + _exit(ERR_FORK); + case 0: + close(pi[1]); + sig_pipedefault(); + execvp(*childargs,childargs); + _exit(ERR_ERR); + } + close(pi[0]); + + substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf); + if (substdio_put(&ssup,user.s,str_len(user.s) + 1) == -1) _exit(ERR_WRITE); + if (substdio_put(&ssup,pass.s,str_len(pass.s) + 1) == -1) _exit(ERR_WRITE); + + if (substdio_flush(&ssup) == -1) _exit(ERR_WRITE); + close(pi[1]); + byte_zero(pass.s,pass.len); + byte_zero(upbuf,sizeof upbuf); + if (wait_pid(&wstat,child) == -1) _exit(ERR_ERR); + if (wait_crashed(wstat)) _exit(ERR_CHILD); + if (wait_exitcode(wstat)) { + #ifdef BADBOY_BADPASS + sleep(BADBOY_BDELAY); + #endif + #ifdef BADAUTH_MSG + out_puts(BADAUTH_MSG); + #endif + #ifdef BADAUTH_HANGUP + _exit(ERR_AUTH); + #endif + } + _exit(ERR_OK); + } + + struct ip_address iplocal = { {0,0,0,0} }; + struct ip_address ipremote = { {0,0,0,0} }; + struct sockaddr_in sa; + + + int main(int argc, char **argv) + { + char *cmd; + char *arg; + char *x; + unsigned char ch; + int i; + + childargs = argv + 1; + { + int opt = 1; + setsockopt(0,SOL_SOCKET,SO_OOBINLINE,(char *) &opt,sizeof opt); + /* if it fails, bummer */ + } + + x = env_get("TCPLOCALIP"); + if (!x) x = "0.0.0.0"; + if (!ip_scan(x,&iplocal)) + byte_zero(&iplocal,4); + + x = env_get("TCPREMOTEIP"); + if (!x) x = "0.0.0.0"; + if (!ip_scan(x,&ipremote)) + byte_zero(&ipremote,4); + + sig_pipeignore(); + out_puts(REPLY_CONNECT); + for (;;) { + if (!stralloc_copys(&line,"")) _exit(ERR_STRALLOC); + for (;;) { + in_get(&ch); + if (ch == '\n') break; + if (!ch) ch = '\n'; + if (!stralloc_append(&line,&ch)) _exit(ERR_STRALLOC); + } + if (line.len && (line.s[line.len - 1] == '\r')) --line.len; + if (!stralloc_0(&line)) _exit(ERR_STRALLOC); + + cmd = line.s; + arg = cmd + str_chr(cmd,' '); + if (*arg) *arg++ = 0; + + if (case_equals(cmd,"quit")) { + out_puts(REPLY_QUIT); + out_flush(); + _exit(ERR_OK); + } + if (case_equals(cmd,"user")) { + if ((MAX_USER == 0) || (str_len(arg) < MAX_USER)) { + if (!stralloc_copys(&user,arg)) _exit(ERR_STRALLOC); + out_puts(REPLY_NOWPASS); + } + else { + out_puts(REPLY_BIGUSER); + } + continue; + } + if (case_equals(cmd,"pass")) { + if ((MAX_PASS == 0) || (str_len(arg) < MAX_PASS)) { + if (!stralloc_copys(&pass,arg)) _exit(ERR_STRALLOC); + if (!stralloc_0(&pass)) _exit(ERR_STRALLOC); + if (!stralloc_0(&user)) _exit(ERR_STRALLOC); + doanddie(); + } + else { + out_puts(REPLY_BIGPASS); + } + continue; + } + out_puts(REPLY_NOAUTH); + } + } diff -crN publicfile-0.52/conf-ld qftpd-0.20/conf-ld *** publicfile-0.52/conf-ld Tue Nov 9 02:23:46 1999 --- qftpd-0.20/conf-ld Tue Apr 17 21:24:34 2001 *************** *** 1,3 **** ! gcc -s This will be used to link .o files into an executable. --- 1,3 ---- ! gcc -s -static This will be used to link .o files into an executable. diff -crN publicfile-0.52/config.h qftpd-0.20/config.h *** publicfile-0.52/config.h Wed Dec 31 19:00:00 1969 --- qftpd-0.20/config.h Mon Apr 23 14:10:29 2001 *************** *** 0 **** --- 1,245 ---- + /* !!ATTENTION!! + The "default" settings in this file are by no means "default" or + "optimized" or "recommended". + Most settings are enabled or set larger (or smaller) than would normally + be necessary in order to facilitate testing. + You really should read through everything and set it accordingly. + */ + /**************************************************************\ + [Globals] + These settings are for use by other settings. + Comments are not provided. + Do not change these unless you know what you are doing. + \**************************************************************/ + + #define UMASK_MKDIR 0775 + #define TRANSFER_ASCII 1 + #define TRANSFER_BINARY 0 + + /**************************************************************\ + [Numbers] + These settings are for tuning anything related to numbers. + \**************************************************************/ + + /* Size of file read/write buffer. + If you adjust this remember to adjust the memory softlimit on the process. + */ + #define BUFFER_FILE 1024 + + /* Size of network receive/send buffer (for files only) + If you adjust this remember to adjust the memory softlimit on the process. + */ + #define BUFFER_NETWORK 2048 + + /* UPDATE: there is no more truncation. if a USER or PASS argument is + longer than one of these, we will return an error. a value of 0 + means there is no limit. + NOTE: I have not tested this, someone please test it and tell me if it works. + */ + #define MAX_PASS 0 + #define MAX_USER 0 + + + /**************************************************************\ + [Enable/Disable] + By #define'ing an item, you enable it. + By #undef'ing an item, you disable it. + \**************************************************************/ + /* NOTE: the BADFILES group of functions are not done, do not enable these! */ + /* support for rejecting files based on file extension, that is + rejecting renaming from/to or uploading. + if you enable this, set an environment variable FTPBADFILES + with a list of file extensions you want to disallow seperated + by a slash '/' character (no wildcards or other fancy stuff) + NOTE: do not begin with a slash '/' character!! if you do this + it will be bad (imagine total protonic reversal) + example: FTPBADFILES=.php/.php3 + */ + #undef BADFILES + /* same as BADFILE except applies to downloading/rm'ing FTPBADFILES*/ + #undef BAD_GET_FILES + + /* this affects the behavior of BADFILES and BAD_GET_FILES. + if this is enabled and the environment variable FTPBADFILES is NOT set, + then every file will be treated as 'bad'. + if this is disabled and the environment variable FTPBADFILES IS set, + then every file will be treated as 'good'. + this is a make-shift-safety-net incase you inadvertantly stop setting + the environment variable FTPBADFILES, so use it at your own risk. + */ + #undef BADFILES_STRICT + + /* + BADBOY_LOGIN applies the ldelay after they supply a password. + BADBOY_BADPASS applies the bdelay after they supply a bad password. + NOTE: I changed this to default to off. I think I am going to remove it + because I just remembered that I already put this into my checkpassword + a long time ago. If someone still wants/needs this let me know, otherwise + I will kill it. + */ + #undef BADBOY_LOGIN + #define BADBOY_LDELAY 1 + #define BADBOY_BADPASS + #define BADBOY_BDELAY 2 + + /* Whether to hangup after a bad authentication attempt. + Disable = dont hangup + Enable = hangup + */ + #define BADAUTH_HANGUP + /* Whether or not to display a message after a failed authentication attempt. + Disable = dont display anything + Enable = display the message here + */ + #undef BADAUGH_MSG "421 Service is temporarily unavailable.\r\n" + + /* Whether or not to use safe buffers for the STOR command. + Disable = better performance + Enable = safer performance + */ + #undef BUFSTOR + + /* Whether or not to use safe buffers for the RETR command. + Disable = better performance + Enable = safer performance + */ + #undef BUFRETR + + /* Whether or not to use EPLF style listings for the LIST command. + Disable = if you want regular people to use the ftpd + Enable = if you want almost nobody to use the ftpd + */ + #undef EPLF + + /* Whether or not to allow operations to be done on files/directories that + begin with a dot '.'. + Disable = not suggested + Enable = suggested + */ + #define HIDE_DOT_FILES + + /* Whether or not to allow operations to be done on files/directories that + contain with a tilde '~'. + Disable = default + Enable = yeah + */ + #undef HIDE_TILDE_FILES + + /* Whether or not files must have o+r access to be list/dele/stor/retr'ed. + Disable = files without o+r might be listed too + Enable = files without o+r are never listed + */ + #undef WORLD_ACCESS + + + /* Whether or not to mangle directory/filenames. + Disable = dont destroy characters, return an error instead + Enable = destroy characters in pathname + */ + #define MANGLE_PATH + /* These characters are OK to use in path/filenames. + If a path/filename contains a character that is not listed in here, + the function will either mangle the character if PATH_MANGLE is enabled, + or it will return error if MANGLE_PATH is disabled. + NOTE: notice in the default, the last character is a SPACE, dont forget to + leave a space character in here if you want to allow spaces in filenames!! + */ + #define PATH_OKCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890._-()[]!@#$%&+=,/ " + /* This is the character to mangle the path with (if enabled) + NOTE: If this character is not listed in PATH_OKCHARS, then the behavior + of functions will be as though MANGLE_PATH was disabled, and they will return + an error. + */ + #define MANGLE_PATH_CHAR '_' + + #define MANGLE_USER + #define MANGLE_PASS + #define USER_OKCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.@-" + #define PASS_OKCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.,<>/?`~!@#$%^&*()_+-={}[]\\|:;\'\" " + #define MANGLE_USER_CHAR '-' + #define MANGLE_PASS_CHAR '-' + /**************************************************************\ + [Defaults] + These settings will control default behavior. + \**************************************************************/ + + #define DEFAULT_TRANSFER TRANSFER_BINARY + + /*Time (in seconds) to wait while waiting to send data.*/ + #define DEFAULT_TIMEOUT_WRITE 60 + + /*Time (in seconds) to wait while waiting to receive data.*/ + #define DEFAULT_TIMEOUT_READ 60 + + /*Time (in seconds) to wait for idle users' input.*/ + #define DEFAULT_TIMEOUT_IDLE 60*2 + + /*Time (in seconds) to wait for connections (in or out).*/ + #define DEFAULT_TIMEOUT_CONN 60 + + #define DEFAULT_MINUID 1000 + #define DEFAULT_MINGID 1000 + #define DEFAULT_UID 65534 + #define DEFAULT_GID 65534 + + /**************************************************************\ + [Server Responses] + You can customize server responses here. + You MUST put \r\n at the end of your responses otherwise you'll break stuff. + \**************************************************************/ + #define REPLY_SYST "215 UNIX\r\n" + #define REPLY_HELP "214 publicfile home page: http://pobox.com/~djb/publicfile.html\r\n" + #define REPLY_PASS "202 You may only authenticate once.\r\n" + #define REPLY_MKD_OK "257 Directory successfully created.\r\n" + #define REPLY_MKD_BAD "550 Unable to create directory.\r\n" + #define REPLY_RMD_OK "250 Directory successfully removed.\r\n" + #define REPLY_RMD_BAD "550 Unable to remove directory.\r\n" + #define REPLY_DELE_OK "250 File successfully deleted.\r\n" + #define REPLY_DELE_BAD "530 Unable to delete file.\r\n" + #define REPLY_RNFR_OK "350 Ok.\r\n" + #define REPLY_RNFR_BAD "530 Error.\r\n" + #define REPLY_RNTO_OK "250 File successfully renamed.\r\n" + #define REPLY_RNTO_BAD "530 Error renaming file.\r\n" + #define REPLY_NOT_ALLOWED "530 Sorry, that command is not allowed.\r\n" + #define REPLY_UNKNOWN "502 Sorry, I don't understand that command.\r\n" + #define REPLY_TYPE_BINARY "200 Okay, using binary.\r\n" + #define REPLY_TYPE_ASCII "200 Type set to A.\r\n" + #define REPLY_TYPE_BAD "504 Sorry, I don't recognize that type.\r\n" + #define REPLY_MODE_STREAM "200 Thanks, I always do stream mode.\r\n" + #define REPLY_MODE_BAD "504 Sorry, I don't do anything except stream mode.\r\n" + #define REPLY_STRU_FILE "200 Thanks, I always do file structure.\r\n" + #define REPLY_STRU_BAD "504 Sorry, I don't do anything except file structure.\r\n" + #define REPLY_NOOP "200 I'm here.\r\n" + #define REPLY_QUIT "221 Goodbye.\r\n" + #define REPLY_USER "230 You may only authenticate once.\r\n" + #define REPLY_NOAUTH "530 Please login with USER and PASS.\r\n" + #define REPLY_BADLOGIN "530 Login incorrect.\r\n" + #define REPLY_NOWPASS "331 Password required.\r\n" + #define REPLY_WELCOME "230 Welcome.\r\n" + #define REPLY_NOWRITE "550 Sorry, you do not have write permission.\r\n" + #define REPLY_CONNECT "220 You have successfully connected.\r\n" + #define REPLY_BIGUSER REPLY_BADLOGIN + #define REPLY_BIGPASS REPLY_BADLOGIN + #define REPLY_BADFILE "530 Error, this is not allowed\r\n" + #define REPLY_NORELAY "501 Sorry, I don't allow PORT relaying.\r\n" + #define REPLY_BADPORT "501 Sorry, I don't accept port numbers below 1024.\r\n" + #define REPLY_BADPORTFMT "501 Sorry, you need to give me six numbers separated by commas.\r\n" + #define REPLY_PORTOK "200 Okay.\r\n" + #define REPLY_RESTOK "350 Okay.\r\n" + + /**************************************************************\ + [Error Codes] + \**************************************************************/ + #define ERR_OK 0 + #define ERR_AUTH 1 + #define ERR_MEM 2 + #define ERR_TIME 3 + #define ERR_FORK 4 + #define ERR_PIPE 5 + #define ERR_WRITE 6 + #define ERR_CHILD 7 + #define ERR_ERR 8 + #define ERR_CHDIR 20 + #define ERR_STRALLOC 21 + #define ERR_LISTEN 22 + #define ERR_UIDGID 30 diff -crN publicfile-0.52/fetch.c qftpd-0.20/fetch.c *** publicfile-0.52/fetch.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/fetch.c Tue Apr 17 21:24:36 2001 *************** *** 1,6 **** --- 1,7 ---- #include #include #include + #include #include "substdio.h" #include "timeoutwrite.h" #include "error.h" *************** *** 8,19 **** #include "direntry.h" #include "fmt.h" #include "fetch.h" ! int fetch_ascii = 1; unsigned long fetch_rest = 0; ! static char inbuf[1024]; ! static char ssbuf[1024]; static substdio ss; static int trouble; --- 9,23 ---- #include "direntry.h" #include "fmt.h" #include "fetch.h" + #include "config.h" + #include "server.h" ! int fetch_ascii = DEFAULT_TRANSFER; unsigned long fetch_rest = 0; ! char filebuf[BUFFER_FILE]; ! static char ssbuf[BUFFER_NETWORK]; ! static substdio ss; static int trouble; *************** *** 21,26 **** --- 25,49 ---- static struct stat st; static char strnum[FMT_ULONG]; + #ifdef BUFSTOR + static int dataread(int fd,char *buf,int len) + { + int w; + + if (trouble) return -1; + + if (fetch_rest) { + if (len > fetch_rest) len = fetch_rest; + fetch_rest -= len; + return len; + } + + w = timeoutread(config.toread,fd,buf,len); + if (w == -1) if (errno != error_intr) trouble = errno; + return w; + } + #endif + static int datawrite(int fd,char *buf,int len) { int w; *************** *** 33,45 **** return len; } ! w = timeoutwrite(60,fd,buf,len); if (w == -1) if (errno != error_intr) trouble = errno; return w; } static void printstat() { substdio_puts(&ss,"+i"); substdio_put(&ss,strnum,fmt_ulong(strnum,(unsigned long) st.st_dev)); substdio_puts(&ss,"."); --- 56,69 ---- return len; } ! w = timeoutwrite(config.towrite,fd,buf,len); if (w == -1) if (errno != error_intr) trouble = errno; return w; } static void printstat() { + #ifdef EPLF substdio_puts(&ss,"+i"); substdio_put(&ss,strnum,fmt_ulong(strnum,(unsigned long) st.st_dev)); substdio_puts(&ss,"."); *************** *** 53,73 **** --- 77,124 ---- if ((st.st_mode & S_IFMT) == S_IFDIR) substdio_puts(&ss,",/"); + #ifdef WORLD_ACCESS if (((st.st_mode & S_IFMT) == S_IFREG) && ((st.st_mode & 0444) == 0444)) { + #endif substdio_puts(&ss,",r,s"); substdio_put(&ss,strnum,fmt_ulong(strnum,(unsigned long) st.st_size)); + #ifdef WORLD_ACCESS } + #endif substdio_puts(&ss,",\t"); + #endif + #ifndef EPLF + char *datestring; + unsigned int len; + + len = fmt_ulong(strnum,(unsigned long) st.st_size); + datestring = ctime(&st.st_mtime); + + substdio_puts(&ss,(st.st_mode & S_IFMT) == S_IFDIR ? "drwxr-xr-x" : "-rw-r--r--"); + substdio_puts(&ss," 1 owner group "); + substdio_put(&ss,strnum,len); + substdio_puts(&ss," "); + substdio_put(&ss,datestring+4,7); + if (st.st_mtime + ((365/2)*86400) > now) + substdio_put(&ss,datestring+11,5); + else + substdio_put(&ss,datestring+19,5); + substdio_puts(&ss," "); + #endif } static void list(char *fn,int flaglong) { int i; + #ifdef HIDE_DOT_FILES if (fn[0] == '.') return; + #endif for (i = 0;fn[i];++i) { if ((fn[i] >= 0) && (fn[i] <= 32)) return; + #ifdef HIDE_TILDE_FILES if (fn[i] == '~') return; + #endif } if (flaglong) { *************** *** 89,98 **** int r; int i; - substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); switch(how) { case FETCH_LISTONE: if (fstat(fdfile,&st) == -1) break; printstat(&st); for (i = 0;fn[i];++i) --- 140,149 ---- int r; int i; switch(how) { case FETCH_LISTONE: + substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); if (fstat(fdfile,&st) == -1) break; printstat(&st); for (i = 0;fn[i];++i) *************** *** 101,110 **** else substdio_put(&ss,&fn[i],1); substdio_puts(&ss,"\r\n"); break; - case FETCH_LIST: case FETCH_NLST: if (fchdir(fdfile) == -1) { trouble = errno; return; --- 152,163 ---- else substdio_put(&ss,&fn[i],1); substdio_puts(&ss,"\r\n"); + substdio_flush(&ss); break; case FETCH_NLST: + case FETCH_LIST: + substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); if (fchdir(fdfile) == -1) { trouble = errno; return; *************** *** 115,145 **** while (d = readdir(dir)) /* XXX: temporary errors */ list(d->d_name,how == FETCH_LIST); closedir(dir); break; ! default: ! for (;;) { ! r = read(fdfile,inbuf,sizeof inbuf); ! if (r == -1) { ! if (errno = error_intr) continue; ! _exit(23); ! } ! if (r == 0) ! break; ! if (!fetch_ascii) ! substdio_put(&ss,inbuf,r); ! else for (i = 0;i < r;++i) { ! if (inbuf[i] == '\n') substdio_put(&ss,"\r",1); ! substdio_put(&ss,inbuf + i,1); } } break; } - - substdio_flush(&ss); } void fetch(char *fn,int fddata,int fdfile,int how) --- 168,230 ---- while (d = readdir(dir)) /* XXX: temporary errors */ list(d->d_name,how == FETCH_LIST); closedir(dir); + substdio_flush(&ss); break; ! case FETCH_RETR: ! #ifdef BUFRETR ! substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); ! if (!fetch_ascii) { ! while ((r = read(fdfile,filebuf,sizeof filebuf)) != 0) { ! if (r == -1) { ! if (errno = error_intr) continue; ! _exit(23); ! } ! substdio_bput(&ss,filebuf,r); ! } ! } ! else { ! while ((r = read(fdfile,filebuf,sizeof filebuf)) != 0) { ! if (r == -1) { ! if (errno = error_intr) continue; ! _exit(23); ! } for (i = 0;i < r;++i) { ! if (filebuf[i] == '\n') substdio_put(&ss,"\r",1); ! substdio_put(&ss,filebuf + i,1); } + } } + substdio_flush(&ss); + #endif + #ifndef BUFRETR + if (fetch_rest) + lseek(fdfile,fetch_rest,SEEK_SET); + while (((r=timeoutread(config.toread,fdfile,filebuf,sizeof filebuf)) > 0) && (timeoutwrite(config.towrite,fddata,filebuf,r) == r)) {}; + #endif + fetch_rest = 0; break; + case FETCH_APPE: + case FETCH_STOR: + #ifdef BUFSTOR + substdio_fdbuf(&ss,dataread,fddata,ssbuf,sizeof ssbuf); + while ((r = substdio_bget(&ss,filebuf,sizeof filebuf)) != 0) { + if (r == -1) { + if (errno = error_intr) continue; + _exit(23); + } + write(fdfile,filebuf,r); + } + substdio_flush(&ss); + #endif + #ifndef BUFSTOR + while (((r=timeoutread(config.toread,fddata,filebuf,sizeof filebuf)) > 0) && (timeoutwrite(config.towrite,fdfile,filebuf,r) == r)) { }; + #endif + break; + default: break; } } void fetch(char *fn,int fddata,int fdfile,int how) diff -crN publicfile-0.52/fetch.h qftpd-0.20/fetch.h *** publicfile-0.52/fetch.h Tue Nov 9 02:23:46 1999 --- qftpd-0.20/fetch.h Tue Apr 17 21:24:37 2001 *************** *** 5,10 **** --- 5,12 ---- #define FETCH_NLST 1 #define FETCH_LIST 2 #define FETCH_LISTONE 3 + #define FETCH_STOR 4 + #define FETCH_APPE 5 extern void fetch(char *,int,int,int); extern int fetch_ascii; diff -crN publicfile-0.52/file.c qftpd-0.20/file.c *** publicfile-0.52/file.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/file.c Tue Apr 17 21:24:37 2001 *************** *** 10,16 **** static void log(char *fn,char *result1,char *result2,int flagread) { ! int i; char ch; char *x; --- 10,16 ---- static void log(char *fn,char *result1,char *result2,int flagread) { ! /* int i; char ch; char *x; *************** *** 33,39 **** substdio_puts(subfderr,result1); substdio_puts(subfderr,result2); substdio_puts(subfderr,"\n"); ! substdio_flush(subfderr); } int file_open(char *fn,struct tai *mtime,unsigned long *length,int flagread) --- 33,44 ---- substdio_puts(subfderr,result1); substdio_puts(subfderr,result2); substdio_puts(subfderr,"\n"); ! substdio_flush(subfderr);*/ ! } ! ! int manglepath(stralloc *fn) ! { ! return(-1); } int file_open(char *fn,struct tai *mtime,unsigned long *length,int flagread) *************** *** 53,58 **** --- 58,111 ---- if (error_temp(errno)) _exit(23); return -1; } + #ifdef WORLD_ACCESS + if ((st.st_mode & 0444) != 0444) { + log(fn,": ","not ugo+r",flagread); + close(fd); + errno = error_acces; + return -1; + } + if ((st.st_mode & 0101) == 0001) { + log(fn,": ","o+x but u-x",flagread); + close(fd); + errno = error_acces; + return -1; + } + #endif + if (flagread) + if ((st.st_mode & S_IFMT) != S_IFREG) { + log(fn,": ","not a regular file",flagread); + close(fd); + errno = error_acces; + return -1; + } + + log(fn,": ","success",flagread); + + *length = st.st_size; + tai_unix(mtime,st.st_mtime); + + return fd; + } + + int file_openwrite(char *fn,struct tai *mtime,unsigned long *length,int flagread) + { + struct stat st; + int fd; + + fd = open_trunc(fn); + if (fd == -1) { + log(fn,": open failed: ",error_str(errno),flagread); + if (error_temp(errno)) _exit(23); + return -1; + } + if (fstat(fd,&st) == -1) { + log(fn,": fstat failed: ",error_str(errno),flagread); + close(fd); + if (error_temp(errno)) _exit(23); + return -1; + } + #ifdef WORLD_ACCESS if ((st.st_mode & 0444) != 0444) { log(fn,": ","not ugo+r",flagread); close(fd); *************** *** 65,70 **** --- 118,124 ---- errno = error_acces; return -1; } + #endif if (flagread) if ((st.st_mode & S_IFMT) != S_IFREG) { log(fn,": ","not a regular file",flagread); *************** *** 80,82 **** --- 134,197 ---- return fd; } + + int file_openappend(char *fn,struct tai *mtime,unsigned long *length,int flagread) + { + struct stat st; + int fd; + + fd = open_append(fn); + if (fd == -1) { + log(fn,": open failed: ",error_str(errno),flagread); + if (error_temp(errno)) _exit(23); + return -1; + } + if (fstat(fd,&st) == -1) { + log(fn,": fstat failed: ",error_str(errno),flagread); + close(fd); + if (error_temp(errno)) _exit(23); + return -1; + } + #ifdef WORLD_ACCESS + + if ((st.st_mode & 0444) != 0444) { + log(fn,": ","not ugo+r",flagread); + close(fd); + errno = error_acces; + return -1; + } + if ((st.st_mode & 0101) == 0001) { + log(fn,": ","o+x but u-x",flagread); + close(fd); + errno = error_acces; + return -1; + } + #endif + if (flagread) + if ((st.st_mode & S_IFMT) != S_IFREG) { + log(fn,": ","not a regular file",flagread); + close(fd); + errno = error_acces; + return -1; + } + + log(fn,": ","success",flagread); + + *length = st.st_size; + tai_unix(mtime,st.st_mtime); + + return fd; + } + + unsigned long filelen(const char *filename) + { + struct stat st; + errno = 0; + return(stat(filename, &st) == -1 ? 0 : st.st_size); + } + + int fileexist(const char *filename) + { + struct stat st; + return(stat(filename, &st)); + } diff -crN publicfile-0.52/file.h qftpd-0.20/file.h *** publicfile-0.52/file.h Tue Nov 9 02:23:46 1999 --- qftpd-0.20/file.h Tue Apr 17 21:24:37 2001 *************** *** 2,8 **** --- 2,13 ---- #define FILE_H #include "tai.h" + #include "stralloc.h" extern int file_open(char *,struct tai *,unsigned long *,int); + extern int file_openwrite(char *,struct tai *,unsigned long *,int); + extern int file_openappend(char *,struct tai *,unsigned long *,int); + extern unsigned long filelen(const char *); + int fileexist(const char *); #endif diff -crN publicfile-0.52/ftpd.c qftpd-0.20/ftpd.c *** publicfile-0.52/ftpd.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/ftpd.c Tue Apr 17 21:24:40 2001 *************** *** 21,32 **** #include "fmt.h" #include "scan.h" #include "ip.h" int safewrite(int fd,char *buf,int len) { int r; ! r = timeoutwrite(60,fd,buf,len); ! if (r <= 0) _exit(0); return r; } --- 21,37 ---- #include "fmt.h" #include "scan.h" #include "ip.h" + #include "config.h" + #include "server.h" + + ServerConfig config; + char filebuf[BUFFER_FILE]; int safewrite(int fd,char *buf,int len) { int r; ! r = timeoutwrite(config.toconn,fd,buf,len); ! if (r <= 0) _exit(ERR_OK); return r; } *************** *** 57,64 **** { int r; out_flush(); ! r = timeoutread(60,fd,buf,len); ! if (r <= 0) _exit(0); return r; } --- 62,69 ---- { int r; out_flush(); ! r = timeoutread(config.toread,fd,buf,len); ! if (r <= 0) _exit(ERR_OK); return r; } *************** *** 95,103 **** --- 100,111 ---- int fdlisten = -1; /* PASV socket; -1 if PASV not active */ unsigned int portremote = 0; + unsigned long restorlen = 0; stralloc dir = {0}; stralloc fn = {0}; + stralloc rnfr = {0}; + stralloc rnto = {0}; void startlistening(char x[6]) { *************** *** 111,125 **** byte_copy(&sa.sin_addr,4,&iplocal); fdlisten = socket(AF_INET,SOCK_STREAM,0); ! if (fdlisten == -1) _exit(22); opt = 1; setsockopt(fdlisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); ! if (bind(fdlisten,(struct sockaddr *) &sa,sizeof sa) == -1) _exit(22); ! if (listen(fdlisten,1) == -1) _exit(22); dummy = sizeof sa; ! if (getsockname(fdlisten,(struct sockaddr *) &sa,&dummy) == -1) _exit(22); byte_copy(x,4,&sa.sin_addr); byte_copy(x + 4,2,&sa.sin_port); --- 119,133 ---- byte_copy(&sa.sin_addr,4,&iplocal); fdlisten = socket(AF_INET,SOCK_STREAM,0); ! if (fdlisten == -1) _exit(ERR_LISTEN); opt = 1; setsockopt(fdlisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); ! if (bind(fdlisten,(struct sockaddr *) &sa,sizeof sa) == -1) _exit(ERR_LISTEN); ! if (listen(fdlisten,1) == -1) _exit(ERR_LISTEN); dummy = sizeof sa; ! if (getsockname(fdlisten,(struct sockaddr *) &sa,&dummy) == -1) _exit(ERR_LISTEN); byte_copy(x,4,&sa.sin_addr); byte_copy(x + 4,2,&sa.sin_port); *************** *** 142,148 **** startlistening(x); ! out_puts("227 ="); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[0])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[1])); --- 150,156 ---- startlistening(x); ! out_puts("227 Entering Passive Mode ("); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[0])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[1])); *************** *** 154,160 **** out_put(strnum,fmt_ulong(strnum,(unsigned long) x[4])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[5])); ! out_puts("\r\n"); } int portparse(char *arg,unsigned char x[6]) --- 162,168 ---- out_put(strnum,fmt_ulong(strnum,(unsigned long) x[4])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[5])); ! out_puts(")\r\n"); } int portparse(char *arg,unsigned char x[6]) *************** *** 183,211 **** if (fdlisten != -1) { close(fdlisten); fdlisten = -1; } if (!portparse(arg,x)) { ! out_puts("501 Sorry, you need to give me six numbers separated by commas.\r\n"); return; } if (x[4] < 4) { ! out_puts("501 Sorry, I don't accept port numbers below 1024.\r\n"); return; } if (byte_diff(x,4,&ipremote)) { ! out_puts("501 Sorry, I don't allow PORT relaying.\r\n"); return; } portremote = x[4] * (unsigned int) 256 + x[5]; ! out_puts("200 Okay.\r\n"); } void rest(char *arg) { scan_ulong(arg,&fetch_rest); ! out_puts("350 Okay.\r\n"); } ! void get(char *arg,int how) { int fdfile; int fddata; --- 191,252 ---- if (fdlisten != -1) { close(fdlisten); fdlisten = -1; } if (!portparse(arg,x)) { ! out_puts(REPLY_BADPORTFMT); return; } if (x[4] < 4) { ! out_puts(REPLY_BADPORT); return; } if (byte_diff(x,4,&ipremote)) { ! out_puts(REPLY_NORELAY); return; } portremote = x[4] * (unsigned int) 256 + x[5]; ! out_puts(REPLY_PORTOK); } void rest(char *arg) { scan_ulong(arg,&fetch_rest); ! out_puts(REPLY_RESTOK); } ! #ifdef BADFILES ! /* return 0 = ok, else bad*/ ! int checkfile(char *fn) { ! char *x; ! char *y; ! char *z; ! int i; ! int start; ! int end; ! int baselen; ! ! x = fn + str_rchr(fn,'.'); ! baselen = str_len(x); ! ! y = env_get("FTPBADFILES"); ! if (!y) { ! #ifdef BADFILES_STRICT ! return(-1); ! #else ! return(0); ! #endif ! } ! for (i=0; i<2; i++) { ! start = str_chr(y,'.'); ! end = str_chr(y,'/'); ! if (baselen == (end - start)) ! if (str_equaln(x,y,baselen)) return(-1); ! y += end+1; ! } ! return(0); ! } ! #endif ! ! void put(char *arg,int how) { int fdfile; int fddata; *************** *** 213,227 **** unsigned long length; int dummy; ! if (!stralloc_copys(&fn,"./0/")) _exit(21); ! if (*arg != '/') { ! if (!stralloc_cat(&fn,&dir)) _exit(21); ! if (!stralloc_append(&fn,"/")) _exit(21); ! } ! if (!stralloc_cats(&fn,arg)) _exit(21); ! pathdecode(&fn); ! if (!stralloc_0(&fn)) _exit(21); fdfile = file_open(fn.s,&mtime,&length,how == FETCH_RETR); if (fdfile == -1) { out_puts("550 Sorry, I can't open that file: "); --- 254,373 ---- unsigned long length; int dummy; ! if (config.write != 1) { ! out_puts(REPLY_NOWRITE); ! return; ! } ! if (*arg == '/') { ! if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); ! } ! else { ! if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); ! if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); ! if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); ! } ! if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); ! if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); ! #ifdef BADFILES ! if (checkfile(fn.s) != 0) { ! if (!stralloc_copys(&fn,"")) _exit(ERR_STRALLOC); ! out_puts(REPLY_BADFILE); ! return; ! } ! #endif ! if (how == FETCH_STOR) ! fdfile = file_openwrite(fn.s,&mtime,&length,how == FETCH_STOR); ! if (how == FETCH_APPE) ! fdfile = file_openappend(fn.s,&mtime,&length,how == FETCH_APPE); ! ! if (fdfile == -1) { ! out_puts("550 Sorry, I can't create that file: "); ! out_puts(error_str(errno)); ! out_puts(".\r\n"); ! return; ! } ! ! out_puts("150 "); ! if ((how == FETCH_RETR) && (fetch_ascii == TRANSFER_ASCII)) ! out_puts("Warning: You're using ASCII! "); ! ! if (fdlisten == -1) { ! out_puts("Making transfer connection...\r\n"); ! out_flush(); ! ! fddata = socket(AF_INET,SOCK_STREAM,0); ! if (fddata == -1) _exit(ERR_LISTEN); ! ! /* kernel will reject port 0 at this point */ ! if (timeoutconn(fddata,&ipremote,portremote,config.toconn) == -1) { ! close(fddata); ! close(fdfile); ! out_puts("425 Sorry, I couldn't make a connection: "); ! out_puts(error_str(errno)); ! out_puts(".\r\n"); ! return; ! } ! } ! else { ! out_puts("Waiting for transfer connection...\r\n"); ! out_flush(); ! ! fddata = timeoutaccept(fdlisten,config.toconn); ! close(fdlisten); fdlisten = -1; + if (fddata != -1) { + dummy = sizeof sa; + if (getpeername(fddata,(struct sockaddr *) &sa,&dummy) == -1) { + close(fddata); fddata = -1; + } + else if (byte_diff(&sa.sin_addr,4,&ipremote)) { + errno = error_acces; + close(fddata); fddata = -1; + } + } + + if (fddata == -1) { + close(fdfile); + out_puts("425 Sorry, I couldn't accept a connection: "); + out_puts(error_str(errno)); + out_puts(".\r\n"); + return; + } + } + + dummy = 1; + setsockopt(fddata,IPPROTO_TCP,1/*TCP_NODELAY*/,&dummy,sizeof dummy); + + fetch(arg,fddata,fdfile,how); /* closes fddata and fdfile */ + + portremote = 0; + } + + void get(char *arg,int how) + { + int fdfile; + int fddata; + struct tai mtime; + unsigned long length; + int dummy; + + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + #ifdef BAD_GET_FILES + if (how == FETCH_RETR) + if (checkfile(fn.s) != 0) { + if (!stralloc_copys(&fn,"")) _exit(ERR_STRALLOC); + return; + } + #endif fdfile = file_open(fn.s,&mtime,&length,how == FETCH_RETR); if (fdfile == -1) { out_puts("550 Sorry, I can't open that file: "); *************** *** 231,237 **** } out_puts("150 "); ! if ((how == FETCH_RETR) && fetch_ascii) out_puts("Warning: You're using ASCII! "); if (fdlisten == -1) { --- 377,383 ---- } out_puts("150 "); ! if ((how == FETCH_RETR) && (fetch_ascii == TRANSFER_ASCII)) out_puts("Warning: You're using ASCII! "); if (fdlisten == -1) { *************** *** 239,248 **** out_flush(); fddata = socket(AF_INET,SOCK_STREAM,0); ! if (fddata == -1) _exit(22); /* kernel will reject port 0 at this point */ ! if (timeoutconn(fddata,&ipremote,portremote,60) == -1) { close(fddata); close(fdfile); out_puts("425 Sorry, I couldn't make a connection: "); --- 385,394 ---- out_flush(); fddata = socket(AF_INET,SOCK_STREAM,0); ! if (fddata == -1) _exit(ERR_LISTEN); /* kernel will reject port 0 at this point */ ! if (timeoutconn(fddata,&ipremote,portremote,config.toconn) == -1) { close(fddata); close(fdfile); out_puts("425 Sorry, I couldn't make a connection: "); *************** *** 255,261 **** out_puts("Waiting for transfer connection...\r\n"); out_flush(); ! fddata = timeoutaccept(fdlisten,60); close(fdlisten); fdlisten = -1; if (fddata != -1) { --- 401,407 ---- out_puts("Waiting for transfer connection...\r\n"); out_flush(); ! fddata = timeoutaccept(fdlisten,config.toconn); close(fdlisten); fdlisten = -1; if (fddata != -1) { *************** *** 286,291 **** --- 432,465 ---- portremote = 0; } + void filesize(char *arg) + { + unsigned int len; + unsigned long flen; + + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + flen = filelen(fn.s); + if (errno) { + out_puts("550 Sorry, there is a failure: "); + out_puts(error_str(errno)); + out_puts(".\r\n"); + return; + } + out_puts("213 "); + len = fmt_ulong(strnum,(unsigned long) flen); + out_put(strnum, len); + out_puts("\r\n"); + } + void dir_moveup(void) { dir.len = byte_rchr(dir.s,dir.len,'/'); *************** *** 293,298 **** --- 467,473 ---- void dir_move(char *to) { + /* if (*to == '/') { if (!stralloc_copys(&dir,"")) _exit(21); ++to; *************** *** 301,306 **** --- 476,489 ---- if (!stralloc_append(&dir,"/")) _exit(21); if (!stralloc_cats(&dir,to)) _exit(21); } + */ + if (to[0] == '/') { + if (!stralloc_copys(&dir,to)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_append(&dir,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&dir,to)) _exit(ERR_STRALLOC); + } } void say_dir(char *code) *************** *** 312,318 **** out_puts("\""); if (!dir.len) out_puts("/"); - else for (i = 0;i < dir.len;++i) { ch = dir.s[i]; if (ch == '\n') out_put("",1); --- 495,500 ---- *************** *** 322,327 **** --- 504,635 ---- out_puts("\" \r\n"); } + int md(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + return mkdir(fn.s,UMASK_MKDIR); + } + + int rd(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + return rmdir(fn.s); + } + + int rm(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + #ifdef BAD_GET_FILES + if (checkfile(fn.s) != 0) { + if (!stralloc_copys(&fn,"")) _exit(ERR_STRALLOC); + return(-1); + } + #endif + return unlink(fn.s); + } + + int renamefrom(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&rnfr,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&rnfr,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&rnfr,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&rnfr,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&rnfr) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&rnfr)) _exit(ERR_STRALLOC); + #ifdef BADFILES + if (checkfile(rnfr.s) != 0) { + if (!stralloc_copys(&rnfr,"")) _exit(ERR_STRALLOC); + return(-1); + } + #endif + return(0); + } + + int renameto(char *arg) + { + int srcfile; + int dstfile; + unsigned long length1; + unsigned long length2; + struct tai mtime1; + struct tai mtime2; + int r; + + if (config.write != 1) return(-1); + if (rnfr.len < 1) return(-1); + + if (*arg == '/') { + if (!stralloc_copys(&rnto,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&rnto,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&rnto,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&rnto,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&rnto) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&rnto)) _exit(ERR_STRALLOC); + if (rnto.len < 1) return(-1); + #ifdef BADFILES + if (checkfile(rnto.s) != 0) { + if (!stralloc_copys(&rnto,"")) _exit(ERR_STRALLOC); + return(-1); + } + #endif + if (str_equal(rnfr.s,rnto.s)) return(-1); + if (fileexist(rnfr.s) != 0) return(-1); + if (fileexist(rnto.s) == 0) return(-1); + dstfile = file_openwrite(rnto.s,&mtime1,&length1,1); + srcfile = file_open(rnfr.s,&mtime2,&length2,1); + if ((dstfile == -1) || (srcfile == -1)) { + close(dstfile); + close(srcfile); + unlink(rnto.s); + return(-1); + } + while (((r=timeoutread(config.toread,srcfile,filebuf,sizeof filebuf)) > 0) && (timeoutwrite(config.towrite,dstfile,filebuf,r) == r)) {}; + if ((close(dstfile) != 0) || (close(srcfile) != 0) || (r == -1) || (filelen(rnfr.s) != filelen(rnto.s))) { + unlink(rnto.s); + return(-1); + } + unlink(rnfr.s); + return(0); + } + void request(char *cmd,char *arg) { if (case_equals(cmd,"spsv")) { spsv(); return; } *************** *** 331,347 **** if (case_equals(cmd,"retr")) { get(arg,FETCH_RETR); return; } if (case_equals(cmd,"list")) { get(arg,*arg ? FETCH_LISTONE : FETCH_LIST); return; } if (case_equals(cmd,"nlst")) { get(arg,FETCH_NLST); return; } if (case_equals(cmd,"quit")) { ! out_puts("221 Bye.\r\n"); out_flush(); _exit(0); } if (case_equals(cmd,"user")) { ! out_puts("230 Hi. No need to log in; I'm an anonymous ftp server.\r\n"); return; } if (case_equals(cmd,"noop")) { ! out_puts("200 I'm here.\r\n"); return; } if (case_equals(cmd,"pwd") || case_equals(cmd,"xpwd")) { --- 639,658 ---- if (case_equals(cmd,"retr")) { get(arg,FETCH_RETR); return; } if (case_equals(cmd,"list")) { get(arg,*arg ? FETCH_LISTONE : FETCH_LIST); return; } if (case_equals(cmd,"nlst")) { get(arg,FETCH_NLST); return; } + if (case_equals(cmd,"stor")) { put(arg,FETCH_STOR); return; } + if (case_equals(cmd,"appe")) { put(arg,FETCH_APPE); return; } + if (case_equals(cmd,"size")) { filesize(arg); return; } if (case_equals(cmd,"quit")) { ! out_puts(REPLY_QUIT); out_flush(); _exit(0); } if (case_equals(cmd,"user")) { ! out_puts(REPLY_USER); return; } if (case_equals(cmd,"noop")) { ! out_puts(REPLY_NOOP); return; } if (case_equals(cmd,"pwd") || case_equals(cmd,"xpwd")) { *************** *** 360,420 **** } if (case_equals(cmd,"stru")) { if ((*arg == 'f') || (*arg == 'F')) { ! out_puts("200 Thanks, I always do file structure.\r\n"); return; } ! out_puts("504 Sorry, I don't do anything except file structure.\r\n"); return; } if (case_equals(cmd,"mode")) { if ((*arg == 's') || (*arg == 'S')) { ! out_puts("200 Thanks, I always do stream mode.\r\n"); return; } ! out_puts("504 Sorry, I don't do anything except stream mode.\r\n"); return; } if (case_equals(cmd,"type")) { if ((*arg == 'a') || (*arg == 'A')) { ! fetch_ascii = 1; ! out_puts("200 Why are you using ASCII?\r\n"); return; } if ((*arg == 'i') || (*arg == 'I') || (*arg == 'l') || (*arg == 'L')) { ! fetch_ascii = 0; ! out_puts("200 Okay, using binary.\r\n"); return; } ! out_puts("504 Sorry, I don't recognize that type.\r\n"); return; } if (case_equals(cmd,"syst")) { ! out_puts("215 UNIX Type: L8\r\n"); return; } if (case_equals(cmd,"help")) { ! out_puts("214 publicfile home page: http://pobox.com/~djb/publicfile.html\r\n"); return; } if (case_equals(cmd,"pass") || case_equals(cmd,"acct")) { ! out_puts("202 I don't need account information; I'm an anonymous FTP server.\r\n"); return; } ! if (case_equals(cmd,"allo")) { ! out_puts("202 Who cares? I don't allow file creation.\r\n"); return; } ! if (case_equals(cmd,"stor") || case_equals(cmd,"stou") || case_equals(cmd,"appe") || case_equals(cmd,"dele") || case_equals(cmd,"rnfr") || case_equals(cmd,"rnto") || case_equals(cmd,"mkd") || case_equals(cmd,"xmkd") || case_equals(cmd,"rmd") || case_equals(cmd,"xrmd")) { ! out_puts("553 Sorry, I don't allow file modification.\r\n"); return; } ! ! out_puts("502 Sorry, I don't understand that command.\r\n"); } stralloc line = {0}; ! void doit(void) { char *cmd; char *arg; --- 671,775 ---- } if (case_equals(cmd,"stru")) { if ((*arg == 'f') || (*arg == 'F')) { ! out_puts(REPLY_STRU_FILE); return; } ! out_puts(REPLY_STRU_BAD); return; } if (case_equals(cmd,"mode")) { if ((*arg == 's') || (*arg == 'S')) { ! out_puts(REPLY_MODE_STREAM); return; } ! out_puts(REPLY_MODE_BAD); return; } if (case_equals(cmd,"type")) { if ((*arg == 'a') || (*arg == 'A')) { ! fetch_ascii = TRANSFER_ASCII; ! out_puts(REPLY_TYPE_ASCII); return; } if ((*arg == 'i') || (*arg == 'I') || (*arg == 'l') || (*arg == 'L')) { ! fetch_ascii = TRANSFER_BINARY; ! out_puts(REPLY_TYPE_BINARY); return; } ! out_puts(REPLY_TYPE_BAD); return; } if (case_equals(cmd,"syst")) { ! out_puts(REPLY_SYST); return; } if (case_equals(cmd,"help")) { ! out_puts(REPLY_HELP); return; } if (case_equals(cmd,"pass") || case_equals(cmd,"acct")) { ! out_puts(REPLY_PASS); return; } ! if (case_equals(cmd,"mkd") || case_equals(cmd,"xmkd")) { ! if (md(arg) == 0) ! out_puts(REPLY_MKD_OK); ! else ! out_puts(REPLY_MKD_BAD); return; } ! if (case_equals(cmd,"rmd") || case_equals(cmd,"xrmd")) { ! if (rd(arg) == 0) ! out_puts(REPLY_RMD_OK); ! else ! out_puts(REPLY_RMD_BAD); return; } ! if (case_equals(cmd,"dele")) { ! if (rm(arg) == 0) ! out_puts(REPLY_DELE_OK); ! else ! out_puts(REPLY_DELE_BAD); ! return; ! } ! if (case_equals(cmd,"stou") || case_equals(cmd,"allo")) { ! out_puts(REPLY_NOT_ALLOWED); ! return; ! } ! if (case_equals(cmd,"rnfr")) { ! if (renamefrom(arg) == 0) ! out_puts(REPLY_RNFR_OK); ! else ! out_puts(REPLY_RNFR_BAD); ! return; ! } ! if (case_equals(cmd,"rnto")) { ! if (renameto(arg) == 0) ! out_puts(REPLY_RNTO_OK); ! else ! out_puts(REPLY_RNTO_BAD); ! return; ! } ! out_puts(REPLY_UNKNOWN); } + void do_config(void) + { + char *x; + config.toread = DEFAULT_TIMEOUT_READ; + config.towrite = DEFAULT_TIMEOUT_WRITE; + config.toidle = DEFAULT_TIMEOUT_IDLE; + config.toconn = DEFAULT_TIMEOUT_CONN; + #ifdef BADFILES + config.badfiles = env_get("FTPBADFILES"); + #endif + x = env_get("FTPWRITE"); + if (!x) config.write = 0; + else config.write = 1; + } stralloc line = {0}; ! void doit(int writing) { char *cmd; char *arg; *************** *** 437,456 **** if (!ip_scan(x,&ipremote)) byte_zero(&ipremote,4); ! if (!stralloc_copys(&dir,"")) _exit(21); sig_pipeignore(); for (;;) { ! if (!stralloc_copys(&line,"")) _exit(21); for (;;) { in_get(&ch); if (ch == '\n') break; if (!ch) ch = '\n'; ! if (!stralloc_append(&line,&ch)) _exit(21); } if (line.len && (line.s[line.len - 1] == '\r')) --line.len; ! if (!stralloc_0(&line)) _exit(21); cmd = line.s; arg = cmd + str_chr(cmd,' '); --- 792,816 ---- if (!ip_scan(x,&ipremote)) byte_zero(&ipremote,4); ! if (!stralloc_copys(&dir,"")) _exit(ERR_STRALLOC); sig_pipeignore(); + do_config(); + if (writing==1) config.write = 1; + + out_puts(REPLY_WELCOME); + for (;;) { ! if (!stralloc_copys(&line,"")) _exit(ERR_STRALLOC); for (;;) { in_get(&ch); if (ch == '\n') break; if (!ch) ch = '\n'; ! if (!stralloc_append(&line,&ch)) _exit(ERR_STRALLOC); } if (line.len && (line.s[line.len - 1] == '\r')) --line.len; ! if (!stralloc_0(&line)) _exit(ERR_STRALLOC); cmd = line.s; arg = cmd + str_chr(cmd,' '); diff -crN publicfile-0.52/haswaitp.h qftpd-0.20/haswaitp.h *** publicfile-0.52/haswaitp.h Wed Dec 31 19:00:00 1969 --- qftpd-0.20/haswaitp.h Tue Apr 17 21:24:42 2001 *************** *** 0 **** --- 1 ---- + #define HASWAITPID 1 diff -crN publicfile-0.52/main.c qftpd-0.20/main.c *** publicfile-0.52/main.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/main.c Tue Apr 17 21:24:45 2001 *************** *** 1,31 **** #include "env.h" #include "exit.h" #include "scan.h" ! extern void doit(void); main(int argc,char **argv) { char *x; unsigned long id; x = argv[1]; if (x) { ! if (chdir(x) == -1) _exit(20); ! if (chroot(".") == -1) _exit(30); } x = env_get("GID"); ! if (x) { scan_ulong(x,&id); ! if (prot_gid((int) id) == -1) _exit(30); ! } x = env_get("UID"); ! if (x) { scan_ulong(x,&id); ! if (prot_uid((int) id) == -1) _exit(30); ! } ! ! doit(); } --- 1,39 ---- #include "env.h" #include "exit.h" #include "scan.h" + #include "config.h" ! extern void doit(int); main(int argc,char **argv) { char *x; unsigned long id; + x = argv[1]; if (x) { ! if (chdir(x) == -1) _exit(ERR_CHDIR); } + if (chroot(".") == -1) _exit(ERR_UIDGID); x = env_get("GID"); ! if (x) scan_ulong(x,&id); ! else ! id=DEFAULT_GID; ! if (id < DEFAULT_MINGID) _exit(ERR_UIDGID); ! if (prot_gid((int) id) == -1) _exit(ERR_UIDGID); x = env_get("UID"); ! if (x) scan_ulong(x,&id); ! else ! id=DEFAULT_UID; ! if (id < DEFAULT_MINUID) _exit(ERR_UIDGID); ! if (prot_uid((int) id) == -1) _exit(ERR_UIDGID); ! ! if (argc > 2) ! if (argv[3][0] == 'w') doit(1); ! doit(0); } diff -crN publicfile-0.52/open_trunc.c qftpd-0.20/open_trunc.c *** publicfile-0.52/open_trunc.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/open_trunc.c Tue Apr 17 21:24:47 2001 *************** *** 4,6 **** --- 4,9 ---- int open_trunc(fn) char *fn; { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } + + int open_append(fn) char *fn; + { return open(fn,O_WRONLY | O_NDELAY | O_APPEND); } diff -crN publicfile-0.52/pathdecode.c qftpd-0.20/pathdecode.c *** publicfile-0.52/pathdecode.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/pathdecode.c Tue Apr 17 21:24:48 2001 *************** *** 1,6 **** #include "pathdecode.h" ! void pathdecode(stralloc *fn) { int i; int j; --- 1,57 ---- #include "pathdecode.h" ! ! /*int pathdecode(char *arg, stralloc *dir) ! { ! int i; //index into arg, arg is the null terminated path string ! char x; //current character ! char w; //previous character ! int len; //temp len variable for str_len ! ! len = str_len(PATH_OKCHARS); ! i = 0; ! if (!stralloc_copys(&fn,"./")) _exit(21); //start every path with a '/' character ! // if (arg[0] == '/') i++; //if user specifies a slash, account for it ! ! if (*arg != '/') { ! if (!stralloc_cat(&fn,&dir)) _exit(21); ! if (!stralloc_append(&fn,"/")) _exit(21); ! } ! else i++; ! for (i=i; i0) { ! w = arg[i-1]; ! if (w == '/') { ! if (x == '/') return(-1); ! #ifdef HIDE_DOT_FILES ! if (x == '.') { ! #ifdef MANGLE_PATH ! x = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif ! #endif ! } ! } ! } ! if (str_chr(PATH_OKCHARS,x) == len) { ! #ifdef MANGLE_PATH ! x = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif ! } ! arg[i] = x; ! } ! if (!stralloc_cat(&fn,&arg)) _exit(21); ! if (!stralloc_0(&fn)) _exit(21); ! return(0); ! } ! */ ! int pathdecode(stralloc *fn) { int i; int j; *************** *** 11,20 **** ch = fn->s[i]; if (ch == 0) ch = '\n'; if (j && (fn->s[j - 1] == '/')) { ! if (ch == '.') ch = ':'; ! if (ch == '/') continue; } fn->s[j++] = ch; } fn->len = j; } --- 62,89 ---- ch = fn->s[i]; if (ch == 0) ch = '\n'; if (j && (fn->s[j - 1] == '/')) { ! #ifdef HIDE_DOT_FILES ! if (ch == '.') { ! #ifdef MANGLE_PATH ! ch = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif ! } ! #endif ! /* if (ch == '/') continue; */ ! } ! if (str_chr(PATH_OKCHARS,fn->s[j]) == str_len(PATH_OKCHARS)) { ! #ifdef MANGLE_PATH ! ch = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif } fn->s[j++] = ch; } fn->len = j; + return(0); } diff -crN publicfile-0.52/pathdecode.h qftpd-0.20/pathdecode.h *** publicfile-0.52/pathdecode.h Tue Nov 9 02:23:46 1999 --- qftpd-0.20/pathdecode.h Tue Apr 17 21:24:48 2001 *************** *** 1,8 **** #ifndef PATHDECODE_H #define PATHDECODE_H ! #include "stralloc.h" ! extern void pathdecode(stralloc *); #endif --- 1,9 ---- #ifndef PATHDECODE_H #define PATHDECODE_H ! #include "config.h" ! #include "server.h" ! extern int pathdecode(stralloc *); #endif diff -crN publicfile-0.52/rmtargets qftpd-0.20/rmtargets *** publicfile-0.52/rmtargets Wed Dec 31 19:00:00 1969 --- qftpd-0.20/rmtargets Mon Apr 23 14:55:31 2001 *************** *** 0 **** --- 1,128 ---- + #!/bin/sh + rm load + rm compile + rm systype + rm hasdevtcp.h + rm configure.o + rm auto-str.o + rm makelib + rm substdio.o + rm substdi.o + rm substdo.o + rm substdio_copy.o + rm subfderr.o + rm substdio.a + rm error.o + rm error_str.o + rm error_temp.o + rm error.a + rm byte_chr.o + rm byte_copy.o + rm byte_cr.o + rm byte_diff.o + rm byte_rchr.o + rm byte_zero.o + rm str_chr.o + rm str_diff.o + rm str_len.o + rm str_rchr.o + rm str_start.o + rm str.a + rm auto-str + rm auto_home.c + rm auto_home.o + rm strerr_die.o + rm strerr_sys.o + rm strerr.a + rm open_read.o + rm open_trunc.o + rm open.a + rm configure + rm choose + rm uint64.h + rm httpd.o + rm main.o + rm pathdecode.o + rm file.o + rm filetype.o + rm httpdate.o + rm percent.o + rm chkshsgr.o + rm chkshsgr + rm hasshsgr.h + rm prot.o + rm select.h + rm timeoutread.o + rm timeoutwrite.o + rm caldate_fmjd.o + rm caltime_utc.o + rm leapsecs_init.o + rm leapsecs_read.o + rm leapsecs_sub.o + rm tai_now.o + rm tai_sub.o + rm tai_unpack.o + rm libtai.a + rm case_diffs.o + rm case_lowerb.o + rm case_startb.o + rm case.a + rm getln.o + rm getln2.o + rm getln.a + rm stralloc_cat.o + rm stralloc_catb.o + rm stralloc_cats.o + rm stralloc_copy.o + rm stralloc_eady.o + rm stralloc_opyb.o + rm stralloc_opys.o + rm stralloc_pend.o + rm stralloc_num.o + rm stralloc.a + rm alloc.o + rm alloc_re.o + rm alloc.a + rm hassgprm.h + rm sig_block.o + rm hassgact.h + rm sig_catch.o + rm sig_pause.o + rm sig_pipe.o + rm sig.a + rm env.o + rm env.a + rm fmt_str.o + rm fmt_uint.o + rm fmt_ulong.o + rm fmt_xlong.o + rm scan_ulong.o + rm fs.a + rm socket.lib + rm httpd + rm ftpd.o + rm direntry.h + rm fetch.o + rm ip.o + rm timeoutconn.o + rm timeoutaccept.o + rm ndelay_on.o + rm ndelay_off.o + rm ndelay.a + rm ftpd + rm rts + rm prog + rm install.o + rm hier.o + rm install + rm instcheck.o + rm instcheck + rm it + rm setup + rm check + rm auth.ftpd + rm auth.ftpd.o + rm utime + rm utime.o + rm wait_nohang.o + rm wait_pid.o diff -crN publicfile-0.52/server.h qftpd-0.20/server.h *** publicfile-0.52/server.h Wed Dec 31 19:00:00 1969 --- qftpd-0.20/server.h Tue Apr 17 21:24:51 2001 *************** *** 0 **** --- 1,22 ---- + #ifndef SERVER_H + #define SERVER_H + + #include "stralloc.h" + + typedef struct { + int toread; /*reading i/o timeout seconds*/ + int towrite; /*writing i/o timeout seconds*/ + int toidle; /*idle timeout seconds*/ + int toconn; /*connection timeout seconds*/ + int write; /*1=writing enabled, else=writing disabled*/ + #ifdef BADFILES + char *badfiles; + #endif + } ServerConfig; + + extern ServerConfig config; + extern stralloc dir; + extern stralloc fn; + extern stralloc rnfr; + extern stralloc rnto; + #endif diff -crN publicfile-0.52/str.h qftpd-0.20/str.h *** publicfile-0.52/str.h Tue Nov 9 02:23:46 1999 --- qftpd-0.20/str.h Tue Apr 17 21:24:53 2001 *************** *** 10,14 **** --- 10,15 ---- extern int str_start(); #define str_equal(s,t) (!str_diff((s),(t))) + #define str_equaln(s,t,l) (!str_diffn((s),(t),(l))) #endif diff -crN publicfile-0.52/str_diff.c qftpd-0.20/str_diff.c *** publicfile-0.52/str_diff.c Tue Nov 9 02:23:46 1999 --- qftpd-0.20/str_diff.c Tue Apr 17 21:24:53 2001 *************** *** 15,17 **** --- 15,30 ---- return ((int)(unsigned int)(unsigned char) x) - ((int)(unsigned int)(unsigned char) *t); } + + int str_diffn(s,t,len) + char *s; + char *t; + int len; + { + for(len=len;len>0;len--) { + if (*s != *t) break; + if (!*s) break; + ++s; ++t; + } + return(len); + } diff -crN publicfile-0.52/wait.3 qftpd-0.20/wait.3 *** publicfile-0.52/wait.3 Wed Dec 31 19:00:00 1969 --- qftpd-0.20/wait.3 Tue Apr 17 21:25:04 2001 *************** *** 0 **** --- 1,93 ---- + .TH wait 3 + .SH NAME + wait \- check child process status + .SH SYNTAX + .B #include + + int \fBwait_nohang\fP(&\fIwstat\fR); + .br + int \fBwait_stop\fP(&\fIwstat\fR); + .br + int \fBwait_stopnohang\fP(&\fIwstat\fR); + .br + int \fBwait_pid\fP(&\fIwstat\fR,\fIpid\fR); + + int \fBwait_exitcode\fP(\fIwstat\fR); + .br + int \fBwait_crashed\fP(\fIwstat\fR); + .br + int \fBwait_stopped\fP(\fIwstat\fR); + .br + int \fBwait_stopsig\fP(\fIwstat\fR); + + int \fIpid\fR; + .br + int \fIwstat\fR; + .SH DESCRIPTION + .B wait_nohang + looks for zombies (child processes that have exited). + If it sees a zombie, + it eliminates the zombie, + puts the zombie's exit status into + .IR wstat , + and returns the zombie's process ID. + If there are several zombies, + .B wait_nohang + picks one. + If there are children but no zombies, + .B wait_nohang + returns 0. + If there are no children, + .B wait_nohang + returns -1, + setting + .B errno + appropriately. + + .B wait_stopnohang + is similar to + .BR wait_nohang , + but it also looks for children that have stopped. + + .B wait_stop + is similar to + .BR wait_stopnohang , + but if there are children it will pause waiting for one of them + to stop or exit. + + .B wait_pid + waits for child process + .I pid + to exit. + It eliminates any zombie that shows up in the meantime, + discarding the exit status. + + .B wait_stop + and + .B wait_pid + retry upon + .BR error_intr . + .SH "STATUS PARSING" + If the child stopped, + .B wait_stopped + is nonzero; + .B wait_stopsig + is the signal that caused the child to stop. + + If the child exited by crashing, + .B wait_stopped + is zero; + .B wait_crashed + is nonzero. + + If the child exited normally, + .B wait_stopped + is zero; + .B wait_crashed + is zero; + and + .B wait_exitcode + is the child's exit code. + .SH "SEE ALSO" + wait(2), + error(3) Binary files publicfile-0.52/wait.a and qftpd-0.20/wait.a differ diff -crN publicfile-0.52/wait.h qftpd-0.20/wait.h *** publicfile-0.52/wait.h Wed Dec 31 19:00:00 1969 --- qftpd-0.20/wait.h Tue Apr 17 21:25:05 2001 *************** *** 0 **** --- 1,14 ---- + #ifndef WAIT_H + #define WAIT_H + + extern int wait_pid(); + extern int wait_nohang(); + extern int wait_stop(); + extern int wait_stopnohang(); + + #define wait_crashed(w) ((w) & 127) + #define wait_exitcode(w) ((w) >> 8) + #define wait_stopsig(w) ((w) >> 8) + #define wait_stopped(w) (((w) & 127) == 127) + + #endif diff -crN publicfile-0.52/wait_nohang.c qftpd-0.20/wait_nohang.c *** publicfile-0.52/wait_nohang.c Wed Dec 31 19:00:00 1969 --- qftpd-0.20/wait_nohang.c Tue Apr 17 21:25:05 2001 *************** *** 0 **** --- 1,12 ---- + #include + #include + #include "haswaitp.h" + + int wait_nohang(wstat) int *wstat; + { + #ifdef HASWAITPID + return waitpid(-1,wstat,WNOHANG); + #else + return wait3(wstat,WNOHANG,(struct rusage *) 0); + #endif + } diff -crN publicfile-0.52/wait_pid.c qftpd-0.20/wait_pid.c *** publicfile-0.52/wait_pid.c Wed Dec 31 19:00:00 1969 --- qftpd-0.20/wait_pid.c Tue Apr 17 21:25:05 2001 *************** *** 0 **** --- 1,39 ---- + #include + #include + #include "error.h" + #include "haswaitp.h" + + #ifdef HASWAITPID + + int wait_pid(wstat,pid) int *wstat; int pid; + { + int r; + + do + r = waitpid(pid,wstat,0); + while ((r == -1) && (errno == error_intr)); + return r; + } + + #else + + /* XXX untested */ + /* XXX breaks down with more than two children */ + static int oldpid = 0; + static int oldwstat; /* defined if(oldpid) */ + + int wait_pid(wstat,pid) int *wstat; int pid; + { + int r; + + if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } + + do { + r = wait(wstat); + if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } + } + while ((r == -1) && (errno == error_intr)); + return r; + } + + #endif