summaryrefslogtreecommitdiffstats
path: root/lib/libftpio
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1996-12-17 20:19:35 +0000
committerjkh <jkh@FreeBSD.org>1996-12-17 20:19:35 +0000
commitb0e8bc6ae5fbcab68fc6fdcbd39bf81c3dcd129a (patch)
tree8179f0a08e678500d14a2f94552bf85172166c35 /lib/libftpio
parentb1c7666d3ff2a20b439ed338746001a84a91637c (diff)
downloadFreeBSD-src-b0e8bc6ae5fbcab68fc6fdcbd39bf81c3dcd129a.zip
FreeBSD-src-b0e8bc6ae5fbcab68fc6fdcbd39bf81c3dcd129a.tar.gz
Sanitize and extend SIGALRM timeout handling.
Diffstat (limited to 'lib/libftpio')
-rw-r--r--lib/libftpio/ftpio.c93
1 files changed, 59 insertions, 34 deletions
diff --git a/lib/libftpio/ftpio.c b/lib/libftpio/ftpio.c
index df8e659..5bc6457 100644
--- a/lib/libftpio/ftpio.c
+++ b/lib/libftpio/ftpio.c
@@ -14,7 +14,7 @@
* Turned inside out. Now returns xfers as new file ids, not as a special
* `state' of FTP_t
*
- * $Id: ftpio.c,v 1.18 1996/11/14 06:59:39 ache Exp $
+ * $Id: ftpio.c,v 1.20 1996/11/14 09:51:47 ache Exp $
*
*/
@@ -45,7 +45,7 @@
#endif
/* How to see by a given code whether or not the connection has timed out */
-#define FTP_TIMEOUT(code) (code == 421)
+#define FTP_TIMEOUT(code) (FtpTimedOut || code == FTP_TIMED_OUT)
/* Internal routines - deal only with internal FTP_t type */
static FTP_t ftp_new(void);
@@ -62,19 +62,28 @@ static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, in
static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto);
static int ftp_close(FTP_t ftp);
static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret);
+static void ftp_timeout(int sig);
+static void ftp_set_timeout(void);
+static void ftp_clear_timeout(void);
+
/* Global status variable - ick */
int FtpTimedOut;
-/* FTP status codes */
-#define FTP_ASCII_HAPPY 200
-#define FTP_BINARY_HAPPY 200
-#define FTP_PORT_HAPPY 200
+/* FTP happy status codes */
+#define FTP_GENERALLY_HAPPY 200
+#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY
+#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY
+#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY
+#define FTP_HAPPY_COMMENT 220
#define FTP_QUIT_HAPPY 221
#define FTP_TRANSFER_HAPPY 226
#define FTP_PASSIVE_HAPPY 227
#define FTP_CHDIR_HAPPY 250
+/* FTP unhappy status codes */
+#define FTP_TIMED_OUT 421
+
/*
* XXX
* gross! evil! bad! We really need an access primitive for cookie in stdio itself.
@@ -98,11 +107,11 @@ check_code(FTP_t ftp, int var, int preferred)
while (1) {
if (var == preferred)
return 0;
- else if (var == 226) /* last operation succeeded */
+ else if (var == FTP_TRANSFER_HAPPY) /* last operation succeeded */
var = get_a_number(ftp, NULL);
- else if (var == 220) /* chit-chat */
+ else if (var == FTP_HAPPY_COMMENT) /* chit-chat */
var = get_a_number(ftp, NULL);
- else if (var == 200) /* success codes */
+ else if (var == FTP_GENERALLY_HAPPY) /* general success code */
var = get_a_number(ftp, NULL);
else {
ftp->errno = var;
@@ -189,8 +198,7 @@ ftpGetSize(FILE *fp, char *name)
sprintf(p, "SIZE %s\r\n", name);
if (ftp->is_verbose)
fprintf(stderr, "Sending %s", p);
- i = writes(ftp->fd_ctrl, p);
- if (i)
+ if (writes(ftp->fd_ctrl, p))
return (off_t)-1;
i = get_a_number(ftp, &cp);
if (check_code(ftp, i, 213))
@@ -216,8 +224,7 @@ ftpGetModtime(FILE *fp, char *name)
sprintf(p, "MDTM %s\r\n", name);
if (ftp->is_verbose)
fprintf(stderr, "Sending %s", p);
- i = writes(ftp->fd_ctrl, p);
- if (i)
+ if (writes(ftp->fd_ctrl, p))
return (time_t)0;
i = get_a_number(ftp, &cp);
if (check_code(ftp, i, 213))
@@ -473,27 +480,44 @@ check_passive(FILE *fp)
}
static void
-ftp_timeout()
+ftp_timeout(int sig)
{
FtpTimedOut = TRUE;
/* Debug("ftp_pkg: ftp_timeout called - operation timed out"); */
}
+static void
+ftp_set_timeout(void)
+{
+ char *cp;
+ int ival;
+
+ FtpTimedOut = FALSE;
+ signal(SIGALRM, ftp_timeout);
+ cp = getenv("FTP_TIMEOUT_INTERVAL");
+ if (!cp || !(ival = atoi(cp)))
+ ival = 120;
+ alarm(ival);
+}
+
+static void
+ftp_clear_timeout(void)
+{
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+}
+
static int
writes(int fd, char *s)
{
int n, i = strlen(s);
- /* Set the timer */
- FtpTimedOut = FALSE;
- signal(SIGALRM, ftp_timeout);
- alarm(120);
- /* Debug("ftp_pkg: writing \"%s\" to ftp connection %d", s, fd); */
+ ftp_set_timeout();
n = write(fd, s, i);
- alarm(0);
- if (i != n)
- return FAILURE;
- return SUCCESS;
+ ftp_clear_timeout();
+ if (FtpTimedOut || i != n)
+ return TRUE;
+ return FALSE;
}
static __inline char *
@@ -502,16 +526,12 @@ get_a_line(FTP_t ftp)
static char buf[BUFSIZ];
int i,j;
- /* Set the timer */
- FtpTimedOut = FALSE;
- signal(SIGALRM, ftp_timeout);
-
/* Debug("ftp_pkg: trying to read a line from %d", ftp->fd_ctrl); */
for(i = 0; i < BUFSIZ;) {
- alarm(120);
+ ftp_set_timeout();
j = read(ftp->fd_ctrl, buf + i, 1);
- alarm(0);
- if (j != 1)
+ ftp_clear_timeout();
+ if (FtpTimedOut || j != 1)
return NULL;
if (buf[i] == '\r' || buf[i] == '\n') {
if (!i)
@@ -537,6 +557,8 @@ get_a_number(FTP_t ftp, char **q)
p = get_a_line(ftp);
if (!p) {
ftp_close(ftp);
+ if (FtpTimedOut)
+ return FTP_TIMED_OUT;
return FAILURE;
}
if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])))
@@ -606,10 +628,12 @@ cmd(FTP_t ftp, const char *fmt, ...)
strcat(p, "\r\n");
if (ftp->is_verbose)
fprintf(stderr, "Sending: %s", p);
- i = writes(ftp->fd_ctrl, p);
- if (i)
+ if (writes(ftp->fd_ctrl, p)) {
+ if (FtpTimedOut)
+ return FTP_TIMED_OUT;
return FAILURE;
- while ((i = get_a_number(ftp, NULL)) == 220);
+ }
+ while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT);
return i;
}
@@ -728,6 +752,7 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t
(void)close(s);
return FAILURE;
}
+
if (seekto && *seekto) {
i = cmd(ftp, "REST %d", *seekto);
if (i < 0 || FTP_TIMEOUT(i)) {
@@ -753,7 +778,7 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t
sin.sin_port = 0;
i = sizeof sin;
if (bind(s, (struct sockaddr *)&sin, i) < 0) {
- close (s);
+ close(s);
return FAILURE;
}
getsockname(s,(struct sockaddr *)&sin,&i);
OpenPOWER on IntegriCloud