diff --git a/release/sysinstall/ftp.c b/release/sysinstall/ftp.c index f83dfdae5a97..0cbb53ffc91b 100644 --- a/release/sysinstall/ftp.c +++ b/release/sysinstall/ftp.c @@ -1,231 +1,231 @@ /* * The new sysinstall program. * * This is probably the last attempt in the `sysinstall' line, the next * generation being slated to essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include #include #include #include #include #include Boolean ftpInitted = FALSE; static FILE *OpenConn; int FtpPort; Boolean mediaInitFTP(Device *dev) { int i, code; char *cp, *rel, *hostname, *dir; char *user, *login_name, password[80]; Device *netdev = (Device *)dev->private; if (ftpInitted) return TRUE; if (isDebug()) msgDebug("Init routine for FTP called.\n"); if (OpenConn) { fclose(OpenConn); OpenConn = NULL; } /* If we can't initialize the network, bag it! */ if (netdev && !netdev->init(netdev)) return FALSE; try: cp = variable_get(VAR_FTP_PATH); if (!cp) { if (DITEM_STATUS(mediaSetFTP(NULL)) == DITEM_FAILURE || (cp = variable_get(VAR_FTP_PATH)) == NULL) { msgConfirm("Unable to get proper FTP path. FTP media not initialized."); if (netdev) netdev->shutdown(netdev); return FALSE; } } hostname = variable_get(VAR_FTP_HOST); dir = variable_get(VAR_FTP_DIR); if (!hostname || !dir) { msgConfirm("Missing FTP host or directory specification. FTP media not initialized,"); if (netdev) netdev->shutdown(netdev); return FALSE; } user = variable_get(VAR_FTP_USER); login_name = (!user || !*user) ? "anonymous" : user; if (variable_get(VAR_FTP_PASS)) SAFE_STRCPY(password, variable_get(VAR_FTP_PASS)); else sprintf(password, "installer@%s", variable_get(VAR_HOSTNAME)); msgNotify("Logging in to %s@%s..", login_name, hostname); if ((OpenConn = ftpLogin(hostname, login_name, password, FtpPort, isDebug(), &code)) == NULL) { - msgConfirm("Couldn't open FTP connection to %s, errcode = %d", hostname, code); + msgConfirm("Couldn't open FTP connection to %s:\n %s.", hostname, ftpErrString(code)); goto punt; } ftpPassive(OpenConn, !strcmp(variable_get(VAR_FTP_STATE), "passive")); ftpBinary(OpenConn); if (dir && *dir != '\0') { if ((i = ftpChdir(OpenConn, dir)) != 0) { if (i == 550) msgConfirm("No such directory ftp://%s/%s\n" "please check your URL and try again.", hostname, dir); else - msgConfirm("FTP chdir to ftp://%s/%s returned error status %d\n", hostname, dir, i); + msgConfirm("FTP chdir to ftp://%s/%s returned error status:\n %s.", hostname, dir, ftpErrString(i)); goto punt; } } /* Give it a shot - can't hurt to try and zoom in if we can, unless the release is set to __RELEASE or "none" which signifies that it's not set */ rel = variable_get(VAR_RELNAME); if (strcmp(rel, "__RELEASE") && strcmp(rel, "none")) i = ftpChdir(OpenConn, rel); else i = 0; if (i) { if (!msgYesNo("Warning: Can't CD to `%s' distribution on this\n" "FTP server. You may need to visit a different server for\n" "the release you're trying to fetch or go to the Options\n" "menu and to set the release name to explicitly match what's\n" "available on %s (or set to \"none\").\n\n" "Would you like to select another FTP server?", rel, hostname)) { variable_unset(VAR_FTP_PATH); if (DITEM_STATUS(mediaSetFTP(NULL)) == DITEM_FAILURE) goto punt; else goto try; } else goto punt; } if (isDebug()) msgDebug("mediaInitFTP was successful (logged in and chdir'd)\n"); ftpInitted = TRUE; return TRUE; punt: if (OpenConn != NULL) { fclose(OpenConn); OpenConn = NULL; } if (netdev) netdev->shutdown(netdev); variable_unset(VAR_FTP_PATH); return FALSE; } FILE * mediaGetFTP(Device *dev, char *file, Boolean probe) { int nretries = 1; FILE *fp; char *try, buf[PATH_MAX]; if (!OpenConn) { msgDebug("No FTP connection open, can't get file %s\n", file); return NULL; } try = file; while ((fp = ftpGet(OpenConn, try, 0)) == NULL) { /* If a hard fail, try to "bounce" the ftp server to clear it */ if (ftpErrno(OpenConn) != 550) { char *cp = variable_get(VAR_FTP_PATH); dev->shutdown(dev); variable_unset(VAR_FTP_PATH); /* If we can't re-initialize, just forget it */ if (!dev->init(dev)) { fclose(OpenConn); OpenConn = NULL; return NULL; } else variable_set2(VAR_FTP_PATH, cp); } else if (probe) return NULL; else { /* Try some alternatives */ switch (nretries++) { case 1: sprintf(buf, "dists/%s", file); try = buf; break; case 2: sprintf(buf, "%s/%s", variable_get(VAR_RELNAME), file); try = buf; break; case 3: sprintf(buf, "%s/dists/%s", variable_get(VAR_RELNAME), file); try = buf; break; case 4: try = file; break; } } } return fp; } void mediaShutdownFTP(Device *dev) { /* Device *netdev = (Device *)dev->private; */ if (!ftpInitted) return; msgDebug("FTP shutdown called. OpenConn = %x\n", OpenConn); if (OpenConn != NULL) { fclose(OpenConn); OpenConn = NULL; } /* if (netdev) netdev->shutdown(netdev); */ ftpInitted = FALSE; } diff --git a/release/sysinstall/index.c b/release/sysinstall/index.c index 79a035814d3e..736e2575e585 100644 --- a/release/sysinstall/index.c +++ b/release/sysinstall/index.c @@ -1,587 +1,587 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include "sysinstall.h" /* Macros and magic values */ #define MAX_MENU 12 #define _MAX_DESC 55 static int index_extract_one(Device *dev, PkgNodePtr top, PkgNodePtr who, Boolean depended); /* Smarter strdup */ inline char * _strdup(char *ptr) { return ptr ? strdup(ptr) : NULL; } static char *descrs[] = { "Package Selection", "To mark a package or select a category, move to it and press SPACE.\n" "To unmark a package, press SPACE again. To go to a previous menu,\n" "select the Cancel button. To search for a package by name, press ESC.\n" "To finally extract packages, you should Cancel all the way out of any\n" "submenus and then this top menu. NOTE: The All category selection\n" "creates a very large submenu. If you select it, please be patient.", "Package Targets", "These are the packages you've selected for extraction.\n\n" "If you're sure of these choices, select OK.\n" "If not, select Cancel to go back to the package selection menu.\n", "All", "All available packages in all categories.", "applications", "User application software.", "astro", "Applications related to astronomy.", "archivers", "Utilities for archiving and unarchiving data.", "audio", "Audio utilities - most require a supported sound card.", "benchmarks", "Utilities for measuring system performance.", "benchmarking", "Utilities for measuring system performance.", "cad", "Computer Aided Design utilities.", "chinese", "Ported software for the Chinese market.", "comms", "Communications utilities.", "databases", "Database software.", "devel", "Software development utilities and libraries.", "development", "Software development utilities and libraries.", "documentation", "Document preparation utilities.", "editors", "Common text editors.", "emulation", "Utilities for emulating other OS types.", "emulators", "Utilities for emulating other OS types.", "games", "Various and sundry amusements.", "graphics", "Graphics libraries and utilities.", "japanese", "Ported software for the Japanese market.", "lang", "Computer languages.", "languages", "Computer languages.", "libraries", "Software development libraries.", "mail", "Electronic mail packages and utilities.", "math", "Mathematical computation software.", "mbone", "Applications and utilities for the mbone.", "misc", "Miscellaneous utilities.", "net", "Networking utilities.", "networking", "Networking utilities.", "news", "USENET News support software.", "numeric", "Mathematical computation software.", "orphans", "Packages without a home elsewhere.", "plan9", "Software from the plan9 Operating System.", "print", "Utilities for dealing with printing.", "printing", "Utilities for dealing with printing.", "programming", "Software development utilities and libraries.", "russian", "Ported software for the Russian market.", "security", "System security software.", "shells", "Various shells (tcsh, bash, etc).", "sysutils", "Various system utilities.", "www", "WEB utilities (browers, HTTP servers, etc).", "troff", "TROFF Text formatting utilities.", "utils", "Various user utilities.", "utilities", "Various user utilities.", "vietnamese", "Ported software for the Vietnamese market.", "x11", "X Window System based utilities.", NULL, NULL, }; static char * fetch_desc(char *name) { int i; for (i = 0; descrs[i]; i += 2) { if (!strcmp(descrs[i], name)) return descrs[i + 1]; } return "No description provided"; } static PkgNodePtr new_pkg_node(char *name, node_type type) { PkgNodePtr tmp = safe_malloc(sizeof(PkgNode)); tmp->name = _strdup(name); tmp->type = type; return tmp; } static char * strip(char *buf) { int i; for (i = 0; buf[i]; i++) if (buf[i] == '\t' || buf[i] == '\n') buf[i] = ' '; return buf; } static IndexEntryPtr new_index(char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint, char *deps) { IndexEntryPtr tmp = safe_malloc(sizeof(IndexEntry)); tmp->name = _strdup(name); tmp->path = _strdup(pathto); tmp->prefix = _strdup(prefix); tmp->comment = _strdup(comment); tmp->descrfile = strip(_strdup(descr)); tmp->maintainer = _strdup(maint); tmp->deps = _strdup(deps); return tmp; } static void index_register(PkgNodePtr top, char *where, IndexEntryPtr ptr) { PkgNodePtr p, q; for (q = NULL, p = top->kids; p; p = p->next) { if (!strcmp(p->name, where)) { q = p; break; } } if (!p) { /* Add new category */ q = new_pkg_node(where, PLACE); q->desc = fetch_desc(where); q->next = top->kids; top->kids = q; } p = new_pkg_node(ptr->name, PACKAGE); p->desc = ptr->comment; p->data = ptr; p->next = q->kids; q->kids = p; } static int copy_to_sep(char *to, char *from, int sep) { char *tok; tok = strchr(from, sep); if (!tok) { *to = '\0'; return 0; } *tok = '\0'; strcpy(to, from); return tok + 1 - from; } static int readline(FILE *fp, char *buf, int max) { int rv, i = 0; char ch; while ((rv = fread(&ch, 1, 1, fp)) == 1 && ch != '\n' && i < max) buf[i++] = ch; if (i < max) buf[i] = '\0'; return rv; } int index_parse(FILE *fp, char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint, char *cats, char *deps) { char line[1024]; char *cp; int i; i = readline(fp, line, 1024); if (i <= 0) return EOF; cp = line; cp += copy_to_sep(name, cp, '|'); cp += copy_to_sep(pathto, cp, '|'); cp += copy_to_sep(prefix, cp, '|'); cp += copy_to_sep(comment, cp, '|'); cp += copy_to_sep(descr, cp, '|'); cp += copy_to_sep(maint, cp, '|'); cp += copy_to_sep(cats, cp, '|'); (void)copy_to_sep(deps, cp, '|'); /* We're not actually interested in any of the other fields */ return 0; } int index_get(char *fname, PkgNodePtr papa) { int i; FILE *fp; fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "Unable to open index file `%s' for reading.\n", fname); i = -1; } else i = index_read(fp, papa); fclose(fp); return i; } int index_read(FILE *fp, PkgNodePtr papa) { char name[127], pathto[255], prefix[255], comment[255], descr[127], maint[127], cats[511], deps[511]; while (index_parse(fp, name, pathto, prefix, comment, descr, maint, cats, deps) != EOF) { char *cp, *cp2, tmp[511]; IndexEntryPtr idx; idx = new_index(name, pathto, prefix, comment, descr, maint, deps); /* For now, we only add things to menus if they're in categories. Keywords are ignored */ for (cp = strcpy(tmp, cats); (cp2 = strchr(cp, ' ')) != NULL; cp = cp2 + 1) { *cp2 = '\0'; index_register(papa, cp, idx); } index_register(papa, cp, idx); /* Add to special "All" category */ index_register(papa, "All", idx); } return 0; } void index_init(PkgNodePtr top, PkgNodePtr plist) { if (top) { top->next = top->kids = NULL; top->name = "Package Selection"; top->type = PLACE; top->desc = fetch_desc(top->name); top->data = NULL; } if (plist) { plist->next = plist->kids = NULL; plist->name = "Package Targets"; plist->type = PLACE; plist->desc = fetch_desc(plist->name); plist->data = NULL; } } void index_print(PkgNodePtr top, int level) { int i; while (top) { for (i = 0; i < level; i++) putchar('\t'); printf("name [%s]: %s\n", top->type == PLACE ? "place" : "package", top->name); for (i = 0; i < level; i++) putchar('\t'); printf("desc: %s\n", top->desc); if (top->kids) index_print(top->kids, level + 1); top = top->next; } } /* Swap one node for another */ static void swap_nodes(PkgNodePtr a, PkgNodePtr b) { PkgNode tmp; tmp = *a; *a = *b; a->next = tmp.next; tmp.next = b->next; *b = tmp; } /* Use a disgustingly simplistic bubble sort to put our lists in order */ void index_sort(PkgNodePtr top) { PkgNodePtr p, q; /* Sort everything at the top level */ for (p = top->kids; p; p = p->next) { for (q = top->kids; q; q = q->next) { if (q->next && strcmp(q->name, q->next->name) > 0) swap_nodes(q, q->next); } } /* Now sub-sort everything n levels down */ for (p = top->kids; p; p = p->next) { if (p->kids) index_sort(p); } } /* Delete an entry out of the list it's in (only the plist, at present) */ void index_delete(PkgNodePtr n) { if (n->next) { PkgNodePtr p = n->next; *n = *(n->next); safe_free(p); } else /* Kludgy end sentinal */ n->name = NULL; } /* * Search for a given node by name, returning the category in if * tp is non-NULL. */ PkgNodePtr index_search(PkgNodePtr top, char *str, PkgNodePtr *tp) { PkgNodePtr p, sp; for (p = top->kids; p && p->name; p = p->next) { /* Subtract out the All category from searches */ if (!strcmp(p->name, "All")) continue; /* If tp == NULL, we're looking for an exact package match */ if (!tp && !strncmp(p->name, str, strlen(str))) return p; /* If tp, we're looking for both a package and a pointer to the place it's in */ if (tp && !strncmp(p->name, str, strlen(str))) { *tp = top; return p; } /* The usual recursion-out-of-laziness ploy */ if (p->kids) if ((sp = index_search(p, str, tp)) != NULL) return sp; } if (p && !p->name) p = NULL; return p; } int pkg_checked(dialogMenuItem *self) { PkgNodePtr kp = self->data, plist = (PkgNodePtr)self->aux; int i; i = index_search(plist, kp->name, NULL) ? TRUE : FALSE; if (kp->type == PACKAGE && plist) return i || package_exists(kp->name); else return FALSE; } int pkg_fire(dialogMenuItem *self) { int ret; PkgNodePtr sp, kp = self->data, plist = (PkgNodePtr)self->aux; if (!plist) ret = DITEM_FAILURE; else if (kp->type == PACKAGE) { sp = index_search(plist, kp->name, NULL); /* Not already selected? */ if (!sp) { if (!package_exists(kp->name)) { PkgNodePtr np = (PkgNodePtr)safe_malloc(sizeof(PkgNode)); *np = *kp; np->next = plist->kids; plist->kids = np; msgInfo("Added %s to selection list", kp->name); } } - else if (sp) { + else { msgInfo("Removed %s from selection list", kp->name); index_delete(sp); } ret = DITEM_SUCCESS; } else { /* Not a package, must be a directory */ int p, s; p = s = 0; index_menu(kp, plist, &p, &s); ret = DITEM_SUCCESS | DITEM_CONTINUE; } return ret; } void pkg_selected(dialogMenuItem *self, int is_selected) { PkgNodePtr kp = self->data; if (!is_selected || kp->type != PACKAGE) return; msgInfo(kp->desc); } int index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll) { int n, rval, maxname; int curr, max; PkgNodePtr kp; dialogMenuItem *nitems; Boolean hasPackages; WINDOW *w; hasPackages = FALSE; nitems = NULL; w = savescr(); n = maxname = 0; /* Figure out if this menu is full of "leaves" or "branches" */ for (kp = top->kids; kp && kp->name; kp = kp->next) { int len; ++n; if (kp->type == PACKAGE && plist) { hasPackages = TRUE; if ((len = strlen(kp->name)) > maxname) maxname = len; } } if (!n && plist) { msgConfirm("The %s menu is empty.", top->name); restorescr(w); return DITEM_LEAVE_MENU; } while (1) { n = 0; curr = max = 0; kp = top->kids; while (kp && kp->name) { char buf[256]; /* Brutally adjust description to fit in menu */ SAFE_STRCPY(buf, kp->desc); if (strlen(buf) > (_MAX_DESC - maxname)) buf[_MAX_DESC - maxname] = '\0'; nitems = item_add(nitems, kp->name, buf, pkg_checked, pkg_fire, pkg_selected, kp, (int)plist, &curr, &max); ++n; kp = kp->next; } /* NULL delimiter so item_free() knows when to stop later */ nitems = item_add(nitems, NULL, NULL, NULL, NULL, NULL, NULL, 0, &curr, &max); recycle: dialog_clear_norefresh(); if (hasPackages) rval = dialog_checklist(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, -n, nitems, NULL); else /* It's a categories menu */ rval = dialog_menu(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, -n, nitems, NULL, pos, scroll); if (rval == -1 && plist) { static char *cp; PkgNodePtr menu; /* Search */ if ((cp = msgGetInput(cp, "Search by package name. Please enter search string:")) != NULL) { PkgNodePtr p = index_search(top, cp, &menu); if (p) { int pos, scroll; /* These need to be set to point at the found item, actually. Hmmm! */ pos = scroll = 0; index_menu(menu, plist, &pos, &scroll); } else msgConfirm("Search string: %s yielded no hits.", cp); } goto recycle; } items_free(nitems, &curr, &max); restorescr(w); return rval ? DITEM_FAILURE : DITEM_SUCCESS; } } int index_extract(Device *dev, PkgNodePtr top, PkgNodePtr plist) { PkgNodePtr tmp; int status = DITEM_SUCCESS; for (tmp = plist->kids; tmp && tmp->name; tmp = tmp->next) status = index_extract_one(dev, top, tmp, FALSE); return status; } static int index_extract_one(Device *dev, PkgNodePtr top, PkgNodePtr who, Boolean depended) { int status = DITEM_SUCCESS; PkgNodePtr tmp2; IndexEntryPtr id = who->data; if (id && id->deps && strlen(id->deps)) { char t[1024], *cp, *cp2; SAFE_STRCPY(t, id->deps); cp = t; while (cp && DITEM_STATUS(status) == DITEM_SUCCESS) { if ((cp2 = index(cp, ' ')) != NULL) *cp2 = '\0'; if ((tmp2 = index_search(top, cp, NULL)) != NULL) { status = index_extract_one(dev, top, tmp2, TRUE); if (DITEM_STATUS(status) != DITEM_SUCCESS) { if (variable_get(VAR_NO_CONFIRM)) msgNotify("Loading of dependant package %s failed", cp); else msgConfirm("Loading of dependant package %s failed", cp); } if (cp2) cp = cp2 + 1; else cp = NULL; } } } /* Done with the deps? Load the real m'coy */ if (DITEM_STATUS(status) == DITEM_SUCCESS) status = package_extract(dev, who->name, depended); return status; } diff --git a/release/sysinstall/main.c b/release/sysinstall/main.c index 688000062255..d9b08a899b7d 100644 --- a/release/sysinstall/main.c +++ b/release/sysinstall/main.c @@ -1,166 +1,166 @@ /* * The new sysinstall program. * * This is probably the last attempt in the `sysinstall' line, the next * generation being slated for what's essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include static void screech(int sig) { printf("\007Fatal signal %d caught! I'm dead..\n", sig); if (RunningAsInit) pause(); else exit(1); } int main(int argc, char **argv) { int choice, scroll, curr, max; /* Catch fatal signals and complain about them if running as init */ if (getpid() == 1) { signal(SIGBUS, screech); signal(SIGSEGV, screech); } /* We don't work too well when running as non-root anymore */ if (geteuid() != 0) { fprintf(stderr, "Error: This utility should only be run as root.\n"); return 1; } /* Set up whatever things need setting up */ systemInitialize(argc, argv); /* Set default flag and variable values */ installVarDefaults(NULL); if (argc > 1 && !strcmp(argv[1], "-fake")) { variable_set2(VAR_DEBUG, "YES"); Fake = TRUE; msgConfirm("I'll be just faking it from here on out, OK?"); } /* Try to preserve our scroll-back buffer */ if (OnVTY) { for (curr = 0; curr < 25; curr++) putchar('\n'); - /* Move stderr aside */ - if (DebugFD) - dup2(DebugFD, 2); } + /* Move stderr aside */ + if (DebugFD) + dup2(DebugFD, 2); /* Probe for all relevant devices on the system */ deviceGetAll(); /* First, see if we have any arguments to process (and argv[0] counts if it's not "sysinstall") */ if (!RunningAsInit) { int i, start_arg; if (!strstr(argv[0], "sysinstall")) start_arg = 0; else if (Fake) start_arg = 2; else start_arg = 1; for (i = start_arg; i < argc; i++) { if (DITEM_STATUS(dispatchCommand(argv[i])) != DITEM_SUCCESS) systemShutdown(1); } if (argc > start_arg) systemShutdown(0); } else { FILE *fp; char buf[BUFSIZ]; fp = fopen("install.cfg", "r"); if (fp) { msgNotify("Loading pre-configuration file"); while (fgets(buf, sizeof buf, fp)) { if (DITEM_STATUS(dispatchCommand(buf)) != DITEM_SUCCESS) { msgDebug("Command `%s' failed - rest of script aborted.\n", buf); break; } } fclose(fp); } #if defined(LOAD_CONFIG_FILE) else { /* If we have a compiled-in startup config file name on the floppy, look for it and try to load it on startup */ extern char *distWanted; /* Tell mediaSetFloppy() to try floppy now */ distWanted = LOAD_CONFIG_FILE; /* Try to open the floppy drive if we can do that first */ if (DITEM_STATUS(mediaSetFloppy(NULL)) != DITEM_FAILURE && mediaDevice->init(mediaDevice)) { fp = mediaDevice->get(mediaDevice, LOAD_CONFIG_FILE, TRUE); if (fp) { msgNotify("Loading %s pre-configuration file", LOAD_CONFIG_FILE); while (fgets(buf, sizeof buf, fp)) { if (DITEM_STATUS(dispatchCommand(buf)) != DITEM_SUCCESS) { msgDebug("Command `%s' failed - rest of script aborted.\n", buf); break; } } fclose(fp); } mediaDevice->shutdown(mediaDevice); } } #endif } /* Begin user dialog at outer menu */ dialog_clear(); while (1) { choice = scroll = curr = max = 0; dmenuOpen(&MenuInitial, &choice, &scroll, &curr, &max, TRUE); if (getpid() != 1 || !msgYesNo("Are you sure you wish to exit? The system will reboot\n" "(be sure to remove any floppies from the drives).")) break; } /* Say goodnight, Gracie */ systemShutdown(0); return 0; /* We should never get here */ } diff --git a/release/sysinstall/package.c b/release/sysinstall/package.c index 0ae2d50ac2a6..78074d772a97 100644 --- a/release/sysinstall/package.c +++ b/release/sysinstall/package.c @@ -1,201 +1,201 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include #include #include #include /* Like package_extract, but assumes current media device */ int package_add(char *name) { if (!mediaVerify()) return DITEM_FAILURE; return package_extract(mediaDevice, name, FALSE); } Boolean package_exists(char *name) { char fname[FILENAME_MAX]; int status /* = vsystem("pkg_info -e %s", name) */; /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX * packages register themselves and should *really be done with * `pkg_info -e ' except that this it's too slow for an * item check routine.. :-( */ snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); status = access(fname, R_OK); - msgDebug("package check for %s returns %s.\n", name, - status ? "failure" : "success"); + if (isDebug()) + msgDebug("package check for %s returns %s.\n", name, status ? "failure" : "success"); return !status; } /* SIGPIPE handler */ static Boolean sigpipe_caught = FALSE; static void catch_pipe(int sig) { sigpipe_caught = TRUE; } /* Extract a package based on a namespec and a media device */ int package_extract(Device *dev, char *name, Boolean depended) { char path[511]; int ret; FILE *fp; /* Check to make sure it's not already there */ if (package_exists(name)) return DITEM_SUCCESS; /* If necessary, initialize the ldconfig hints */ if (!file_readable("/var/run/ld.so.hints")) vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib"); if (!dev->init(dev)) { msgConfirm("Unable to initialize media type for package extract."); return DITEM_FAILURE; } /* Be initially optimistic */ ret = DITEM_SUCCESS | DITEM_RESTORE; /* Make a couple of paranoid locations for temp files to live if user specified none */ if (!variable_get("PKG_TMPDIR")) { /* Set it to a location with as much space as possible */ variable_set2("PKG_TMPDIR", "/usr/tmp"); } Mkdir(variable_get("PKG_TMPDIR")); if (!index(name, '/')) sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); else sprintf(path, "%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); fp = dev->get(dev, path, TRUE); if (fp) { int i, tot, pfd[2]; pid_t pid; signal(SIGPIPE, catch_pipe); msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); pipe(pfd); pid = fork(); if (!pid) { dup2(pfd[0], 0); close(pfd[0]); dup2(DebugFD, 1); close(2); close(pfd[1]); i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); if (isDebug()) msgDebug("pkg_add returns %d status\n", i); } else { char buf[BUFSIZ]; WINDOW *w = savescr(); struct timeval start, stop; close(pfd[0]); tot = 0; (void)gettimeofday(&start, (struct timezone *)0); while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { int seconds; tot += i; /* Print statistics about how we're doing */ (void) gettimeofday(&stop, (struct timezone *)0); stop.tv_sec = stop.tv_sec - start.tv_sec; stop.tv_usec = stop.tv_usec - start.tv_usec; if (stop.tv_usec < 0) stop.tv_sec--, stop.tv_usec += 1000000; seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); if (!seconds) seconds = 1; msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1024.0); /* Write it out */ if (write(pfd[1], buf, i) != i) { msgInfo("Write failure to pkg_add! Package may be corrupt."); break; } } close(pfd[1]); fclose(fp); if (sigpipe_caught) msgDebug("Caught SIGPIPE while trying to install the %s package.\n", name); else msgInfo("Package %s read successfully - waiting for pkg_add", name); refresh(); i = waitpid(pid, &tot, 0); if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { if (variable_get(VAR_NO_CONFIRM)) msgNotify("Add of package %s aborted due to some error -\n" "Please check the debug screen for more info.", name); else msgConfirm("Add of package %s aborted due to some error -\n" "Please check the debug screen for more info.", name); } else msgNotify("Package %s was added successfully", name); /* Now catch any stragglers */ while (wait3(&tot, WNOHANG, NULL) > 0); sleep(1); restorescr(w); sigpipe_caught = FALSE; } } else { msgDebug("pkg_extract: get returned NULL\n"); dialog_clear_norefresh(); if (variable_get(VAR_NO_CONFIRM)) msgNotify("Unable to fetch package %s from selected media.\n" "No package add will be done.", name); else { msgConfirm("Unable to fetch package %s from selected media.\n" "No package add will be done.", name); } ret = DITEM_FAILURE | DITEM_RESTORE; } return ret; } diff --git a/usr.sbin/sade/main.c b/usr.sbin/sade/main.c index 688000062255..d9b08a899b7d 100644 --- a/usr.sbin/sade/main.c +++ b/usr.sbin/sade/main.c @@ -1,166 +1,166 @@ /* * The new sysinstall program. * * This is probably the last attempt in the `sysinstall' line, the next * generation being slated for what's essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include static void screech(int sig) { printf("\007Fatal signal %d caught! I'm dead..\n", sig); if (RunningAsInit) pause(); else exit(1); } int main(int argc, char **argv) { int choice, scroll, curr, max; /* Catch fatal signals and complain about them if running as init */ if (getpid() == 1) { signal(SIGBUS, screech); signal(SIGSEGV, screech); } /* We don't work too well when running as non-root anymore */ if (geteuid() != 0) { fprintf(stderr, "Error: This utility should only be run as root.\n"); return 1; } /* Set up whatever things need setting up */ systemInitialize(argc, argv); /* Set default flag and variable values */ installVarDefaults(NULL); if (argc > 1 && !strcmp(argv[1], "-fake")) { variable_set2(VAR_DEBUG, "YES"); Fake = TRUE; msgConfirm("I'll be just faking it from here on out, OK?"); } /* Try to preserve our scroll-back buffer */ if (OnVTY) { for (curr = 0; curr < 25; curr++) putchar('\n'); - /* Move stderr aside */ - if (DebugFD) - dup2(DebugFD, 2); } + /* Move stderr aside */ + if (DebugFD) + dup2(DebugFD, 2); /* Probe for all relevant devices on the system */ deviceGetAll(); /* First, see if we have any arguments to process (and argv[0] counts if it's not "sysinstall") */ if (!RunningAsInit) { int i, start_arg; if (!strstr(argv[0], "sysinstall")) start_arg = 0; else if (Fake) start_arg = 2; else start_arg = 1; for (i = start_arg; i < argc; i++) { if (DITEM_STATUS(dispatchCommand(argv[i])) != DITEM_SUCCESS) systemShutdown(1); } if (argc > start_arg) systemShutdown(0); } else { FILE *fp; char buf[BUFSIZ]; fp = fopen("install.cfg", "r"); if (fp) { msgNotify("Loading pre-configuration file"); while (fgets(buf, sizeof buf, fp)) { if (DITEM_STATUS(dispatchCommand(buf)) != DITEM_SUCCESS) { msgDebug("Command `%s' failed - rest of script aborted.\n", buf); break; } } fclose(fp); } #if defined(LOAD_CONFIG_FILE) else { /* If we have a compiled-in startup config file name on the floppy, look for it and try to load it on startup */ extern char *distWanted; /* Tell mediaSetFloppy() to try floppy now */ distWanted = LOAD_CONFIG_FILE; /* Try to open the floppy drive if we can do that first */ if (DITEM_STATUS(mediaSetFloppy(NULL)) != DITEM_FAILURE && mediaDevice->init(mediaDevice)) { fp = mediaDevice->get(mediaDevice, LOAD_CONFIG_FILE, TRUE); if (fp) { msgNotify("Loading %s pre-configuration file", LOAD_CONFIG_FILE); while (fgets(buf, sizeof buf, fp)) { if (DITEM_STATUS(dispatchCommand(buf)) != DITEM_SUCCESS) { msgDebug("Command `%s' failed - rest of script aborted.\n", buf); break; } } fclose(fp); } mediaDevice->shutdown(mediaDevice); } } #endif } /* Begin user dialog at outer menu */ dialog_clear(); while (1) { choice = scroll = curr = max = 0; dmenuOpen(&MenuInitial, &choice, &scroll, &curr, &max, TRUE); if (getpid() != 1 || !msgYesNo("Are you sure you wish to exit? The system will reboot\n" "(be sure to remove any floppies from the drives).")) break; } /* Say goodnight, Gracie */ systemShutdown(0); return 0; /* We should never get here */ } diff --git a/usr.sbin/sysinstall/ftp.c b/usr.sbin/sysinstall/ftp.c index f83dfdae5a97..0cbb53ffc91b 100644 --- a/usr.sbin/sysinstall/ftp.c +++ b/usr.sbin/sysinstall/ftp.c @@ -1,231 +1,231 @@ /* * The new sysinstall program. * * This is probably the last attempt in the `sysinstall' line, the next * generation being slated to essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include #include #include #include #include #include Boolean ftpInitted = FALSE; static FILE *OpenConn; int FtpPort; Boolean mediaInitFTP(Device *dev) { int i, code; char *cp, *rel, *hostname, *dir; char *user, *login_name, password[80]; Device *netdev = (Device *)dev->private; if (ftpInitted) return TRUE; if (isDebug()) msgDebug("Init routine for FTP called.\n"); if (OpenConn) { fclose(OpenConn); OpenConn = NULL; } /* If we can't initialize the network, bag it! */ if (netdev && !netdev->init(netdev)) return FALSE; try: cp = variable_get(VAR_FTP_PATH); if (!cp) { if (DITEM_STATUS(mediaSetFTP(NULL)) == DITEM_FAILURE || (cp = variable_get(VAR_FTP_PATH)) == NULL) { msgConfirm("Unable to get proper FTP path. FTP media not initialized."); if (netdev) netdev->shutdown(netdev); return FALSE; } } hostname = variable_get(VAR_FTP_HOST); dir = variable_get(VAR_FTP_DIR); if (!hostname || !dir) { msgConfirm("Missing FTP host or directory specification. FTP media not initialized,"); if (netdev) netdev->shutdown(netdev); return FALSE; } user = variable_get(VAR_FTP_USER); login_name = (!user || !*user) ? "anonymous" : user; if (variable_get(VAR_FTP_PASS)) SAFE_STRCPY(password, variable_get(VAR_FTP_PASS)); else sprintf(password, "installer@%s", variable_get(VAR_HOSTNAME)); msgNotify("Logging in to %s@%s..", login_name, hostname); if ((OpenConn = ftpLogin(hostname, login_name, password, FtpPort, isDebug(), &code)) == NULL) { - msgConfirm("Couldn't open FTP connection to %s, errcode = %d", hostname, code); + msgConfirm("Couldn't open FTP connection to %s:\n %s.", hostname, ftpErrString(code)); goto punt; } ftpPassive(OpenConn, !strcmp(variable_get(VAR_FTP_STATE), "passive")); ftpBinary(OpenConn); if (dir && *dir != '\0') { if ((i = ftpChdir(OpenConn, dir)) != 0) { if (i == 550) msgConfirm("No such directory ftp://%s/%s\n" "please check your URL and try again.", hostname, dir); else - msgConfirm("FTP chdir to ftp://%s/%s returned error status %d\n", hostname, dir, i); + msgConfirm("FTP chdir to ftp://%s/%s returned error status:\n %s.", hostname, dir, ftpErrString(i)); goto punt; } } /* Give it a shot - can't hurt to try and zoom in if we can, unless the release is set to __RELEASE or "none" which signifies that it's not set */ rel = variable_get(VAR_RELNAME); if (strcmp(rel, "__RELEASE") && strcmp(rel, "none")) i = ftpChdir(OpenConn, rel); else i = 0; if (i) { if (!msgYesNo("Warning: Can't CD to `%s' distribution on this\n" "FTP server. You may need to visit a different server for\n" "the release you're trying to fetch or go to the Options\n" "menu and to set the release name to explicitly match what's\n" "available on %s (or set to \"none\").\n\n" "Would you like to select another FTP server?", rel, hostname)) { variable_unset(VAR_FTP_PATH); if (DITEM_STATUS(mediaSetFTP(NULL)) == DITEM_FAILURE) goto punt; else goto try; } else goto punt; } if (isDebug()) msgDebug("mediaInitFTP was successful (logged in and chdir'd)\n"); ftpInitted = TRUE; return TRUE; punt: if (OpenConn != NULL) { fclose(OpenConn); OpenConn = NULL; } if (netdev) netdev->shutdown(netdev); variable_unset(VAR_FTP_PATH); return FALSE; } FILE * mediaGetFTP(Device *dev, char *file, Boolean probe) { int nretries = 1; FILE *fp; char *try, buf[PATH_MAX]; if (!OpenConn) { msgDebug("No FTP connection open, can't get file %s\n", file); return NULL; } try = file; while ((fp = ftpGet(OpenConn, try, 0)) == NULL) { /* If a hard fail, try to "bounce" the ftp server to clear it */ if (ftpErrno(OpenConn) != 550) { char *cp = variable_get(VAR_FTP_PATH); dev->shutdown(dev); variable_unset(VAR_FTP_PATH); /* If we can't re-initialize, just forget it */ if (!dev->init(dev)) { fclose(OpenConn); OpenConn = NULL; return NULL; } else variable_set2(VAR_FTP_PATH, cp); } else if (probe) return NULL; else { /* Try some alternatives */ switch (nretries++) { case 1: sprintf(buf, "dists/%s", file); try = buf; break; case 2: sprintf(buf, "%s/%s", variable_get(VAR_RELNAME), file); try = buf; break; case 3: sprintf(buf, "%s/dists/%s", variable_get(VAR_RELNAME), file); try = buf; break; case 4: try = file; break; } } } return fp; } void mediaShutdownFTP(Device *dev) { /* Device *netdev = (Device *)dev->private; */ if (!ftpInitted) return; msgDebug("FTP shutdown called. OpenConn = %x\n", OpenConn); if (OpenConn != NULL) { fclose(OpenConn); OpenConn = NULL; } /* if (netdev) netdev->shutdown(netdev); */ ftpInitted = FALSE; } diff --git a/usr.sbin/sysinstall/index.c b/usr.sbin/sysinstall/index.c index 79a035814d3e..736e2575e585 100644 --- a/usr.sbin/sysinstall/index.c +++ b/usr.sbin/sysinstall/index.c @@ -1,587 +1,587 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include "sysinstall.h" /* Macros and magic values */ #define MAX_MENU 12 #define _MAX_DESC 55 static int index_extract_one(Device *dev, PkgNodePtr top, PkgNodePtr who, Boolean depended); /* Smarter strdup */ inline char * _strdup(char *ptr) { return ptr ? strdup(ptr) : NULL; } static char *descrs[] = { "Package Selection", "To mark a package or select a category, move to it and press SPACE.\n" "To unmark a package, press SPACE again. To go to a previous menu,\n" "select the Cancel button. To search for a package by name, press ESC.\n" "To finally extract packages, you should Cancel all the way out of any\n" "submenus and then this top menu. NOTE: The All category selection\n" "creates a very large submenu. If you select it, please be patient.", "Package Targets", "These are the packages you've selected for extraction.\n\n" "If you're sure of these choices, select OK.\n" "If not, select Cancel to go back to the package selection menu.\n", "All", "All available packages in all categories.", "applications", "User application software.", "astro", "Applications related to astronomy.", "archivers", "Utilities for archiving and unarchiving data.", "audio", "Audio utilities - most require a supported sound card.", "benchmarks", "Utilities for measuring system performance.", "benchmarking", "Utilities for measuring system performance.", "cad", "Computer Aided Design utilities.", "chinese", "Ported software for the Chinese market.", "comms", "Communications utilities.", "databases", "Database software.", "devel", "Software development utilities and libraries.", "development", "Software development utilities and libraries.", "documentation", "Document preparation utilities.", "editors", "Common text editors.", "emulation", "Utilities for emulating other OS types.", "emulators", "Utilities for emulating other OS types.", "games", "Various and sundry amusements.", "graphics", "Graphics libraries and utilities.", "japanese", "Ported software for the Japanese market.", "lang", "Computer languages.", "languages", "Computer languages.", "libraries", "Software development libraries.", "mail", "Electronic mail packages and utilities.", "math", "Mathematical computation software.", "mbone", "Applications and utilities for the mbone.", "misc", "Miscellaneous utilities.", "net", "Networking utilities.", "networking", "Networking utilities.", "news", "USENET News support software.", "numeric", "Mathematical computation software.", "orphans", "Packages without a home elsewhere.", "plan9", "Software from the plan9 Operating System.", "print", "Utilities for dealing with printing.", "printing", "Utilities for dealing with printing.", "programming", "Software development utilities and libraries.", "russian", "Ported software for the Russian market.", "security", "System security software.", "shells", "Various shells (tcsh, bash, etc).", "sysutils", "Various system utilities.", "www", "WEB utilities (browers, HTTP servers, etc).", "troff", "TROFF Text formatting utilities.", "utils", "Various user utilities.", "utilities", "Various user utilities.", "vietnamese", "Ported software for the Vietnamese market.", "x11", "X Window System based utilities.", NULL, NULL, }; static char * fetch_desc(char *name) { int i; for (i = 0; descrs[i]; i += 2) { if (!strcmp(descrs[i], name)) return descrs[i + 1]; } return "No description provided"; } static PkgNodePtr new_pkg_node(char *name, node_type type) { PkgNodePtr tmp = safe_malloc(sizeof(PkgNode)); tmp->name = _strdup(name); tmp->type = type; return tmp; } static char * strip(char *buf) { int i; for (i = 0; buf[i]; i++) if (buf[i] == '\t' || buf[i] == '\n') buf[i] = ' '; return buf; } static IndexEntryPtr new_index(char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint, char *deps) { IndexEntryPtr tmp = safe_malloc(sizeof(IndexEntry)); tmp->name = _strdup(name); tmp->path = _strdup(pathto); tmp->prefix = _strdup(prefix); tmp->comment = _strdup(comment); tmp->descrfile = strip(_strdup(descr)); tmp->maintainer = _strdup(maint); tmp->deps = _strdup(deps); return tmp; } static void index_register(PkgNodePtr top, char *where, IndexEntryPtr ptr) { PkgNodePtr p, q; for (q = NULL, p = top->kids; p; p = p->next) { if (!strcmp(p->name, where)) { q = p; break; } } if (!p) { /* Add new category */ q = new_pkg_node(where, PLACE); q->desc = fetch_desc(where); q->next = top->kids; top->kids = q; } p = new_pkg_node(ptr->name, PACKAGE); p->desc = ptr->comment; p->data = ptr; p->next = q->kids; q->kids = p; } static int copy_to_sep(char *to, char *from, int sep) { char *tok; tok = strchr(from, sep); if (!tok) { *to = '\0'; return 0; } *tok = '\0'; strcpy(to, from); return tok + 1 - from; } static int readline(FILE *fp, char *buf, int max) { int rv, i = 0; char ch; while ((rv = fread(&ch, 1, 1, fp)) == 1 && ch != '\n' && i < max) buf[i++] = ch; if (i < max) buf[i] = '\0'; return rv; } int index_parse(FILE *fp, char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint, char *cats, char *deps) { char line[1024]; char *cp; int i; i = readline(fp, line, 1024); if (i <= 0) return EOF; cp = line; cp += copy_to_sep(name, cp, '|'); cp += copy_to_sep(pathto, cp, '|'); cp += copy_to_sep(prefix, cp, '|'); cp += copy_to_sep(comment, cp, '|'); cp += copy_to_sep(descr, cp, '|'); cp += copy_to_sep(maint, cp, '|'); cp += copy_to_sep(cats, cp, '|'); (void)copy_to_sep(deps, cp, '|'); /* We're not actually interested in any of the other fields */ return 0; } int index_get(char *fname, PkgNodePtr papa) { int i; FILE *fp; fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "Unable to open index file `%s' for reading.\n", fname); i = -1; } else i = index_read(fp, papa); fclose(fp); return i; } int index_read(FILE *fp, PkgNodePtr papa) { char name[127], pathto[255], prefix[255], comment[255], descr[127], maint[127], cats[511], deps[511]; while (index_parse(fp, name, pathto, prefix, comment, descr, maint, cats, deps) != EOF) { char *cp, *cp2, tmp[511]; IndexEntryPtr idx; idx = new_index(name, pathto, prefix, comment, descr, maint, deps); /* For now, we only add things to menus if they're in categories. Keywords are ignored */ for (cp = strcpy(tmp, cats); (cp2 = strchr(cp, ' ')) != NULL; cp = cp2 + 1) { *cp2 = '\0'; index_register(papa, cp, idx); } index_register(papa, cp, idx); /* Add to special "All" category */ index_register(papa, "All", idx); } return 0; } void index_init(PkgNodePtr top, PkgNodePtr plist) { if (top) { top->next = top->kids = NULL; top->name = "Package Selection"; top->type = PLACE; top->desc = fetch_desc(top->name); top->data = NULL; } if (plist) { plist->next = plist->kids = NULL; plist->name = "Package Targets"; plist->type = PLACE; plist->desc = fetch_desc(plist->name); plist->data = NULL; } } void index_print(PkgNodePtr top, int level) { int i; while (top) { for (i = 0; i < level; i++) putchar('\t'); printf("name [%s]: %s\n", top->type == PLACE ? "place" : "package", top->name); for (i = 0; i < level; i++) putchar('\t'); printf("desc: %s\n", top->desc); if (top->kids) index_print(top->kids, level + 1); top = top->next; } } /* Swap one node for another */ static void swap_nodes(PkgNodePtr a, PkgNodePtr b) { PkgNode tmp; tmp = *a; *a = *b; a->next = tmp.next; tmp.next = b->next; *b = tmp; } /* Use a disgustingly simplistic bubble sort to put our lists in order */ void index_sort(PkgNodePtr top) { PkgNodePtr p, q; /* Sort everything at the top level */ for (p = top->kids; p; p = p->next) { for (q = top->kids; q; q = q->next) { if (q->next && strcmp(q->name, q->next->name) > 0) swap_nodes(q, q->next); } } /* Now sub-sort everything n levels down */ for (p = top->kids; p; p = p->next) { if (p->kids) index_sort(p); } } /* Delete an entry out of the list it's in (only the plist, at present) */ void index_delete(PkgNodePtr n) { if (n->next) { PkgNodePtr p = n->next; *n = *(n->next); safe_free(p); } else /* Kludgy end sentinal */ n->name = NULL; } /* * Search for a given node by name, returning the category in if * tp is non-NULL. */ PkgNodePtr index_search(PkgNodePtr top, char *str, PkgNodePtr *tp) { PkgNodePtr p, sp; for (p = top->kids; p && p->name; p = p->next) { /* Subtract out the All category from searches */ if (!strcmp(p->name, "All")) continue; /* If tp == NULL, we're looking for an exact package match */ if (!tp && !strncmp(p->name, str, strlen(str))) return p; /* If tp, we're looking for both a package and a pointer to the place it's in */ if (tp && !strncmp(p->name, str, strlen(str))) { *tp = top; return p; } /* The usual recursion-out-of-laziness ploy */ if (p->kids) if ((sp = index_search(p, str, tp)) != NULL) return sp; } if (p && !p->name) p = NULL; return p; } int pkg_checked(dialogMenuItem *self) { PkgNodePtr kp = self->data, plist = (PkgNodePtr)self->aux; int i; i = index_search(plist, kp->name, NULL) ? TRUE : FALSE; if (kp->type == PACKAGE && plist) return i || package_exists(kp->name); else return FALSE; } int pkg_fire(dialogMenuItem *self) { int ret; PkgNodePtr sp, kp = self->data, plist = (PkgNodePtr)self->aux; if (!plist) ret = DITEM_FAILURE; else if (kp->type == PACKAGE) { sp = index_search(plist, kp->name, NULL); /* Not already selected? */ if (!sp) { if (!package_exists(kp->name)) { PkgNodePtr np = (PkgNodePtr)safe_malloc(sizeof(PkgNode)); *np = *kp; np->next = plist->kids; plist->kids = np; msgInfo("Added %s to selection list", kp->name); } } - else if (sp) { + else { msgInfo("Removed %s from selection list", kp->name); index_delete(sp); } ret = DITEM_SUCCESS; } else { /* Not a package, must be a directory */ int p, s; p = s = 0; index_menu(kp, plist, &p, &s); ret = DITEM_SUCCESS | DITEM_CONTINUE; } return ret; } void pkg_selected(dialogMenuItem *self, int is_selected) { PkgNodePtr kp = self->data; if (!is_selected || kp->type != PACKAGE) return; msgInfo(kp->desc); } int index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll) { int n, rval, maxname; int curr, max; PkgNodePtr kp; dialogMenuItem *nitems; Boolean hasPackages; WINDOW *w; hasPackages = FALSE; nitems = NULL; w = savescr(); n = maxname = 0; /* Figure out if this menu is full of "leaves" or "branches" */ for (kp = top->kids; kp && kp->name; kp = kp->next) { int len; ++n; if (kp->type == PACKAGE && plist) { hasPackages = TRUE; if ((len = strlen(kp->name)) > maxname) maxname = len; } } if (!n && plist) { msgConfirm("The %s menu is empty.", top->name); restorescr(w); return DITEM_LEAVE_MENU; } while (1) { n = 0; curr = max = 0; kp = top->kids; while (kp && kp->name) { char buf[256]; /* Brutally adjust description to fit in menu */ SAFE_STRCPY(buf, kp->desc); if (strlen(buf) > (_MAX_DESC - maxname)) buf[_MAX_DESC - maxname] = '\0'; nitems = item_add(nitems, kp->name, buf, pkg_checked, pkg_fire, pkg_selected, kp, (int)plist, &curr, &max); ++n; kp = kp->next; } /* NULL delimiter so item_free() knows when to stop later */ nitems = item_add(nitems, NULL, NULL, NULL, NULL, NULL, NULL, 0, &curr, &max); recycle: dialog_clear_norefresh(); if (hasPackages) rval = dialog_checklist(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, -n, nitems, NULL); else /* It's a categories menu */ rval = dialog_menu(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, -n, nitems, NULL, pos, scroll); if (rval == -1 && plist) { static char *cp; PkgNodePtr menu; /* Search */ if ((cp = msgGetInput(cp, "Search by package name. Please enter search string:")) != NULL) { PkgNodePtr p = index_search(top, cp, &menu); if (p) { int pos, scroll; /* These need to be set to point at the found item, actually. Hmmm! */ pos = scroll = 0; index_menu(menu, plist, &pos, &scroll); } else msgConfirm("Search string: %s yielded no hits.", cp); } goto recycle; } items_free(nitems, &curr, &max); restorescr(w); return rval ? DITEM_FAILURE : DITEM_SUCCESS; } } int index_extract(Device *dev, PkgNodePtr top, PkgNodePtr plist) { PkgNodePtr tmp; int status = DITEM_SUCCESS; for (tmp = plist->kids; tmp && tmp->name; tmp = tmp->next) status = index_extract_one(dev, top, tmp, FALSE); return status; } static int index_extract_one(Device *dev, PkgNodePtr top, PkgNodePtr who, Boolean depended) { int status = DITEM_SUCCESS; PkgNodePtr tmp2; IndexEntryPtr id = who->data; if (id && id->deps && strlen(id->deps)) { char t[1024], *cp, *cp2; SAFE_STRCPY(t, id->deps); cp = t; while (cp && DITEM_STATUS(status) == DITEM_SUCCESS) { if ((cp2 = index(cp, ' ')) != NULL) *cp2 = '\0'; if ((tmp2 = index_search(top, cp, NULL)) != NULL) { status = index_extract_one(dev, top, tmp2, TRUE); if (DITEM_STATUS(status) != DITEM_SUCCESS) { if (variable_get(VAR_NO_CONFIRM)) msgNotify("Loading of dependant package %s failed", cp); else msgConfirm("Loading of dependant package %s failed", cp); } if (cp2) cp = cp2 + 1; else cp = NULL; } } } /* Done with the deps? Load the real m'coy */ if (DITEM_STATUS(status) == DITEM_SUCCESS) status = package_extract(dev, who->name, depended); return status; } diff --git a/usr.sbin/sysinstall/main.c b/usr.sbin/sysinstall/main.c index 688000062255..d9b08a899b7d 100644 --- a/usr.sbin/sysinstall/main.c +++ b/usr.sbin/sysinstall/main.c @@ -1,166 +1,166 @@ /* * The new sysinstall program. * * This is probably the last attempt in the `sysinstall' line, the next * generation being slated for what's essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include static void screech(int sig) { printf("\007Fatal signal %d caught! I'm dead..\n", sig); if (RunningAsInit) pause(); else exit(1); } int main(int argc, char **argv) { int choice, scroll, curr, max; /* Catch fatal signals and complain about them if running as init */ if (getpid() == 1) { signal(SIGBUS, screech); signal(SIGSEGV, screech); } /* We don't work too well when running as non-root anymore */ if (geteuid() != 0) { fprintf(stderr, "Error: This utility should only be run as root.\n"); return 1; } /* Set up whatever things need setting up */ systemInitialize(argc, argv); /* Set default flag and variable values */ installVarDefaults(NULL); if (argc > 1 && !strcmp(argv[1], "-fake")) { variable_set2(VAR_DEBUG, "YES"); Fake = TRUE; msgConfirm("I'll be just faking it from here on out, OK?"); } /* Try to preserve our scroll-back buffer */ if (OnVTY) { for (curr = 0; curr < 25; curr++) putchar('\n'); - /* Move stderr aside */ - if (DebugFD) - dup2(DebugFD, 2); } + /* Move stderr aside */ + if (DebugFD) + dup2(DebugFD, 2); /* Probe for all relevant devices on the system */ deviceGetAll(); /* First, see if we have any arguments to process (and argv[0] counts if it's not "sysinstall") */ if (!RunningAsInit) { int i, start_arg; if (!strstr(argv[0], "sysinstall")) start_arg = 0; else if (Fake) start_arg = 2; else start_arg = 1; for (i = start_arg; i < argc; i++) { if (DITEM_STATUS(dispatchCommand(argv[i])) != DITEM_SUCCESS) systemShutdown(1); } if (argc > start_arg) systemShutdown(0); } else { FILE *fp; char buf[BUFSIZ]; fp = fopen("install.cfg", "r"); if (fp) { msgNotify("Loading pre-configuration file"); while (fgets(buf, sizeof buf, fp)) { if (DITEM_STATUS(dispatchCommand(buf)) != DITEM_SUCCESS) { msgDebug("Command `%s' failed - rest of script aborted.\n", buf); break; } } fclose(fp); } #if defined(LOAD_CONFIG_FILE) else { /* If we have a compiled-in startup config file name on the floppy, look for it and try to load it on startup */ extern char *distWanted; /* Tell mediaSetFloppy() to try floppy now */ distWanted = LOAD_CONFIG_FILE; /* Try to open the floppy drive if we can do that first */ if (DITEM_STATUS(mediaSetFloppy(NULL)) != DITEM_FAILURE && mediaDevice->init(mediaDevice)) { fp = mediaDevice->get(mediaDevice, LOAD_CONFIG_FILE, TRUE); if (fp) { msgNotify("Loading %s pre-configuration file", LOAD_CONFIG_FILE); while (fgets(buf, sizeof buf, fp)) { if (DITEM_STATUS(dispatchCommand(buf)) != DITEM_SUCCESS) { msgDebug("Command `%s' failed - rest of script aborted.\n", buf); break; } } fclose(fp); } mediaDevice->shutdown(mediaDevice); } } #endif } /* Begin user dialog at outer menu */ dialog_clear(); while (1) { choice = scroll = curr = max = 0; dmenuOpen(&MenuInitial, &choice, &scroll, &curr, &max, TRUE); if (getpid() != 1 || !msgYesNo("Are you sure you wish to exit? The system will reboot\n" "(be sure to remove any floppies from the drives).")) break; } /* Say goodnight, Gracie */ systemShutdown(0); return 0; /* We should never get here */ } diff --git a/usr.sbin/sysinstall/package.c b/usr.sbin/sysinstall/package.c index 0ae2d50ac2a6..78074d772a97 100644 --- a/usr.sbin/sysinstall/package.c +++ b/usr.sbin/sysinstall/package.c @@ -1,201 +1,201 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include #include #include #include /* Like package_extract, but assumes current media device */ int package_add(char *name) { if (!mediaVerify()) return DITEM_FAILURE; return package_extract(mediaDevice, name, FALSE); } Boolean package_exists(char *name) { char fname[FILENAME_MAX]; int status /* = vsystem("pkg_info -e %s", name) */; /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX * packages register themselves and should *really be done with * `pkg_info -e ' except that this it's too slow for an * item check routine.. :-( */ snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); status = access(fname, R_OK); - msgDebug("package check for %s returns %s.\n", name, - status ? "failure" : "success"); + if (isDebug()) + msgDebug("package check for %s returns %s.\n", name, status ? "failure" : "success"); return !status; } /* SIGPIPE handler */ static Boolean sigpipe_caught = FALSE; static void catch_pipe(int sig) { sigpipe_caught = TRUE; } /* Extract a package based on a namespec and a media device */ int package_extract(Device *dev, char *name, Boolean depended) { char path[511]; int ret; FILE *fp; /* Check to make sure it's not already there */ if (package_exists(name)) return DITEM_SUCCESS; /* If necessary, initialize the ldconfig hints */ if (!file_readable("/var/run/ld.so.hints")) vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib"); if (!dev->init(dev)) { msgConfirm("Unable to initialize media type for package extract."); return DITEM_FAILURE; } /* Be initially optimistic */ ret = DITEM_SUCCESS | DITEM_RESTORE; /* Make a couple of paranoid locations for temp files to live if user specified none */ if (!variable_get("PKG_TMPDIR")) { /* Set it to a location with as much space as possible */ variable_set2("PKG_TMPDIR", "/usr/tmp"); } Mkdir(variable_get("PKG_TMPDIR")); if (!index(name, '/')) sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); else sprintf(path, "%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); fp = dev->get(dev, path, TRUE); if (fp) { int i, tot, pfd[2]; pid_t pid; signal(SIGPIPE, catch_pipe); msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); pipe(pfd); pid = fork(); if (!pid) { dup2(pfd[0], 0); close(pfd[0]); dup2(DebugFD, 1); close(2); close(pfd[1]); i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); if (isDebug()) msgDebug("pkg_add returns %d status\n", i); } else { char buf[BUFSIZ]; WINDOW *w = savescr(); struct timeval start, stop; close(pfd[0]); tot = 0; (void)gettimeofday(&start, (struct timezone *)0); while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { int seconds; tot += i; /* Print statistics about how we're doing */ (void) gettimeofday(&stop, (struct timezone *)0); stop.tv_sec = stop.tv_sec - start.tv_sec; stop.tv_usec = stop.tv_usec - start.tv_usec; if (stop.tv_usec < 0) stop.tv_sec--, stop.tv_usec += 1000000; seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); if (!seconds) seconds = 1; msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1024.0); /* Write it out */ if (write(pfd[1], buf, i) != i) { msgInfo("Write failure to pkg_add! Package may be corrupt."); break; } } close(pfd[1]); fclose(fp); if (sigpipe_caught) msgDebug("Caught SIGPIPE while trying to install the %s package.\n", name); else msgInfo("Package %s read successfully - waiting for pkg_add", name); refresh(); i = waitpid(pid, &tot, 0); if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { if (variable_get(VAR_NO_CONFIRM)) msgNotify("Add of package %s aborted due to some error -\n" "Please check the debug screen for more info.", name); else msgConfirm("Add of package %s aborted due to some error -\n" "Please check the debug screen for more info.", name); } else msgNotify("Package %s was added successfully", name); /* Now catch any stragglers */ while (wait3(&tot, WNOHANG, NULL) > 0); sleep(1); restorescr(w); sigpipe_caught = FALSE; } } else { msgDebug("pkg_extract: get returned NULL\n"); dialog_clear_norefresh(); if (variable_get(VAR_NO_CONFIRM)) msgNotify("Unable to fetch package %s from selected media.\n" "No package add will be done.", name); else { msgConfirm("Unable to fetch package %s from selected media.\n" "No package add will be done.", name); } ret = DITEM_FAILURE | DITEM_RESTORE; } return ret; }