aboutsummaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorYaroslav Tykhiy <ytykhiy@gmail.com>2002-02-15 18:02:43 +0000
committerYaroslav Tykhiy <ytykhiy@gmail.com>2002-02-15 18:02:43 +0000
commitcafc694e09ebcb19f2db65abe1452bd439f3c7f1 (patch)
tree108eb2de44f1299ae05a6f503da01477fae198f2 /libexec
parente90f396fcb541ef8f42eef744b91ce30ad71211e (diff)
Notes
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ftpd/ftpd.c117
1 files changed, 85 insertions, 32 deletions
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 004c27ecd00f..80f19e039cc0 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -78,7 +78,6 @@ static const char rcsid[] =
#include <netdb.h>
#include <pwd.h>
#include <grp.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -128,7 +127,6 @@ union sockunion pasv_addr;
int daemon_mode;
int data;
-jmp_buf errcatch, urgcatch;
int logged_in;
struct passwd *pw;
int debug;
@@ -153,6 +151,7 @@ int noepsv=0; /* EPSV command is disabled. */
int noretr=0; /* RETR command is disabled. */
int noguestretr=0; /* RETR command is disabled for anon users. */
+static volatile sig_atomic_t recvurg;
sig_atomic_t transflag;
off_t file_size;
off_t byte_count;
@@ -245,7 +244,8 @@ static void inithosts __P((void));
static void selecthost __P((union sockunion *));
#endif
static void ack __P((char *));
-static void myoob __P((int));
+static void sigurg __P((int));
+static void myoob __P((void));
static int checkuser __P((char *, char *, int));
static FILE *dataconn __P((char *, off_t, char *));
static void dolog __P((struct sockaddr *));
@@ -254,8 +254,9 @@ static void end_login __P((void));
static FILE *getdatasock __P((char *));
static char *gunique __P((char *));
static void lostconn __P((int));
+static void sigquit __P((int));
static int receive_data __P((FILE *, FILE *));
-static void send_data __P((FILE *, FILE *, off_t, off_t, int));
+static int send_data __P((FILE *, FILE *, off_t, off_t, int));
static struct passwd *
sgetpwnam __P((char *));
static char *sgetsave __P((char *));
@@ -288,8 +289,11 @@ main(argc, argv, envp)
char *bindname = NULL;
int family = AF_UNSPEC;
int enable_v4 = 0;
+ struct sigaction sa;
tzset(); /* in case no timezone database in ~ftp */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
#ifdef OLD_SETPROCTITLE
/*
@@ -421,7 +425,8 @@ main(argc, argv, envp)
syslog(LOG_ERR, "failed to become a daemon");
exit(1);
}
- (void) signal(SIGCHLD, reapchild);
+ sa.sa_handler = reapchild;
+ (void)sigaction(SIGCHLD, &sa, NULL);
/* init bind_sa */
memset(&hints, 0, sizeof(hints));
@@ -524,10 +529,23 @@ main(argc, argv, envp)
}
}
- (void) signal(SIGCHLD, SIG_IGN);
- (void) signal(SIGPIPE, lostconn);
- if (signal(SIGURG, myoob) == SIG_ERR)
- syslog(LOG_ERR, "signal: %m");
+ sa.sa_handler = SIG_DFL;
+ (void)sigaction(SIGCHLD, &sa, NULL);
+
+ sa.sa_handler = sigurg;
+ sa.sa_flags = 0; /* don't restart syscalls for SIGURG */
+ (void)sigaction(SIGURG, &sa, NULL);
+
+ sigfillset(&sa.sa_mask); /* block all signals in handler */
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = sigquit;
+ (void)sigaction(SIGHUP, &sa, NULL);
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGQUIT, &sa, NULL);
+ (void)sigaction(SIGTERM, &sa, NULL);
+
+ sa.sa_handler = lostconn;
+ (void)sigaction(SIGPIPE, &sa, NULL);
addrlen = sizeof(ctrl_addr);
if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
@@ -612,7 +630,6 @@ main(argc, argv, envp)
hostname[MAXHOSTNAMELEN - 1] = '\0';
#endif
reply(220, "%s FTP server (%s) ready.", hostname, version);
- (void) setjmp(errcatch);
for (;;)
(void) yyparse();
/* NOTREACHED */
@@ -628,6 +645,15 @@ lostconn(signo)
dologout(1);
}
+static void
+sigquit(signo)
+ int signo;
+{
+
+ syslog(LOG_ERR, "got signal %d", signo);
+ dologout(1);
+}
+
#ifdef VIRTUAL_HOSTING
/*
* read in virtual host tables (if they exist)
@@ -1727,7 +1753,7 @@ pdata_err:
*
* NB: Form isn't handled.
*/
-static void
+static int
send_data(instr, outstr, blksize, filesize, isreg)
FILE *instr, *outstr;
off_t blksize;
@@ -1740,14 +1766,12 @@ send_data(instr, outstr, blksize, filesize, isreg)
off_t cnt;
transflag++;
- if (setjmp(urgcatch)) {
- transflag = 0;
- return;
- }
switch (type) {
case TYPE_A:
while ((c = getc(instr)) != EOF) {
+ if (recvurg)
+ goto got_oob;
byte_count++;
if (c == '\n') {
if (ferror(outstr))
@@ -1756,6 +1780,8 @@ send_data(instr, outstr, blksize, filesize, isreg)
}
(void) putc(c, outstr);
}
+ if (recvurg)
+ goto got_oob;
fflush(outstr);
transflag = 0;
if (ferror(instr))
@@ -1763,7 +1789,7 @@ send_data(instr, outstr, blksize, filesize, isreg)
if (ferror(outstr))
goto data_err;
reply(226, "Transfer complete.");
- return;
+ return (0);
case TYPE_I:
case TYPE_L:
@@ -1785,6 +1811,8 @@ send_data(instr, outstr, blksize, filesize, isreg)
while (err != -1 && cnt < filesize) {
err = sendfile(filefd, netfd, offset, len,
(struct sf_hdtr *) NULL, &cnt, 0);
+ if (recvurg)
+ goto got_oob;
byte_count += cnt;
offset += cnt;
len -= cnt;
@@ -1798,14 +1826,14 @@ send_data(instr, outstr, blksize, filesize, isreg)
}
reply(226, "Transfer complete.");
- return;
+ return (0);
}
oldway:
if ((buf = malloc((u_int)blksize)) == NULL) {
transflag = 0;
perror_reply(451, "Local resource failure: malloc");
- return;
+ return (-1);
}
while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
@@ -1819,21 +1847,28 @@ oldway:
goto data_err;
}
reply(226, "Transfer complete.");
- return;
+ return (0);
default:
transflag = 0;
reply(550, "Unimplemented TYPE %d in send_data", type);
- return;
+ return (-1);
}
data_err:
transflag = 0;
perror_reply(426, "Data connection");
- return;
+ return (-1);
file_err:
transflag = 0;
perror_reply(551, "Error on input file");
+ return (-1);
+
+got_oob:
+ myoob();
+ recvurg = 0;
+ transflag = 0;
+ return (-1);
}
/*
@@ -1851,11 +1886,6 @@ receive_data(instr, outstr)
char buf[BUFSIZ];
transflag++;
- if (setjmp(urgcatch)) {
- transflag = 0;
- return (-1);
- }
-
bare_lfs = 0;
switch (type) {
@@ -1863,10 +1893,14 @@ receive_data(instr, outstr)
case TYPE_I:
case TYPE_L:
while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
+ if (recvurg)
+ goto got_oob;
if (write(fileno(outstr), buf, cnt) != cnt)
goto file_err;
byte_count += cnt;
}
+ if (recvurg)
+ goto got_oob;
if (cnt < 0)
goto data_err;
transflag = 0;
@@ -1879,6 +1913,8 @@ receive_data(instr, outstr)
case TYPE_A:
while ((c = getc(instr)) != EOF) {
+ if (recvurg)
+ goto got_oob;
byte_count++;
if (c == '\n')
bare_lfs++;
@@ -1894,6 +1930,8 @@ receive_data(instr, outstr)
(void) putc(c, outstr);
contin2: ;
}
+ if (recvurg)
+ goto got_oob;
fflush(outstr);
if (ferror(instr))
goto data_err;
@@ -1922,6 +1960,12 @@ file_err:
transflag = 0;
perror_reply(452, "Error writing file");
return (-1);
+
+got_oob:
+ myoob();
+ recvurg = 0;
+ transflag = 0;
+ return (-1);
}
void
@@ -2341,9 +2385,16 @@ dologout(status)
}
static void
-myoob(signo)
+sigurg(signo)
int signo;
{
+
+ recvurg = 1;
+}
+
+static void
+myoob()
+{
char *cp;
/* only process if transfer occurring */
@@ -2359,7 +2410,6 @@ myoob(signo)
tmpline[0] = '\0';
reply(426, "Transfer aborted. Data connection closed.");
reply(226, "Abort successful");
- longjmp(urgcatch, 1);
}
if (strcmp(cp, "STAT\r\n") == 0) {
tmpline[0] = '\0';
@@ -2675,10 +2725,6 @@ send_file_list(whichf)
simple = 1;
}
- if (setjmp(urgcatch)) {
- transflag = 0;
- goto out;
- }
while ((dirname = *dirlist++)) {
if (stat(dirname, &st) < 0) {
/*
@@ -2720,6 +2766,13 @@ send_file_list(whichf)
while ((dir = readdir(dirp)) != NULL) {
char nbuf[MAXPATHLEN];
+ if (recvurg) {
+ myoob();
+ recvurg = 0;
+ transflag = 0;
+ goto out;
+ }
+
if (dir->d_name[0] == '.' && dir->d_namlen == 1)
continue;
if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&