diff options
23 files changed, 782 insertions, 176 deletions
diff --git a/usr.sbin/pkg_install/README b/usr.sbin/pkg_install/README index dd42917cec0a..dabd52a8a2fd 100644 --- a/usr.sbin/pkg_install/README +++ b/usr.sbin/pkg_install/README @@ -2,4 +2,7 @@ This is the pkg_install suite of tools for doing maintainance of software "packages". More documentation is available in the man pages for each individual command. -This is pkg_install version 0.5. +This code was written by Jordan Hubbard for FreeBSD, snatched and +mildly reshaped by John Kohl in NetBSD and the changes taken back into +FreeBSD again by Jordan. Whee! :-) + diff --git a/usr.sbin/pkg_install/add/add.h b/usr.sbin/pkg_install/add/add.h index 019fc925737f..5bbaa2e9ebdc 100644 --- a/usr.sbin/pkg_install/add/add.h +++ b/usr.sbin/pkg_install/add/add.h @@ -1,4 +1,4 @@ -/* $Id: add.h,v 1.4 1993/09/04 05:06:25 jkh Exp $ */ +/* $Id: add.h,v 1.3 1993/09/05 04:53:47 jkh Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -28,6 +28,7 @@ typedef enum { NORMAL, MASTER, SLAVE } add_mode_t; extern char *Prefix; extern Boolean NoInstall; extern Boolean NoRecord; +extern Boolean Force; extern char *Mode; extern char *Owner; extern char *Group; diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c index d5db041e6a06..6a48ba6d4598 100644 --- a/usr.sbin/pkg_install/add/extract.c +++ b/usr.sbin/pkg_install/add/extract.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: extract.c,v 1.4 1993/09/06 23:26:21 jkh Exp $"; +static const char *rcsid = "$Id: extract.c,v 1.5 1993/09/18 03:38:47 jkh Exp $"; #endif /* @@ -25,11 +25,49 @@ static const char *rcsid = "$Id: extract.c,v 1.4 1993/09/06 23:26:21 jkh Exp $"; #include "lib.h" #include "add.h" + +#define STARTSTRING "tar cf -" +#define TOOBIG(str) ((strlen(str) + 6 + strlen(home) + where_count > maxargs) \ + || (strlen(str) + 6 + strlen(home) + perm_count > maxargs)) + +#define PUSHOUT(todir) /* push out string */ \ + if (strlen(where_args) > sizeof(STARTSTRING)-1) { \ + strcat(where_args, "|tar xpf - -C "); \ + strcat(where_args, todir); \ + if (system(where_args)) \ + barf("can't invoke tar pipeline"); \ + strcpy(where_args, STARTSTRING); \ + where_count = sizeof(STARTSTRING)-1; \ + } \ + if (perm_count) { \ + apply_perms(todir, perm_args); \ + perm_args[0] = 0;\ + perm_count = 0; \ + } + void extract_plist(char *home, Package *pkg) { PackingList p = pkg->head; char *last_file; + char *where_args, *perm_args, *last_chdir; + int maxargs, where_count = 0, perm_count = 0, add_count; + + maxargs = sysconf(_SC_ARG_MAX); + maxargs -= 64; /* some slop for the tar cmd text, + and sh -c */ + where_args = malloc(maxargs); + if (!where_args) + barf("can't get argument list space"); + perm_args = malloc(maxargs); + if (!perm_args) + barf("can't get argument list space"); + + strcpy(where_args, STARTSTRING); + where_count = sizeof(STARTSTRING)-1; + perm_args[0] = 0; + + last_chdir = 0; /* Reset the world */ Owner = NULL; @@ -58,15 +96,49 @@ extract_plist(char *home, Package *pkg) /* first try to rename it into place */ sprintf(try, "%s/%s", Directory, p->name); - if (rename(p->name, try) == FAIL) - copy_hierarchy(Directory, p->name, TRUE); - apply_perms(Directory, p->name); + if (rename(p->name, try) == 0) { + /* try to add to list of perms to be changed, + and run in bulk. */ + add_count = snprintf(&perm_args[perm_count], + maxargs - perm_count, + "%s ", p->name); + if (add_count > maxargs - perm_count) + barf("oops, miscounted strings!"); + perm_count += add_count; + if (p->name[0] == '/') { + PUSHOUT(Directory); + } + } else { + /* rename failed, try copying with a big tar command */ + if (p->name[0] == '/' || + TOOBIG(p->name) || + last_chdir != Directory) { + PUSHOUT(last_chdir); + last_chdir = Directory; + } + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s", p->name); + if (add_count > maxargs - where_count) + barf("oops, miscounted strings!"); + where_count += add_count; + add_count = snprintf(&perm_args[perm_count], + maxargs - perm_count, + "%s ", p->name); + if (add_count > maxargs - perm_count) + barf("oops, miscounted strings!"); + perm_count += add_count; + if (p->name[0] == '/') { + PUSHOUT(Directory); + } + } } break; case PLIST_CWD: if (Verbose) printf("extract: CWD to %s\n", p->name); + PUSHOUT(Directory); if (strcmp(p->name, ".")) { if (!Fake && make_hierarchy(p->name) == FAIL) barf("Unable make directory '%s'.", p->name); @@ -78,6 +150,7 @@ extract_plist(char *home, Package *pkg) case PLIST_CMD: format_cmd(cmd, p->name, Directory, last_file); + PUSHOUT(Directory); if (Verbose) printf("extract: execute '%s'\n", cmd); if (!Fake && system(cmd)) @@ -85,14 +158,17 @@ extract_plist(char *home, Package *pkg) break; case PLIST_CHMOD: + PUSHOUT(Directory); Mode = p->name; break; case PLIST_CHOWN: + PUSHOUT(Directory); Owner = p->name; break; case PLIST_CHGRP: + PUSHOUT(Directory); Group = p->name; break; @@ -105,4 +181,5 @@ extract_plist(char *home, Package *pkg) } p = p->next; } + PUSHOUT(Directory); } diff --git a/usr.sbin/pkg_install/add/futil.c b/usr.sbin/pkg_install/add/futil.c index 423f69694427..3bda0b449480 100644 --- a/usr.sbin/pkg_install/add/futil.c +++ b/usr.sbin/pkg_install/add/futil.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: futil.c,v 1.4 1993/09/04 05:06:27 jkh Exp $"; +static const char *rcsid = "$Id: futil.c,v 1.2 1993/09/03 23:00:34 jkh Exp $"; #endif /* @@ -62,25 +62,33 @@ make_hierarchy(char *dir) /* Using permission defaults, apply them as necessary */ void -apply_perms(char *dir, char *file) +apply_perms(char *dir, char *arg) { - char fname[FILENAME_MAX]; + char *cd_to; - if (!dir || *file == '/') /* absolute path? */ - strcpy(fname, file); + if (!dir || *arg == '/') /* absolute path? */ + cd_to = "/"; else - sprintf(fname, "%s/%s", dir, file); + cd_to = dir; + if (Mode) - if (vsystem("chmod -R %s %s", Mode, fname)) - whinge("Couldn't change mode of '%s' to '%s'.", - fname, Mode); - if (Owner) - if (vsystem("chown -R %s %s", Owner, fname)) + if (vsystem("cd %s && chmod -R %s %s", cd_to, Mode, arg)) + whinge("Couldn't change modes of '%s' to '%s'.", + arg, Mode); + if (Owner && Group) { + if (vsystem("cd %s && chown -R %s.%s %s", cd_to, Owner, Group, arg)) + whinge("Couldn't change owner/group of '%s' to '%s.%s'.", + arg, Owner, Group); + return; + } + if (Owner) { + if (vsystem("cd %s && chown -R %s %s", cd_to, Owner, arg)) whinge("Couldn't change owner of '%s' to '%s'.", - fname, Owner); - if (Group) - if (vsystem("chgrp -R %s %s", Group, fname)) + arg, Owner); + return; + } else if (Group) + if (vsystem("cd %s && chgrp -R %s %s", cd_to, Group, arg)) whinge("Couldn't change group of '%s' to '%s'.", - fname, Group); + arg, Group); } diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c index 710fd7021a29..341b700b46eb 100644 --- a/usr.sbin/pkg_install/add/main.c +++ b/usr.sbin/pkg_install/add/main.c @@ -1,5 +1,5 @@ #ifndef lint -static char *rcsid = "$Id: main.c,v 1.3 1993/09/05 04:53:49 jkh Exp $"; +static char *rcsid = "$Id: main.c,v 1.4 1993/09/14 19:53:01 jkh Exp $"; #endif /* @@ -26,11 +26,12 @@ static char *rcsid = "$Id: main.c,v 1.3 1993/09/05 04:53:49 jkh Exp $"; #include "lib.h" #include "add.h" -static char Options[] = "hvIRnp:SMt:"; +static char Options[] = "hvIRfnp:SMt:"; char *Prefix = NULL; Boolean NoInstall = FALSE; Boolean NoRecord = FALSE; +Boolean Force = FALSE; char *Mode = NULL; char *Owner = NULL; @@ -66,6 +67,10 @@ main(int argc, char **argv) NoRecord = TRUE; break; + case 'f': + Force = TRUE; + break; + case 'n': Fake = TRUE; Verbose = TRUE; diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c index 684a8187068b..f5f5f07ca9c3 100644 --- a/usr.sbin/pkg_install/add/perform.c +++ b/usr.sbin/pkg_install/add/perform.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: perform.c,v 1.11 1994/10/14 05:43:41 jkh Exp $"; +static const char *rcsid = "$Id: perform.c,v 1.12 1994/11/17 10:53:21 jkh Exp $"; #endif /* @@ -26,6 +26,7 @@ static const char *rcsid = "$Id: perform.c,v 1.11 1994/10/14 05:43:41 jkh Exp $" #include "add.h" #include <signal.h> +#include <sys/wait.h> static int pkg_do(char *); static int sanity_check(char *); @@ -131,14 +132,40 @@ pkg_do(char *pkg) setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : NULL, 1); PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous"; + /* Protect against old packages with bogus @name fields */ + sprintf(LogDir, "%s/%s", LOG_DIR, basename_of(PkgName)); + if (isdir(LogDir)) { + whinge("Package `%s' already recorded as installed.\n", PkgName); + code = 1; + goto success; /* close enough for government work */ + } + for (p = Plist.head; p ; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Checking dependency on package list `%s'\n", p->name); + if (!Fake && vsystem("pkg_info -e %s", p->name)) { + whinge("Package `%s' depends on missing package `%s'%s.", PkgName, + p->name, Force ? " (proceeding anyway)" : ""); + if (!Force) + code++; + } + } + if (code != 0) + goto success; /* close enough for government work */ + if (fexists(REQUIRE_FNAME)) { vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ if (Verbose) printf("Running requirements file first for %s..\n", PkgName); if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, PkgName)) { - whinge("Package %s fails requirements - not installed.", - pkg_fullname); - return 1; + whinge("Package %s fails requirements %s", + pkg_fullname, + Force ? "installing anyway" : "- not installed."); + if (!Force) { + code = 1; + goto success; /* close enough for government work */ + } } } if (!NoInstall && fexists(INSTALL_FNAME)) { @@ -147,15 +174,65 @@ pkg_do(char *pkg) printf("Running install with PRE-INSTALL for %s..\n", PkgName); if (!Fake && vsystem("./%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) { whinge("Install script returned error status."); - goto fail; + code = 1; + goto success; /* nothing to uninstall yet */ } } extract_plist(home, &Plist); + if (!NoInstall && fexists(MTREE_FNAME)) { + if (Verbose) + printf("Running mtree for %s..\n", PkgName); + p = find_plist(&Plist, PLIST_CWD); + if (Verbose) + printf("mtree -u -f %s -d -e -p %s\n", MTREE_FNAME, + p ? p->name : "/"); + if (!Fake) { + pid_t chpid; + int rval, status; + chpid = fork(); + if (chpid == 0) { + execl("/usr/sbin/mtree", "mtree", "-u", "-f", MTREE_FNAME, + "-d", "-e", "-p", p ? p->name : "/"); + perror("cannot execute mtree"); + exit(3); + } + if (chpid == (pid_t) -1) { + warn("Cannot fork mtree"); + code = 1; + goto fail; + } + if (waitpid(chpid, &status, 0) == -1) { + warn("Cannot wait for mtree"); + code = 1; + goto fail; + } + if (!WIFEXITED(status)) { + whinge("Strange exit from mtree: %x", status); + code = 1; + goto fail; + } +#ifdef DEBUG + whinge("mtree exits %d\n", WEXITSTATUS(status)); +#endif + switch (WEXITSTATUS(status)) { + case 0: + break; /* normal */ + case 2: + whinge("\nWARNING: Mtree attempted some work which may not have completed.\n\tExamine the above output.\n\t(most likely it changed directory permissions)\n"); + break; + default: + whinge("Error status %d from mtree.", WEXITSTATUS(status)); + code = 1; + goto fail; + } + } + } if (!NoInstall && fexists(INSTALL_FNAME)) { if (Verbose) printf("Running install with POST-INSTALL for %s..\n", PkgName); if (!Fake && vsystem("./%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) { whinge("Install script returned error status."); + code = 1; goto fail; } } @@ -163,6 +240,7 @@ pkg_do(char *pkg) char contents[FILENAME_MAX]; FILE *cfile; + umask(022); if (getuid() != 0) whinge("Not running as root - trying to record install anyway."); if (!PkgName) { @@ -198,15 +276,50 @@ pkg_do(char *pkg) fclose(cfile); copy_file(".", DESC_FNAME, LogDir); copy_file(".", COMMENT_FNAME, LogDir); + if (fexists(DISPLAY_FNAME)) + copy_file(".", DISPLAY_FNAME, LogDir); + for (p = Plist.head; p ; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Attempting to record dependency on package `%s'\n", + p->name); + sprintf(contents, "%s/%s/%s", LOG_DIR, basename_of(p->name), + REQUIRED_BY_FNAME); + cfile = fopen(contents, "a"); + if (!cfile) { + whinge("Can't open dependency file '%s'!\n\tDependency registration incomplete.", + contents); + continue; + } + fprintf(cfile, "%s\n", basename_of(PkgName)); + if (fclose(cfile) == EOF) + warn("Cannot properly close file %s", contents); + } if (Verbose) printf("Package %s registered in %s\n", PkgName, LogDir); } + + if (p = find_plist(&Plist, PLIST_DISPLAY)) { + FILE *fp; + char buf[BUFSIZ]; + fp = fopen(p->name, "r"); + if (fp) { + putc('\n', stdout); + while (fgets(buf, sizeof(buf), fp)) + fputs(buf, stdout); + putc('\n', stdout); + (void) fclose(fp); + } else + warn("Cannot open display file `%s'.", p->name); + } + goto success; fail: - /* Nuke the whole (installed) show */ + /* Nuke the whole (installed) show, XXX but don't clean directories */ if (!Fake) - delete_package(FALSE, &Plist); + delete_package(FALSE, FALSE, &Plist); success: /* delete the packing list contents */ @@ -240,7 +353,7 @@ cleanup(int signo) printf("Signal %d received, cleaning up..\n", signo); if (Plist.head) { if (!Fake) - delete_package(FALSE, &Plist); + delete_package(FALSE, FALSE, &Plist); free_plist(&Plist); } if (!Fake && LogDir[0]) diff --git a/usr.sbin/pkg_install/create/create.h b/usr.sbin/pkg_install/create/create.h index d45c177c5c46..e0ee4ccacefa 100644 --- a/usr.sbin/pkg_install/create/create.h +++ b/usr.sbin/pkg_install/create/create.h @@ -1,4 +1,4 @@ -/* $Id: create.h,v 1.4 1993/09/12 20:45:28 jkh Exp $ */ +/* $Id: create.h,v 1.5 1994/05/19 18:27:38 alm Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -26,12 +26,14 @@ extern char *Prefix; extern char *Comment; extern char *Desc; +extern char *Display; extern char *Install; extern char *DeInstall; extern char *Contents; extern char *Require; extern char *PlayPen; extern char *ExcludeFrom; +extern char *Mtree; extern int Dereference; void check_list(char *, Package *); diff --git a/usr.sbin/pkg_install/create/main.c b/usr.sbin/pkg_install/create/main.c index e7805ca46e83..623d7d117a6d 100644 --- a/usr.sbin/pkg_install/create/main.c +++ b/usr.sbin/pkg_install/create/main.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: main.c,v 1.6 1994/04/16 21:50:53 jkh Exp $"; +static const char *rcsid = "$Id: main.c,v 1.7 1994/05/19 18:27:40 alm Exp $"; #endif /* @@ -16,17 +16,19 @@ static const char *rcsid = "$Id: main.c,v 1.6 1994/04/16 21:50:53 jkh Exp $"; #include "lib.h" #include "create.h" -static char Options[] = "YNhvf:p:c:d:i:k:r:t:X:"; +static char Options[] = "YNhvf:p:c:d:i:k:r:t:X:D:m:"; char *Prefix = NULL; char *Comment = NULL; char *Desc = NULL; +char *Display = NULL; char *Install = NULL; char *DeInstall = NULL; char *Contents = NULL; char *Require = NULL; char *PlayPen = NULL; char *ExcludeFrom = NULL; +char *Mtree = NULL; int Dereference = 0; int @@ -91,6 +93,14 @@ main(int argc, char **argv) Dereference = 1; break; + case 'D': + Display = optarg; + break; + + case 'm': + Mtree = optarg; + break; + case '?': default: usage(prog_name, NULL); @@ -140,11 +150,15 @@ usage(const char *name, const char *fmt, ...) fprintf(stderr, "-f file get list of files from file (- for stdin)\n"); fprintf(stderr, "-h follow symbolic links\n"); fprintf(stderr, "-i script install script\n"); - fprintf(stderr, "-p arg install prefix will be arg\n"); fprintf(stderr, "-k script de-install script\n"); + fprintf(stderr, "-D file install notice\n"); + fprintf(stderr, "-m file mtree spec for directories\n"); + fprintf(stderr, "-p prefix install prefix will be arg\n"); fprintf(stderr, "-r script pre/post requirements script\n"); fprintf(stderr, "-t temp use temp as template for mktemp()\n"); fprintf(stderr, "-X file exclude files listed in file\n"); fprintf(stderr, "-v verbose\n"); + fprintf(stderr, "-Y assume `yes' answer to all questions\n"); + fprintf(stderr, "-N assume `no' answer to all questions\n"); exit(1); } diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c index 36d6d5f20265..6d15ef8e3864 100644 --- a/usr.sbin/pkg_install/create/perform.c +++ b/usr.sbin/pkg_install/create/perform.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: perform.c,v 1.12 1994/10/14 05:55:46 jkh Exp $"; +static const char *rcsid = "$Id: perform.c,v 1.13 1994/11/17 10:54:11 jkh Exp $"; #endif /* @@ -84,6 +84,8 @@ pkg_perform(char **pkgs) /* Make first "real contents" pass over it */ check_list(home, &plist); + (void) umask(022); /* make sure gen'ed directories, files don't have + group or other write bits. */ copy_plist(home, &plist); mark_plist(&plist); @@ -111,6 +113,18 @@ pkg_perform(char **pkgs) add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, REQUIRE_FNAME); } + if (Display) { + copy_file(home, Display, DISPLAY_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DISPLAY_FNAME); + add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME); + } + if (Mtree) { + copy_file(home, Mtree, MTREE_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, MTREE_FNAME); + add_plist(&plist, PLIST_MTREE, MTREE_FNAME); + } /* Run through the list again, picking up extra "local" items */ check_list(".", &plist); diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c index 0d877795e5e8..f50bd8fb0926 100644 --- a/usr.sbin/pkg_install/create/pl.c +++ b/usr.sbin/pkg_install/create/pl.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: pl.c,v 1.4 1994/08/29 16:31:38 adam Exp $"; +static const char *rcsid = "$Id: pl.c,v 1.5 1994/11/17 10:35:04 jkh Exp $"; #endif /* @@ -24,6 +24,7 @@ static const char *rcsid = "$Id: pl.c,v 1.4 1994/08/29 16:31:38 adam Exp $"; #include "lib.h" #include "create.h" +#include <errno.h> /* Check a list for files that require preconversion */ void @@ -59,6 +60,35 @@ check_list(char *home, Package *pkg) } } +static int +trylink(const char *from, const char *to) +{ + if (link(from, to) == 0) + return 0; + if (errno == ENOENT) { + /* try making the container directory */ + char *cp = strrchr(to, '/'); + if (cp) + vsystem("mkdir -p %.*s", cp - to, + to); + return link(from, to); + } + return -1; +} + +#define STARTSTRING "tar cf -" +#define TOOBIG(str) strlen(str) + 6 + strlen(home) + where_count > maxargs +#define PUSHOUT() /* push out string */ \ + if (where_count > sizeof(STARTSTRING)-1) { \ + strcat(where_args, "|tar xpf -"); \ + if (system(where_args)) \ + barf("can't invoke tar pipeline"); \ + memset(where_args, 0, maxargs); \ + last_chdir = NULL; \ + strcpy(where_args, STARTSTRING); \ + where_count = sizeof(STARTSTRING)-1; \ + } + /* * Copy unmarked files in packing list to playpen - marked files * have already been copied in an earlier pass through the list. @@ -68,7 +98,30 @@ copy_plist(char *home, Package *plist) { PackingList p = plist->head; char *where = home; - char *there = NULL; + char *there = NULL, *mythere; + char *where_args, *last_chdir, *root = "/"; + int maxargs, where_count = 0, add_count; + struct stat stb; + dev_t curdir; + + maxargs = sysconf(_SC_ARG_MAX); + maxargs -= 64; /* some slop for the tar cmd text, + and sh -c */ + where_args = malloc(maxargs); + if (!where_args) + barf("can't get argument list space"); + + memset(where_args, 0, maxargs); + strcpy(where_args, STARTSTRING); + where_count = sizeof(STARTSTRING)-1; + last_chdir = 0; + + if (stat(".", &stb) == 0) + curdir = stb.st_dev; + else + curdir = (dev_t) -1; /* It's ok if this is a valid dev_t; + this is just a hint for an + optimization. */ while (p) { if (p->type == PLIST_CWD) @@ -80,16 +133,84 @@ copy_plist(char *home, Package *plist) else if (p->type == PLIST_FILE && !p->marked) { char fn[FILENAME_MAX]; + /* First, look for it in the "home" dir */ sprintf(fn, "%s/%s", home, p->name); - if (fexists(fn)) - copy_hierarchy(home, p->name, FALSE); + if (fexists(fn)) { + if (lstat(fn, &stb) == 0 && stb.st_dev == curdir && + S_ISREG(stb.st_mode)) { + /* if we can link it to the playpen, that avoids a copy + and saves time. */ + if (p->name[0] != '/') { + /* don't link abspn stuff--it doesn't come from + local dir! */ + if (trylink(fn, p->name) == 0) { + p = p->next; + continue; + } + } + } + if (TOOBIG(fn)) { + PUSHOUT(); + } + if (p->name[0] == '/') { + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s %s", + last_chdir == root ? "" : "-C /", + p->name); + last_chdir = root; + } else { + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s%s %s", + last_chdir == home ? "" : "-C ", + last_chdir == home ? "" : home, + p->name); + last_chdir = home; + } + if (add_count > maxargs - where_count) + barf("oops, miscounted strings!"); + where_count += add_count; + } /* * Otherwise, try along the actual extraction path.. */ - else - copy_hierarchy(there ? there : where, p->name, FALSE); + else { + if (p->name[0] == '/') + mythere = root; + else mythere = there; + sprintf(fn, "%s/%s", mythere ? mythere : where, p->name); + if (lstat(fn, &stb) == 0 && stb.st_dev == curdir && + S_ISREG(stb.st_mode)) { + /* if we can link it to the playpen, that avoids a copy + and saves time. */ + if (trylink(fn, p->name) == 0) { + p = p->next; + continue; + } + } + if (TOOBIG(p->name)) { + PUSHOUT(); + } + if (last_chdir == (mythere ? mythere : where)) + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s", p->name); + else + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " -C %s %s", + mythere ? mythere : where, + p->name); + if (add_count > maxargs - where_count) + barf("oops, miscounted strings!"); + where_count += add_count; + last_chdir = (mythere ? mythere : where); + } } p = p->next; } + PUSHOUT(); + free(where_args); } diff --git a/usr.sbin/pkg_install/delete/delete.h b/usr.sbin/pkg_install/delete/delete.h index 2828cdf3d327..e618d182611c 100644 --- a/usr.sbin/pkg_install/delete/delete.h +++ b/usr.sbin/pkg_install/delete/delete.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: delete.h,v 1.1.1.1 1993/08/26 01:19:54 jkh Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -25,6 +25,8 @@ extern char *Prefix; extern Boolean NoDeInstall; +extern Boolean CleanDirs; +extern Boolean Force; extern char *Directory; extern char *PkgName; diff --git a/usr.sbin/pkg_install/delete/main.c b/usr.sbin/pkg_install/delete/main.c index a66edfd5967d..c59f94bfc30b 100644 --- a/usr.sbin/pkg_install/delete/main.c +++ b/usr.sbin/pkg_install/delete/main.c @@ -1,5 +1,5 @@ #ifndef lint -static char *rcsid = "$Id: main.c,v 1.5 1993/09/04 05:06:38 jkh Exp $"; +static char *rcsid = "$Id: main.c,v 1.2 1993/09/03 23:01:00 jkh Exp $"; #endif /* @@ -26,15 +26,17 @@ static char *rcsid = "$Id: main.c,v 1.5 1993/09/04 05:06:38 jkh Exp $"; #include "lib.h" #include "delete.h" -static char Options[] = "hvDnp:"; +static char Options[] = "hvDdnfp:"; char *Prefix = NULL; Boolean NoDeInstall = FALSE; +Boolean CleanDirs = FALSE; +Boolean Force = FALSE; int main(int argc, char **argv) { - int ch, err; + int ch, error; char **pkgs, **start; char *prog_name = argv[0]; @@ -45,6 +47,10 @@ main(int argc, char **argv) Verbose = TRUE; break; + case 'f': + Force = TRUE; + break; + case 'p': Prefix = optarg; break; @@ -53,6 +59,10 @@ main(int argc, char **argv) NoDeInstall = TRUE; break; + case 'd': + CleanDirs = TRUE; + break; + case 'n': Fake = TRUE; Verbose = TRUE; @@ -77,10 +87,12 @@ main(int argc, char **argv) if (pkgs == start) usage(prog_name, "Missing package name(s)"); *pkgs = NULL; - if ((err = pkg_perform(start)) != NULL) { + if (!Fake && getuid() != 0) + errx(1, "You must be root to delete packages."); + if ((error = pkg_perform(start)) != NULL) { if (Verbose) - fprintf(stderr, "%d package deletion(s) failed.\n", err); - return err; + fprintf(stderr, "%d package deletion(s) failed.\n", error); + return error; } else return 0; @@ -102,6 +114,9 @@ usage(const char *name, const char *fmt, ...) fprintf(stderr, "Where args are one or more of:\n\n"); fprintf(stderr, "-v verbose\n"); fprintf(stderr, "-p arg override prefix with arg\n"); + fprintf(stderr, "-d delete empty directories when deinstalling\n"); + fprintf(stderr, "-f force delete even if dependencies exist\n"); + fprintf(stderr, " or deinstall/requirement checks fail\n"); fprintf(stderr, "-D don't execute pkg de-install script, if any\n"); fprintf(stderr, "-n don't actually de-install, just show steps\n"); exit(1); diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c index 0b94b2c5c87b..9986ee15d497 100644 --- a/usr.sbin/pkg_install/delete/perform.c +++ b/usr.sbin/pkg_install/delete/perform.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: perform.c,v 1.4 1994/05/25 18:00:02 asami Exp $"; +static const char *rcsid = "$Id: perform.c,v 1.5 1994/09/29 13:19:39 jkh Exp $"; #endif /* @@ -27,6 +27,7 @@ static const char *rcsid = "$Id: perform.c,v 1.4 1994/05/25 18:00:02 asami Exp $ static int pkg_do(char *); static void sanity_check(char *); +static void undepend(PackingList, char *); static char LogDir[FILENAME_MAX]; @@ -65,6 +66,20 @@ pkg_do(char *pkg) whinge("Unable to change directory to %s! Deinstall failed.", LogDir); return 1; } + if (!isemptyfile(REQUIRED_BY_FNAME)) { + char buf[512]; + whinge("Package `%s' is required by these other packages", pkg); + whinge("and may not be deinstalled%s:", Force ? " (but I'll delete it anyway)" : "" ); + cfile = fopen(REQUIRED_BY_FNAME, "r"); + if (cfile) { + while (fgets(buf, sizeof(buf), cfile)) + fprintf(stderr, "%s", buf); + fclose(cfile); + } else + whinge("cannot open requirements file `%s'", REQUIRED_BY_FNAME); + if (!Force) + return 1; + } sanity_check(LogDir); cfile = fopen(CONTENTS_FNAME, "r"); if (!cfile) { @@ -83,8 +98,10 @@ pkg_do(char *pkg) printf("Executing 'require' script.\n"); vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ if (vsystem("./%s %s DEINSTALL", REQUIRE_FNAME, pkg)) { - whinge("Package %s fails requirements - not deleted.", pkg); - return 1; + whinge("Package %s fails requirements %s", pkg, + Force ? "." : "- not deleted."); + if (!Force) + return 1; } } if (!NoDeInstall && fexists(DEINSTALL_FNAME)) { @@ -94,17 +111,27 @@ pkg_do(char *pkg) vsystem("chmod +x %s", DEINSTALL_FNAME); /* make sure */ if (vsystem("./%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) { whinge("De-Install script returned error status."); - return 1; + if (!Force) + return 1; } } } if (chdir(home) == FAIL) barf("Toto! This doesn't look like Kansas anymore!"); - if (!Fake && delete_package(FALSE, &Plist) != FAIL && + if (!Fake && delete_package(FALSE, CleanDirs, &Plist) != FAIL && vsystem("%s -r %s", REMOVE_CMD, LogDir)) { whinge("Couldn't remove log entry in %s, de-install failed.", LogDir); return 1; } + for (p = Plist.head; p ; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Attempting to remove dependency on package `%s'\n", + p->name); + if (!Fake) + undepend(p, pkg); + } return 0; } @@ -120,3 +147,56 @@ cleanup(int sig) { /* Nothing to do */ } + +static void +undepend(PackingList p, char *pkgname) +{ + char fname[FILENAME_MAX], ftmp[FILENAME_MAX]; + char fbuf[FILENAME_MAX]; + FILE *fp, *fpwr; + int s; + + sprintf(fname, "%s/%s/%s", LOG_DIR, p->name, REQUIRED_BY_FNAME); + fp = fopen(fname, "r"); + if (fp == NULL) { + whinge("Couldn't open dependency file `%s'", fname); + return; + } + sprintf(ftmp, "%s.XXXXXX", fname); + s = mkstemp(ftmp); + if (s == -1) { + fclose(fp); + whinge("Couldn't open temp file `%s'", ftmp); + return; + } + fpwr = fdopen(s, "w"); + if (fpwr == NULL) { + close(s); + fclose(fp); + whinge("Couldn't fdopen temp file `%s'", ftmp); + remove(ftmp); + return; + } + while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { + if (fbuf[strlen(fbuf)-1] == '\n') + fbuf[strlen(fbuf)-1] = '\0'; + if (strcmp(fbuf, pkgname)) /* no match */ + fputs(fbuf, fpwr), putc('\n', fpwr); + } + (void) fclose(fp); + if (fchmod(s, 0644) == FAIL) { + whinge("Error changing permission of temp file `%s'", ftmp); + fclose(fpwr); + remove(ftmp); + return; + } + if (fclose(fpwr) == EOF) { + whinge("Error closing temp file `%s'", ftmp); + remove(ftmp); + return; + } + if (rename(ftmp, fname) == -1) + warn("Error renaming `%s' to `%s'", ftmp, fname); + remove(ftmp); /* just in case */ + return; +} diff --git a/usr.sbin/pkg_install/info/info.h b/usr.sbin/pkg_install/info/info.h index b978bd495bd3..6feb73e69671 100644 --- a/usr.sbin/pkg_install/info/info.h +++ b/usr.sbin/pkg_install/info/info.h @@ -1,4 +1,4 @@ -/* $Id: info.h,v 1.4 1993/09/04 05:06:40 jkh Exp $ */ +/* $Id: info.h,v 1.5 1993/09/08 01:46:56 jkh Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -23,15 +23,18 @@ #ifndef _INST_INFO_H_INCLUDE #define _INST_INFO_H_INCLUDE -#define SHOW_COMMENT 0x1 -#define SHOW_DESC 0x2 -#define SHOW_PLIST 0x4 -#define SHOW_INSTALL 0x8 -#define SHOW_DEINSTALL 0x10 -#define SHOW_REQUIRE 0x20 -#define SHOW_PREFIX 0x40 -#define SHOW_INDEX 0x80 -#define SHOW_FILES 0x100 +#define SHOW_COMMENT 0x0001 +#define SHOW_DESC 0x0002 +#define SHOW_PLIST 0x0004 +#define SHOW_INSTALL 0x0008 +#define SHOW_DEINSTALL 0x0010 +#define SHOW_REQUIRE 0x0020 +#define SHOW_PREFIX 0x0040 +#define SHOW_INDEX 0x0080 +#define SHOW_FILES 0x0100 +#define SHOW_DISPLAY 0x0200 +#define SHOW_REQBY 0x0400 +#define SHOW_MTREE 0x0800 extern int Flags; extern Boolean AllInstalled; diff --git a/usr.sbin/pkg_install/info/main.c b/usr.sbin/pkg_install/info/main.c index 6132fab26262..ce8449e32943 100644 --- a/usr.sbin/pkg_install/info/main.c +++ b/usr.sbin/pkg_install/info/main.c @@ -1,5 +1,5 @@ #ifndef lint -static char *rcsid = "$Id: main.c,v 1.6 1994/05/25 06:28:14 jkh Exp $"; +static char *rcsid = "$Id: main.c,v 1.7 1994/06/01 05:15:00 asami Exp $"; #endif /* @@ -26,7 +26,7 @@ static char *rcsid = "$Id: main.c,v 1.6 1994/05/25 06:28:14 jkh Exp $"; #include "lib.h" #include "info.h" -static char Options[] = "acde:fikrpLqIvhl:"; +static char Options[] = "acdDe:fikrRpLqImvhl:"; int Flags = 0; Boolean AllInstalled = FALSE; @@ -53,7 +53,7 @@ main(int argc, char **argv) Verbose = TRUE; /* Reasonable definition of 'everything' */ Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL | - SHOW_DEINSTALL | SHOW_REQUIRE; + SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE; break; case 'I': @@ -72,6 +72,10 @@ main(int argc, char **argv) Flags |= SHOW_DESC; break; + case 'D': + Flags |= SHOW_DISPLAY; + break; + case 'f': Flags |= SHOW_PLIST; break; @@ -88,10 +92,18 @@ main(int argc, char **argv) Flags |= SHOW_REQUIRE; break; + case 'R': + Flags |= SHOW_REQBY; + break; + case 'L': Flags |= SHOW_FILES; break; + case 'm': + Flags |= SHOW_MTREE; + break; + case 'l': InfoPrefix = optarg; break; @@ -120,7 +132,7 @@ main(int argc, char **argv) /* Set some reasonable defaults */ if (!Flags) - Flags = SHOW_COMMENT | SHOW_DESC; + Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY; /* Get all the remaining package names, if any */ while (*argv) @@ -151,15 +163,19 @@ usage(const char *name, const char *fmt, ...) fprintf(stderr, "-I print 'index' of packages\n"); fprintf(stderr, "-c print `one line comment'\n"); fprintf(stderr, "-d print description\n"); + fprintf(stderr, "-D print install notice\n"); fprintf(stderr, "-f show packing list\n"); fprintf(stderr, "-i show install script\n"); fprintf(stderr, "-k show deinstall script\n"); fprintf(stderr, "-r show requirements script\n"); + fprintf(stderr, "-R show packages depending on this package\n"); fprintf(stderr, "-p show prefix\n"); fprintf(stderr, "-l <str> Prefix each info catagory with <str>\n"); + fprintf(stderr, "-L show intalled files\n"); + fprintf(stderr, "-q minimal output (``quiet'' mode)\n"); fprintf(stderr, "-v show all information\n"); fprintf(stderr, "-t temp use temp as template for mktemp()\n"); fprintf(stderr, "-e pkg returns 0 if pkg is installed, 1 otherwise\n"); - fprintf(stderr, "\n[no args = -c -d]\n"); + fprintf(stderr, "\n[no args = -c -d -R]\n"); exit(1); } diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c index b537f172526f..a28f2a0f9fd7 100644 --- a/usr.sbin/pkg_install/info/perform.c +++ b/usr.sbin/pkg_install/info/perform.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: perform.c,v 1.8 1994/10/14 05:55:57 jkh Exp $"; +static const char *rcsid = "$Id: perform.c,v 1.9 1994/10/14 05:57:49 jkh Exp $"; #endif /* @@ -60,7 +60,9 @@ pkg_perform(char **pkgs) } else ++err_cnt; - } + } else if (CheckPkg) + return 1; /* no dir -> not installed! */ + } for (i = 0; pkgs[i]; i++) err_cnt += pkg_do(pkgs[i]); @@ -143,14 +145,20 @@ pkg_do(char *pkg) printf("%sInformation for %s:\n\n", InfoPrefix, pkg); if (Flags & SHOW_COMMENT) show_file("Comment:\n", COMMENT_FNAME); + if ((Flags & SHOW_REQBY) && !isemptyfile(REQUIRED_BY_FNAME)) + show_file("Required by:\n", REQUIRED_BY_FNAME); if (Flags & SHOW_DESC) show_file("Description:\n", DESC_FNAME); + if ((Flags & SHOW_DISPLAY) && fexists(DISPLAY_FNAME)) + show_file("Install notice:\n", DISPLAY_FNAME); if (Flags & SHOW_PLIST) show_plist("Packing list:\n", &plist, (plist_t)-1); if ((Flags & SHOW_INSTALL) && fexists(INSTALL_FNAME)) show_file("Install script:\n", INSTALL_FNAME); if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME)) show_file("De-Install script:\n", DEINSTALL_FNAME); + if ((Flags & SHOW_MTREE) && fexists(MTREE_FNAME)) + show_file("mtree file:\n", MTREE_FNAME); if (Flags & SHOW_PREFIX) show_plist("Prefix(s):\n", &plist, PLIST_CWD); if (Flags & SHOW_FILES) diff --git a/usr.sbin/pkg_install/info/pkg_info.1 b/usr.sbin/pkg_install/info/pkg_info.1 index 1f28c17bc322..df996ceca048 100644 --- a/usr.sbin/pkg_install/info/pkg_info.1 +++ b/usr.sbin/pkg_install/info/pkg_info.1 @@ -16,108 +16,119 @@ .\" .\" @(#)pkg_info.1 .\" -.TH pkg_info 1 "July 18, 1993" "" "FreeBSD" - -.SH NAME -pkg_info - a utility for getting information on software package distributions. -.SH SYNOPSIS -.na -.B pkg_info -.RB [options] -.RB "pkg-file|pkg-name\ [.. pkg-file|pkg-name]" - -.SH DESCRIPTION +.Dd November 25, 1994 +.Dt pkg_info 1 +.Os NetBSD 1.0 +.Sh NAME +.Nm pkg_info +.Nd a utility for displaying information on software packages. +.Sh SYNOPSIS +.Nm pkg_info +.Op Fl cdDikrRpLqImv +.Op Fl e Ar package +.Op Fl l Ar prefix +.Ar pkg-name ... +.Nm pkg_info +.Fl a +.Op Ar flags +.Sh DESCRIPTION The -.B pkg_info +.Nm command is used to dump out information for packages, either packed up in files or already installed on the system with the -.B pkg_create +.Xr pkg_create 8 command. - -.SH OPTIONS -.TP +.Sh OPTIONS The following command line options are supported. -.TP -.B \-a +.Bl -tag -width indent +.It Ar pkg-name ... +The named packages are described. Names may either be installed package +names or pathnames to package distribution files. +.It Fl a Show all currently installed packages. -.TP -.B \-v +.It Fl v Turns on verbose output. -.TP -.B \-p +.It Fl p Show the installation prefix for each package. -.TP -.B \-q -Be "quiet" in emitting report headers and such, just dump the +.It Fl q +Be ``quiet'' in emitting report headers and such, just dump the raw info (basically, assume a non-human reading). -.TP -.B \-c +.It Fl c Show the comment (one liner) field for each package. -.TP -.B \-d +.It Fl d Show the long description field for each package. -.TP -.B \-f +.It Fl D +Show the install-message file for each package. +.It Fl f Show the packing list instructions for each package. -.TP -.B \-i +.It Fl i Show the install script (if any) for each package. -.TP -.B \-k +.It Fl k Show the de-install script (if any) for each package. -.TP -.B \-r +.It Fl r Show the requirements script (if any) for each package. -.TP -.B \-L +.It Fl m +Show the mtree file (if any) for each package. +.It Fl L Show the files within each package. This is different from just viewing the packing list, since full pathnames for everything are generated. -.TP -.BI "\-e\ " pkg-name +.It Fl e Ar pkg-name If the package identified by -.I pkg-name +.Ar pkg-name is currently installed, return 0, otherwise return 1. This option allows you to easily test for the presence of another (perhaps prerequisite) package from a script. -.TP -.BI "\-l\ " str +.It Fl l Ar str Prefix each information catagory header (see -.I \-q) +.Fl q ) shown with -.I str. +.Ar str . This is primarily of use to front-end programs who want to request a lot of different information fields at once for a package, but don't necessary want the output intermingled in such a way that they can't organize it. This lets you add a special token to the start of each field. -.TP -.BI "\-t\ " template +.Fl t Ar template Use -.I template -as the input to mktemp(3). By default, this is the string -.B /tmp/instmp.XXXXXX -, but it may be necessary to override it in the situation where +.Ar template +as the input to +.Xr mktemp 3 +when creating a ``staging area.'' +By default, this is the string +.Pa /tmp/instmp.XXXXXX , +but it may be necessary to override it in the situation where space in your -.B /tmp +.Pa /tmp directory is limited. Be sure to leave some number of `X' characters -for mktemp(3) to fill in with a unique ID. +for +.Xr mktemp 3 +to fill in with a unique ID. +.Bd -filled -offset indent -compact Note: This should really not be necessary with pkg_info, since very little information is extracted from each package -and one would have to have a very small /tmp indeed to overflow -it. -.PP -.SH "TECHNICAL DETAILS" -Package info is either extracted from files supplied on the +and one would have to have a very small +.Pa /tmp +indeed to overflow it. +.Ed +.Sh TECHNICAL DETAILS +Package info is either extracted from package files named on the command line, or from already installed package information -in /var/db/pkg/<pkg-name>. -.SH BUGS +in +.Pa /var/db/pkg/<pkg-name> . +.Sh SEE ALSO +.Xr mktemp 3 , +.Xr mtree 8 , +.Xr pkg_add 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 . +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for NetBSD +.El +.Sh BUGS Sure to be some. -.SH "SEE ALSO" -.BR pkg_add "(" 1 ")," -.BR pkg_create "(" 1 ")," -.BR pkg_delete "(" 1 ")," -.SH AUTHORS -Jordan Hubbard - diff --git a/usr.sbin/pkg_install/info/show.c b/usr.sbin/pkg_install/info/show.c index 3000ccf8f6d4..93efd0e94722 100644 --- a/usr.sbin/pkg_install/info/show.c +++ b/usr.sbin/pkg_install/info/show.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: show.c,v 1.4 1993/09/04 05:06:44 jkh Exp $"; +static const char *rcsid = "$Id: show.c,v 1.3 1993/09/08 01:46:59 jkh Exp $"; #endif /* @@ -74,6 +74,10 @@ show_plist(char *title, Package *plist, plist_t type) printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", p->name); break; + case PLIST_SRC: + printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name); + break; + case PLIST_CMD: printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name); break; @@ -101,10 +105,32 @@ show_plist(char *title, Package *plist, plist_t type) ign = TRUE; break; + case PLIST_IGNORE_INST: + printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" : + "\tIgnore next file installation directive (doesn't belong)\n"); + ign = TRUE; + break; + case PLIST_NAME: printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name); break; + case PLIST_DISPLAY: + printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name); + break; + + case PLIST_PKGDEP: + printf(Quiet ? "@pkgdep %s\n" : "\tPackage depends on: %s\n", p->name); + break; + + case PLIST_MTREE: + printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name); + break; + + case PLIST_DIR_RM: + printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name); + break; + default: barf("Unknown command type %d (%s)\n", p->type, p->name); break; diff --git a/usr.sbin/pkg_install/lib/exec.c b/usr.sbin/pkg_install/lib/exec.c index 5232dd2b4dcf..dd6b184fffd8 100644 --- a/usr.sbin/pkg_install/lib/exec.c +++ b/usr.sbin/pkg_install/lib/exec.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: exec.c,v 1.4 1993/09/04 05:06:47 jkh Exp $"; +static const char *rcsid = "$Id: exec.c,v 1.2 1993/09/03 23:01:12 jkh Exp $"; #endif /* @@ -33,16 +33,28 @@ int vsystem(const char *fmt, ...) { va_list args; - char cmd[FILENAME_MAX * 2]; /* reasonable default for what I do */ - int ret; + char *cmd; + int ret, maxargs; + + maxargs = sysconf(_SC_ARG_MAX); + maxargs -= 32; /* some slop for the sh -c */ + cmd = malloc(maxargs); + if (!cmd) { + whinge("vsystem can't alloc arg space"); + return 1; + } va_start(args, fmt); - vsprintf(cmd, fmt, args); + if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) { + whinge("vsystem args are too long"); + return 1; + } #ifdef DEBUG printf("Executing %s\n", cmd); #endif ret = system(cmd); va_end(args); + free(cmd); return ret; } diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c index 698fd8754382..e2c26688a0f5 100644 --- a/usr.sbin/pkg_install/lib/file.c +++ b/usr.sbin/pkg_install/lib/file.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: file.c,v 1.4 1993/09/06 23:28:42 jkh Exp $"; +static const char *rcsid = "$Id: file.c,v 1.5 1993/09/18 03:39:48 jkh Exp $"; #endif /* @@ -39,8 +39,7 @@ isdir(char *fname) { struct stat sb; - if (stat(fname, &sb) != FAIL && - (sb.st_mode & S_IFDIR)) + if (stat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode)) return TRUE; else return FALSE; @@ -48,7 +47,7 @@ isdir(char *fname) /* Check to see if file is a dir, and is empty */ Boolean -isempty(char *fname) +isemptydir(char *fname) { if (isdir(fname)) { DIR *dirp; @@ -69,6 +68,19 @@ isempty(char *fname) return FALSE; } +/* Check to see if file is a file and is empty. If nonexistent or not + a file, say "it's empty", otherwise return TRUE if zero sized. */ +Boolean +isemptyfile(char *fname) +{ + struct stat sb; + if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) { + if (sb.st_size != 0) + return FALSE; + } + return TRUE; +} + char * get_file_contents(char *fname) { @@ -84,7 +96,7 @@ get_file_contents(char *fname) if (fd == FAIL) barf("Unable to open '%s' for reading.", fname); if (read(fd, contents, sb.st_size) != sb.st_size) - barf("Short read on '%s' - did not get %d bytes.", fname, sb.st_size); + barf("Short read on '%s' - did not get %qd bytes.", fname, sb.st_size); close(fd); contents[sb.st_size] = '\0'; return contents; diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h index b9f6a15efec2..abcfed741169 100644 --- a/usr.sbin/pkg_install/lib/lib.h +++ b/usr.sbin/pkg_install/lib/lib.h @@ -1,4 +1,4 @@ -/* $Id: lib.h,v 1.10 1994/10/04 16:07:50 jkh Exp $ */ +/* $Id: lib.h,v 1.11 1994/11/17 10:51:46 jkh Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -66,6 +66,9 @@ #define INSTALL_FNAME "+INSTALL" #define DEINSTALL_FNAME "+DEINSTALL" #define REQUIRE_FNAME "+REQUIRE" +#define REQUIRED_BY_FNAME "+REQUIRED_BY" +#define DISPLAY_FNAME "+DISPLAY" +#define MTREE_FNAME "+MTREE_DIRS" #define CMD_CHAR '@' /* prefix for extended PLIST cmd */ @@ -75,7 +78,8 @@ enum _plist_t { PLIST_FILE, PLIST_CWD, PLIST_CMD, PLIST_CHMOD, PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, - PLIST_IGNORE, PLIST_NAME, PLIST_UNEXEC, PLIST_SRC + PLIST_IGNORE, PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY, + PLIST_PKGDEP, PLIST_MTREE, PLIST_DIR_RM, PLIST_IGNORE_INST }; typedef enum _plist_t plist_t; @@ -119,7 +123,7 @@ char *get_file_contents(char *); void write_file(char *, char *); void copy_file(char *, char *, char *); void copy_hierarchy(char *, char *, Boolean); -int delete_hierarchy(char *, Boolean); +int delete_hierarchy(char *, Boolean, Boolean); int unpack(char *, char *); void format_cmd(char *, char *, char *, char *); @@ -142,7 +146,7 @@ void add_plist_top(Package *, plist_t, char *); void write_plist(Package *, FILE *); void read_plist(Package *, FILE *); int plist_cmd(char *, char **); -int delete_package(Boolean, Package *); +int delete_package(Boolean, Boolean, Package *); /* For all */ void usage(const char *, const char *, ...); diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c index 577ae5ee8b9d..282f3d04e25b 100644 --- a/usr.sbin/pkg_install/lib/plist.c +++ b/usr.sbin/pkg_install/lib/plist.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: plist.c,v 1.8 1994/08/28 14:15:30 jkh Exp $"; +static const char *rcsid = "$Id: plist.c,v 1.9 1994/09/29 13:19:43 jkh Exp $"; #endif /* @@ -198,8 +198,18 @@ plist_cmd(char *s, char **arg) return PLIST_COMMENT; else if (!strcmp(cmd, "ignore")) return PLIST_IGNORE; + else if (!strcmp(cmd, "ignore_inst")) + return PLIST_IGNORE_INST; else if (!strcmp(cmd, "name")) return PLIST_NAME; + else if (!strcmp(cmd, "display")) + return PLIST_DISPLAY; + else if (!strcmp(cmd, "pkgdep")) + return PLIST_PKGDEP; + else if (!strcmp(cmd, "mtree")) + return PLIST_MTREE; + else if (!strcmp(cmd, "dirrm")) + return PLIST_DIR_RM; else return FAIL; } @@ -280,6 +290,7 @@ write_plist(Package *pkg, FILE *fp) break; case PLIST_IGNORE: + case PLIST_IGNORE_INST: /* a one-time non-ignored file */ fprintf(fp, "%cignore\n", CMD_CHAR); break; @@ -287,6 +298,22 @@ write_plist(Package *pkg, FILE *fp) fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name); break; + case PLIST_DISPLAY: + fprintf(fp, "%cdisplay %s\n", CMD_CHAR, plist->name); + break; + + case PLIST_PKGDEP: + fprintf(fp, "%cpkgdep %s\n", CMD_CHAR, plist->name); + break; + + case PLIST_MTREE: + fprintf(fp, "%cmtree %s\n", CMD_CHAR, plist->name); + break; + + case PLIST_DIR_RM: + fprintf(fp, "%cdirrm %s\n", CMD_CHAR, plist->name); + break; + default: barf("Unknown command type %d (%s)\n", plist->type, plist->name); break; @@ -297,7 +324,7 @@ write_plist(Package *pkg, FILE *fp) /* Delete the results of a package installation, not the packaging itself */ int -delete_package(Boolean ign_err, Package *pkg) +delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) { PackingList p = pkg->head; char *Where = ".", *last_file = ""; @@ -322,14 +349,16 @@ delete_package(Boolean ign_err, Package *pkg) } else if (p->type == PLIST_IGNORE) p = p->next; - else if (p->type == PLIST_FILE) { + else if (p->type == PLIST_FILE || p->type == PLIST_DIR_RM) { char full_name[FILENAME_MAX]; sprintf(full_name, "%s/%s", Where, p->name); if (Verbose) - printf("Delete: %s\n", full_name); + printf("Delete%s: %s\n", + p->type == PLIST_FILE ? "" : " directory", full_name); - if (!Fake && delete_hierarchy(full_name, ign_err)) { + if (!Fake && delete_hierarchy(full_name, ign_err, + p->type == PLIST_DIR_RM ? FALSE : nukedirs)) { whinge("Unable to completely remove file '%s'", full_name); fail = FAIL; } @@ -340,26 +369,44 @@ delete_package(Boolean ign_err, Package *pkg) return fail; } +#ifdef DEBUG +#define RMDIR(dir) vsystem("%s %s", RMDIR_CMD, dir) +#define REMOVE(dir,ie) vsystem("%s %s%s", REMOVE_CMD, (ie ? "-f " : ""), dir) +#else +#define RMDIR rmdir +#define REMOVE(file,ie) remove(file) +#endif + /* Selectively delete a hierarchy */ int -delete_hierarchy(char *dir, Boolean ign_err) +delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) { char *cp1, *cp2; cp1 = cp2 = dir; - if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir)) - return 1; + if (nukedirs) { + if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir)) + return 1; + } else if (isdir(dir)) { + if (RMDIR(dir)) + return 1; + } else { + if (REMOVE(dir, ign_err)) + return 1; + } + + if (!nukedirs) + return 0; while (cp2) { if ((cp2 = rindex(cp1, '/')) != NULL) *cp2 = '\0'; - if (!isempty(dir)) + if (!isemptydir(dir)) return 0; - if (vsystem("%s %s", RMDIR_CMD, dir) && ign_err) + if (RMDIR(dir) && ign_err) return 1; - /* Put it back */ + /* back up the pathname one component */ if (cp2) { - *cp2 = '/'; - cp1 = cp2 - 1; + cp1 = dir; } } return 0; diff --git a/usr.sbin/pkg_install/tkpkg b/usr.sbin/pkg_install/tkpkg index c4c9273be241..5a3e500ae776 100755 --- a/usr.sbin/pkg_install/tkpkg +++ b/usr.sbin/pkg_install/tkpkg @@ -1,7 +1,10 @@ #!/usr/local/bin/wish -f -#$Id: pkg,v 1.1 1993/09/04 17:06:09 jkh Exp $ +#$Id: tkpkg,v 1.1 1994/01/06 08:16:20 jkh Exp $ +# +#$Log: tkpkg,v $ +# Revision 1.1 1994/01/06 08:16:20 jkh +# Cleaning house. # -#$Log: pkg,v $ # Revision 1.1 1993/09/04 17:06:09 jkh # Added Rich's wish front-end. # @@ -41,7 +44,7 @@ text .f.t -width 80 -height 20 -yscrollcommand ".f.s set" -relief sunken # instructions and show the package description when the user clicks # on a package. # -.f.t insert end "Double click on a package above to see it's +.f.t insert end "Double click on a package above to see its complete description here." scrollbar .f.s -relief sunken -command ".f.t yview" pack append .f .f.s {right filly} .f.t {left expand fill} @@ -64,7 +67,7 @@ button .menu.installed -text "What is Installed?" \ button .menu.available -text "What can I install?" \ -command "list_pkgs \"pkg_info -I -c [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}] |tr ' ' ' '\"" button .menu.cont -text "Contents?" \ - -command "global pkgname; apply_to_pkg \"pkg_info -d -v |tr -d ''\"" + -command "apply_to_pkg \"pkg_info -d -v\"" button .menu.quit -text "Quit" -command "destroy ." button .menu.help -text "Help" -command "do_help" @@ -81,7 +84,7 @@ pack append .menu \ #------------------------------------------------------- proc list_pkgs {s} { set line "" - set f [eval "open {| csh -c \"$s\" } r"] + set f [eval "open {| sh -c \"$s\" } r"] .frame.list delete 0 end while {[gets $f line] > 0} { .frame.list insert end $line @@ -91,7 +94,7 @@ proc list_pkgs {s} { # display the list of available packages set archives [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}] -if {$pkgname == ""} { +if {$archives == ""} { .frame.list delete 0 end .frame.list insert end "Warning: no compressed tar archives files found." } else { @@ -122,25 +125,34 @@ proc do_help {{w .help}} { wm iconname $w "Help" button $w.ok -text OK -command "destroy $w" message $w.t -relief raised -bd 2 \ - -text "You can install, deinstall and list info on the available packages. To select a package and see it's complete description, press mouse button 1 over the package name. To install a selected package, press the Install button. To exit, press the \"Quit\" button." + -text "You can install, deinstall and list info on the available packages. To select a package and see its complete description, press mouse button 1 over the package name. To install a selected package, press the Install button. To exit, press the \"Quit\" button." pack append $w $w.ok {bottom fillx} $w.t {expand fill} } #------------------------------------------------------- # Apply a command to a package. #------------------------------------------------------- proc apply_to_pkg {s} { + apply_to_pkg_err $s "" +} +#------------------------------------------------------- +# Apply a command to a package, with error stream redirection instructions. +#------------------------------------------------------- +proc apply_to_pkg_err {s errredir} { global pkgname .f.t delete 0.0 end if {$pkgname == ""} { .f.t insert end "You must double click on a package name first!" } else { + apply_to_pkg_int "$s $pkgname" "2>&1" + } +} +proc apply_to_pkg_int {s errredir} { .f.t delete 0.0 end - .f.t insert end "Running: $s $pkgname\n" - set f [eval "open {| $s $pkgname} r"] + .f.t insert end "Running: $s\n" + set f [eval "open {| sh -c \"$s $errredir\" } r"] while {![eof $f]} { .f.t insert end [read $f 64] } - } } #------------------------------------------------------- # Invoke an arbitrary command. |