From 135c95a58297753db2ae56a95840175411efd5b6 Mon Sep 17 00:00:00 2001 From: "Jordan K. Hubbard" Date: Fri, 17 Jan 1997 15:58:58 +0000 Subject: [PATCH] Add timeout support to sysinstall's general media handling, allow SIGINT to stand for "time out now!" in certain cases. --- release/sysinstall/attr.c | 9 +------- release/sysinstall/dist.c | 38 ++++++++++++++++++++++++++++---- release/sysinstall/media.c | 22 ++++++++++++++++++ release/sysinstall/sysinstall.h | 6 +++++ release/sysinstall/system.c | 29 ++++++++++++++++++++++++ usr.sbin/sade/sade.h | 6 +++++ usr.sbin/sade/system.c | 29 ++++++++++++++++++++++++ usr.sbin/sysinstall/dist.c | 38 ++++++++++++++++++++++++++++---- usr.sbin/sysinstall/media.c | 22 ++++++++++++++++++ usr.sbin/sysinstall/sysinstall.h | 6 +++++ usr.sbin/sysinstall/system.c | 29 ++++++++++++++++++++++++ 11 files changed, 218 insertions(+), 16 deletions(-) diff --git a/release/sysinstall/attr.c b/release/sysinstall/attr.c index d98af51bc8c9..3b0031687cf8 100644 --- a/release/sysinstall/attr.c +++ b/release/sysinstall/attr.c @@ -165,19 +165,12 @@ attr_match(Attribs *attr, char *name) if (isDebug()) msgDebug("Trying to match attribute `%s'\n", name); - for (n = 0; attr[n].name[0] && strcasecmp(attr[n].name, name) != 0; n++) { - if (isDebug()) - msgDebug("Skipping attribute %u\n", n); - } - - if (isDebug()) - msgDebug("Stopped on attribute %u\n", n); + for (n = 0; attr[n].name[0] && strcasecmp(attr[n].name, name); n++); if (attr[n].name[0]) { if (isDebug()) msgDebug("Returning `%s'\n", attr[n].value); return(attr[n].value); } - return NULL; } diff --git a/release/sysinstall/dist.c b/release/sysinstall/dist.c index cf2b3c7d2469..ea7a78157621 100644 --- a/release/sysinstall/dist.c +++ b/release/sysinstall/dist.c @@ -36,6 +36,7 @@ #include "sysinstall.h" #include +#include unsigned int Dists; unsigned int DESDists; @@ -339,6 +340,13 @@ distSetXF86(dialogMenuItem *self) return i | DITEM_RECREATE; } +/* timeout handler */ +static void +media_timeout(int sig) +{ + AlarmWentOff = TRUE; +} + static Boolean distExtract(char *parent, Distribution *me) { @@ -350,6 +358,7 @@ distExtract(char *parent, Distribution *me) Attribs *dist_attr; WINDOW *w = savescr(); struct timeval start, stop; + struct sigaction old, new; status = TRUE; dialog_clear_norefresh(); @@ -388,15 +397,26 @@ distExtract(char *parent, Distribution *me) snprintf(buf, sizeof buf, "%s/%s.inf", path, dist); fp = mediaDevice->get(mediaDevice, buf, TRUE); if (fp > 0) { + int status; + if (isDebug()) msgDebug("Parsing attributes file for distribution %s\n", dist); dist_attr = alloca(sizeof(Attribs) * MAX_ATTRIBS); - if (DITEM_STATUS(attr_parse(dist_attr, fp)) == DITEM_FAILURE) + + /* Make ^C fake a sudden timeout */ + new.sa_handler = media_timeout; + new.sa_flags = 0; + new.sa_mask = 0; + sigaction(SIGINT, &new, &old); + + alarm_set(MEDIA_TIMEOUT, media_timeout); + status = attr_parse(dist_attr, fp); + alarm_clear(); + sigaction(SIGINT, &old, NULL); /* Restore signal handler */ + if (DITEM_STATUS(status) == DITEM_FAILURE) msgConfirm("Cannot parse information file for the %s distribution!\n" "Please verify that your media is valid and try again.", dist); else { - if (isDebug()) - msgDebug("Looking for attribute `pieces'\n"); tmp = attr_match(dist_attr, "pieces"); if (tmp) numchunks = strtol(tmp, 0, 0); @@ -464,11 +484,20 @@ distExtract(char *parent, Distribution *me) } snprintf(prompt, sizeof prompt, "Extracting %s into %s directory...", dist, root_bias(me[i].my_dir)); dialog_gauge("Progress", prompt, 8, 15, 6, 50, (int)((float)(chunk + 1) / numchunks * 100)); + + /* Make ^C fake a sudden timeout */ + new.sa_handler = media_timeout; + new.sa_flags = 0; + new.sa_mask = 0; + sigaction(SIGINT, &new, &old); + while (1) { int seconds; + alarm_set(MEDIA_TIMEOUT, media_timeout); n = fread(buf, 1, BUFSIZ, fp); - if (n <= 0) + alarm_clear(); + if (n <= 0 || AlarmWentOff) break; total += n; @@ -495,6 +524,7 @@ distExtract(char *parent, Distribution *me) goto punt; } } + sigaction(SIGINT, &old, NULL); /* Restore signal handler */ fclose(fp); } close(fd2); diff --git a/release/sysinstall/media.c b/release/sysinstall/media.c index 8bade8adf5a3..cc8e2aa967c5 100644 --- a/release/sysinstall/media.c +++ b/release/sysinstall/media.c @@ -35,6 +35,7 @@ */ #include "sysinstall.h" +#include #include #include #include @@ -515,6 +516,11 @@ mediaExtractDistEnd(int zpid, int cpid) return TRUE; } +static void +media_timeout(int sig) +{ + AlarmWentOff = TRUE; +} Boolean mediaExtractDist(char *dir, char *dist, FILE *fp) @@ -522,6 +528,7 @@ mediaExtractDist(char *dir, char *dist, FILE *fp) int i, j, total, seconds, zpid, cpid, pfd[2], qfd[2]; char buf[BUFSIZ]; struct timeval start, stop; + struct sigaction new, old; if (!dir) dir = "/"; @@ -582,7 +589,19 @@ mediaExtractDist(char *dir, char *dist, FILE *fp) total = 0; (void)gettimeofday(&start, (struct timezone *)0); + /* Make ^C fake a sudden timeout */ + new.sa_handler = media_timeout; + new.sa_flags = 0; + new.sa_mask = 0; + sigaction(SIGINT, &new, &old); + + alarm_set(MEDIA_TIMEOUT, media_timeout); while ((i = fread(buf, 1, BUFSIZ, fp)) > 0) { + alarm_clear(); + if (AlarmWentOff) { + msgDebug("Failure to read from media - timeout or user abort.\n"); + break; + } if (write(qfd[1], buf, i) != i) { msgDebug("Write error on transfer to cpio process, try of %d bytes\n", i); break; @@ -600,7 +619,10 @@ mediaExtractDist(char *dir, char *dist, FILE *fp) msgInfo("%10d bytes read from %s dist @ %.1f KB/sec.", total, dist, (total / seconds) / 1024.0); } + alarm_set(MEDIA_TIMEOUT, media_timeout); } + alarm_clear(); + sigaction(SIGINT, &old, NULL); /* restore sigint */ close(qfd[1]); i = waitpid(zpid, &j, 0); diff --git a/release/sysinstall/sysinstall.h b/release/sysinstall/sysinstall.h index 0eea56fb046d..69e400a6a0f2 100644 --- a/release/sysinstall/sysinstall.h +++ b/release/sysinstall/sysinstall.h @@ -68,6 +68,9 @@ #define INTERFACE_MAX 50 /* Maximum number of network interfaces we'll deal with */ #define IO_ERROR -2 /* Status code for I/O error rather than normal EOF */ +/* Number of seconds to wait for data to come off even the slowest media */ +#define MEDIA_TIMEOUT 300 + /* * I make some pretty gross assumptions about having a max of 50 chunks * total - 8 slices and 42 partitions. I can't easily display many more @@ -301,6 +304,7 @@ typedef struct _devPriv { /*** Externs ***/ +extern Boolean AlarmWentOff; /* Convenience variable for alarm_foo() stuff */ extern int DebugFD; /* Where diagnostic output goes */ extern Boolean Fake; /* Don't actually modify anything - testing */ extern Boolean SystemWasInstalled; /* Did we install it? */ @@ -627,6 +631,8 @@ extern int package_extract(Device *dev, char *name, Boolean depended); extern Boolean package_exists(char *name); /* system.c */ +extern void alarm_clear(void); +extern void alarm_set(int delay, void (*handler)(int sig)); extern void systemInitialize(int argc, char **argv); extern void systemShutdown(int status); extern int execExecute(char *cmd, char *name); diff --git a/release/sysinstall/system.c b/release/sysinstall/system.c index 354f80522838..1fc46964da64 100644 --- a/release/sysinstall/system.c +++ b/release/sysinstall/system.c @@ -47,6 +47,35 @@ handle_intr(int sig) restorescr(save); } +/* Public variable for ease of use - handler should set it if interested */ +Boolean AlarmWentOff; + +/* Simple alarm interface */ +void +alarm_set(int delay, void (*handler)(int sig)) +{ + struct sigaction act; + + act.sa_handler = handler; + act.sa_flags = 0; + act.sa_mask = 0; + sigaction(SIGALRM, &act, NULL); + AlarmWentOff = FALSE; + alarm(delay); +} + +void +alarm_clear(void) +{ + struct sigaction act; + + alarm(0); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + act.sa_mask = 0; + sigaction(SIGALRM, &act, NULL); +} + /* Expand a file into a convenient location, nuking it each time */ static char * expand(char *fname) diff --git a/usr.sbin/sade/sade.h b/usr.sbin/sade/sade.h index 0eea56fb046d..69e400a6a0f2 100644 --- a/usr.sbin/sade/sade.h +++ b/usr.sbin/sade/sade.h @@ -68,6 +68,9 @@ #define INTERFACE_MAX 50 /* Maximum number of network interfaces we'll deal with */ #define IO_ERROR -2 /* Status code for I/O error rather than normal EOF */ +/* Number of seconds to wait for data to come off even the slowest media */ +#define MEDIA_TIMEOUT 300 + /* * I make some pretty gross assumptions about having a max of 50 chunks * total - 8 slices and 42 partitions. I can't easily display many more @@ -301,6 +304,7 @@ typedef struct _devPriv { /*** Externs ***/ +extern Boolean AlarmWentOff; /* Convenience variable for alarm_foo() stuff */ extern int DebugFD; /* Where diagnostic output goes */ extern Boolean Fake; /* Don't actually modify anything - testing */ extern Boolean SystemWasInstalled; /* Did we install it? */ @@ -627,6 +631,8 @@ extern int package_extract(Device *dev, char *name, Boolean depended); extern Boolean package_exists(char *name); /* system.c */ +extern void alarm_clear(void); +extern void alarm_set(int delay, void (*handler)(int sig)); extern void systemInitialize(int argc, char **argv); extern void systemShutdown(int status); extern int execExecute(char *cmd, char *name); diff --git a/usr.sbin/sade/system.c b/usr.sbin/sade/system.c index 354f80522838..1fc46964da64 100644 --- a/usr.sbin/sade/system.c +++ b/usr.sbin/sade/system.c @@ -47,6 +47,35 @@ handle_intr(int sig) restorescr(save); } +/* Public variable for ease of use - handler should set it if interested */ +Boolean AlarmWentOff; + +/* Simple alarm interface */ +void +alarm_set(int delay, void (*handler)(int sig)) +{ + struct sigaction act; + + act.sa_handler = handler; + act.sa_flags = 0; + act.sa_mask = 0; + sigaction(SIGALRM, &act, NULL); + AlarmWentOff = FALSE; + alarm(delay); +} + +void +alarm_clear(void) +{ + struct sigaction act; + + alarm(0); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + act.sa_mask = 0; + sigaction(SIGALRM, &act, NULL); +} + /* Expand a file into a convenient location, nuking it each time */ static char * expand(char *fname) diff --git a/usr.sbin/sysinstall/dist.c b/usr.sbin/sysinstall/dist.c index cf2b3c7d2469..ea7a78157621 100644 --- a/usr.sbin/sysinstall/dist.c +++ b/usr.sbin/sysinstall/dist.c @@ -36,6 +36,7 @@ #include "sysinstall.h" #include +#include unsigned int Dists; unsigned int DESDists; @@ -339,6 +340,13 @@ distSetXF86(dialogMenuItem *self) return i | DITEM_RECREATE; } +/* timeout handler */ +static void +media_timeout(int sig) +{ + AlarmWentOff = TRUE; +} + static Boolean distExtract(char *parent, Distribution *me) { @@ -350,6 +358,7 @@ distExtract(char *parent, Distribution *me) Attribs *dist_attr; WINDOW *w = savescr(); struct timeval start, stop; + struct sigaction old, new; status = TRUE; dialog_clear_norefresh(); @@ -388,15 +397,26 @@ distExtract(char *parent, Distribution *me) snprintf(buf, sizeof buf, "%s/%s.inf", path, dist); fp = mediaDevice->get(mediaDevice, buf, TRUE); if (fp > 0) { + int status; + if (isDebug()) msgDebug("Parsing attributes file for distribution %s\n", dist); dist_attr = alloca(sizeof(Attribs) * MAX_ATTRIBS); - if (DITEM_STATUS(attr_parse(dist_attr, fp)) == DITEM_FAILURE) + + /* Make ^C fake a sudden timeout */ + new.sa_handler = media_timeout; + new.sa_flags = 0; + new.sa_mask = 0; + sigaction(SIGINT, &new, &old); + + alarm_set(MEDIA_TIMEOUT, media_timeout); + status = attr_parse(dist_attr, fp); + alarm_clear(); + sigaction(SIGINT, &old, NULL); /* Restore signal handler */ + if (DITEM_STATUS(status) == DITEM_FAILURE) msgConfirm("Cannot parse information file for the %s distribution!\n" "Please verify that your media is valid and try again.", dist); else { - if (isDebug()) - msgDebug("Looking for attribute `pieces'\n"); tmp = attr_match(dist_attr, "pieces"); if (tmp) numchunks = strtol(tmp, 0, 0); @@ -464,11 +484,20 @@ distExtract(char *parent, Distribution *me) } snprintf(prompt, sizeof prompt, "Extracting %s into %s directory...", dist, root_bias(me[i].my_dir)); dialog_gauge("Progress", prompt, 8, 15, 6, 50, (int)((float)(chunk + 1) / numchunks * 100)); + + /* Make ^C fake a sudden timeout */ + new.sa_handler = media_timeout; + new.sa_flags = 0; + new.sa_mask = 0; + sigaction(SIGINT, &new, &old); + while (1) { int seconds; + alarm_set(MEDIA_TIMEOUT, media_timeout); n = fread(buf, 1, BUFSIZ, fp); - if (n <= 0) + alarm_clear(); + if (n <= 0 || AlarmWentOff) break; total += n; @@ -495,6 +524,7 @@ distExtract(char *parent, Distribution *me) goto punt; } } + sigaction(SIGINT, &old, NULL); /* Restore signal handler */ fclose(fp); } close(fd2); diff --git a/usr.sbin/sysinstall/media.c b/usr.sbin/sysinstall/media.c index 8bade8adf5a3..cc8e2aa967c5 100644 --- a/usr.sbin/sysinstall/media.c +++ b/usr.sbin/sysinstall/media.c @@ -35,6 +35,7 @@ */ #include "sysinstall.h" +#include #include #include #include @@ -515,6 +516,11 @@ mediaExtractDistEnd(int zpid, int cpid) return TRUE; } +static void +media_timeout(int sig) +{ + AlarmWentOff = TRUE; +} Boolean mediaExtractDist(char *dir, char *dist, FILE *fp) @@ -522,6 +528,7 @@ mediaExtractDist(char *dir, char *dist, FILE *fp) int i, j, total, seconds, zpid, cpid, pfd[2], qfd[2]; char buf[BUFSIZ]; struct timeval start, stop; + struct sigaction new, old; if (!dir) dir = "/"; @@ -582,7 +589,19 @@ mediaExtractDist(char *dir, char *dist, FILE *fp) total = 0; (void)gettimeofday(&start, (struct timezone *)0); + /* Make ^C fake a sudden timeout */ + new.sa_handler = media_timeout; + new.sa_flags = 0; + new.sa_mask = 0; + sigaction(SIGINT, &new, &old); + + alarm_set(MEDIA_TIMEOUT, media_timeout); while ((i = fread(buf, 1, BUFSIZ, fp)) > 0) { + alarm_clear(); + if (AlarmWentOff) { + msgDebug("Failure to read from media - timeout or user abort.\n"); + break; + } if (write(qfd[1], buf, i) != i) { msgDebug("Write error on transfer to cpio process, try of %d bytes\n", i); break; @@ -600,7 +619,10 @@ mediaExtractDist(char *dir, char *dist, FILE *fp) msgInfo("%10d bytes read from %s dist @ %.1f KB/sec.", total, dist, (total / seconds) / 1024.0); } + alarm_set(MEDIA_TIMEOUT, media_timeout); } + alarm_clear(); + sigaction(SIGINT, &old, NULL); /* restore sigint */ close(qfd[1]); i = waitpid(zpid, &j, 0); diff --git a/usr.sbin/sysinstall/sysinstall.h b/usr.sbin/sysinstall/sysinstall.h index 0eea56fb046d..69e400a6a0f2 100644 --- a/usr.sbin/sysinstall/sysinstall.h +++ b/usr.sbin/sysinstall/sysinstall.h @@ -68,6 +68,9 @@ #define INTERFACE_MAX 50 /* Maximum number of network interfaces we'll deal with */ #define IO_ERROR -2 /* Status code for I/O error rather than normal EOF */ +/* Number of seconds to wait for data to come off even the slowest media */ +#define MEDIA_TIMEOUT 300 + /* * I make some pretty gross assumptions about having a max of 50 chunks * total - 8 slices and 42 partitions. I can't easily display many more @@ -301,6 +304,7 @@ typedef struct _devPriv { /*** Externs ***/ +extern Boolean AlarmWentOff; /* Convenience variable for alarm_foo() stuff */ extern int DebugFD; /* Where diagnostic output goes */ extern Boolean Fake; /* Don't actually modify anything - testing */ extern Boolean SystemWasInstalled; /* Did we install it? */ @@ -627,6 +631,8 @@ extern int package_extract(Device *dev, char *name, Boolean depended); extern Boolean package_exists(char *name); /* system.c */ +extern void alarm_clear(void); +extern void alarm_set(int delay, void (*handler)(int sig)); extern void systemInitialize(int argc, char **argv); extern void systemShutdown(int status); extern int execExecute(char *cmd, char *name); diff --git a/usr.sbin/sysinstall/system.c b/usr.sbin/sysinstall/system.c index 354f80522838..1fc46964da64 100644 --- a/usr.sbin/sysinstall/system.c +++ b/usr.sbin/sysinstall/system.c @@ -47,6 +47,35 @@ handle_intr(int sig) restorescr(save); } +/* Public variable for ease of use - handler should set it if interested */ +Boolean AlarmWentOff; + +/* Simple alarm interface */ +void +alarm_set(int delay, void (*handler)(int sig)) +{ + struct sigaction act; + + act.sa_handler = handler; + act.sa_flags = 0; + act.sa_mask = 0; + sigaction(SIGALRM, &act, NULL); + AlarmWentOff = FALSE; + alarm(delay); +} + +void +alarm_clear(void) +{ + struct sigaction act; + + alarm(0); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + act.sa_mask = 0; + sigaction(SIGALRM, &act, NULL); +} + /* Expand a file into a convenient location, nuking it each time */ static char * expand(char *fname)