diff options
author | Marco S Hyman <marc@cvs.openbsd.org> | 1998-09-07 22:30:18 +0000 |
---|---|---|
committer | Marco S Hyman <marc@cvs.openbsd.org> | 1998-09-07 22:30:18 +0000 |
commit | b7191a530a228038c0867ad6aedd90f5b534d1e9 (patch) | |
tree | dff11f7b0f8e66c2c0a6b6dbf273127ef93423cd /usr.sbin/pkg_install/add | |
parent | d772ee662c59d0c57ee6ec091bcc1b5d284fb641 (diff) |
updated pkg_* tools. Merged in many changes/improvements from NetBSD.
New features include md5 hash so pkg_delete won't remove files that have
changed and the ability to define conflicting packages, e.g. you can't
install both mh and nmh. The ports tree will have to be updated to take
advantage of this.
Let me know of any problems, real or imagined :-)
Diffstat (limited to 'usr.sbin/pkg_install/add')
-rw-r--r-- | usr.sbin/pkg_install/add/add.h | 3 | ||||
-rw-r--r-- | usr.sbin/pkg_install/add/extract.c | 128 | ||||
-rw-r--r-- | usr.sbin/pkg_install/add/futil.c | 18 | ||||
-rw-r--r-- | usr.sbin/pkg_install/add/main.c | 43 | ||||
-rw-r--r-- | usr.sbin/pkg_install/add/perform.c | 227 | ||||
-rw-r--r-- | usr.sbin/pkg_install/add/pkg_add.1 | 189 |
6 files changed, 366 insertions, 242 deletions
diff --git a/usr.sbin/pkg_install/add/add.h b/usr.sbin/pkg_install/add/add.h index 1475e474de9..90c1b947f18 100644 --- a/usr.sbin/pkg_install/add/add.h +++ b/usr.sbin/pkg_install/add/add.h @@ -1,4 +1,5 @@ -/* $OpenBSD: add.h,v 1.1 1996/06/04 07:56:02 niklas Exp $ */ +/* $OpenBSD: add.h,v 1.2 1998/09/07 22:30:13 marc Exp $ */ +/* from FreeBSD Id: add.h,v 1.8 1997/02/22 16:09:15 peter Exp */ /* * FreeBSD install - a package for the installation and maintainance diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c index a769b490165..7e330a860a8 100644 --- a/usr.sbin/pkg_install/add/extract.c +++ b/usr.sbin/pkg_install/add/extract.c @@ -1,7 +1,7 @@ -/* $OpenBSD: extract.c,v 1.5 1998/06/23 23:17:16 millert Exp $ */ +/* $OpenBSD: extract.c,v 1.6 1998/09/07 22:30:13 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: extract.c,v 1.5 1998/06/23 23:17:16 millert Exp $"; +static const char *rcsid = "$OpenBSD: extract.c,v 1.6 1998/09/07 22:30:13 marc Exp $"; #endif /* @@ -24,20 +24,22 @@ static const char *rcsid = "$OpenBSD: extract.c,v 1.5 1998/06/23 23:17:16 miller * */ +#include <err.h> #include "lib.h" #include "add.h" -#define STARTSTRING "tar cf -" -#define TOOBIG(str) ((strlen(str) + 6 + strlen(home) + where_count > maxargs) \ +#define STARTSTRING "tar cf - " +#define TOOBIG(str) ((strlen(str) + 22 + 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 "); \ + if (where_count > sizeof(STARTSTRING)-1) { \ + strcat(where_args, "|tar xf - -C "); \ strcat(where_args, todir); \ if (system(where_args)) \ - barf("can't invoke tar pipeline"); \ + cleanup(0), errx(2, "can not invoke %lu byte tar pipeline: %s", \ + (u_long)strlen(where_args), where_args); \ strcpy(where_args, STARTSTRING); \ where_count = sizeof(STARTSTRING)-1; \ } \ @@ -47,6 +49,32 @@ static const char *rcsid = "$OpenBSD: extract.c,v 1.5 1998/06/23 23:17:16 miller perm_count = 0; \ } +static void +rollback(char *name, char *home, PackingList start, PackingList stop) +{ + PackingList q; + char try[FILENAME_MAX], bup[FILENAME_MAX], *dir; + + dir = home; + for (q = start; q != stop; q = q->next) { + if (q->type == PLIST_FILE) { + snprintf(try, FILENAME_MAX, "%s/%s", dir, q->name); + if (make_preserve_name(bup, FILENAME_MAX, name, try) && fexists(bup)) { + (void)chflags(try, 0); + (void)unlink(try); + if (rename(bup, try)) + warnx("rollback: unable to rename %s back to %s", bup, try); + } + } + else if (q->type == PLIST_CWD) { + if (strcmp(q->name, ".")) + dir = q->name; + else + dir = home; + } + } +} + void extract_plist(char *home, Package *pkg) { @@ -54,22 +82,22 @@ extract_plist(char *home, Package *pkg) char *last_file; char *where_args, *perm_args, *last_chdir; int maxargs, where_count = 0, perm_count = 0, add_count; + Boolean preserve; - maxargs = sysconf(_SC_ARG_MAX); - maxargs -= 64; /* some slop for the tar cmd text, - and sh -c */ - where_args = malloc(maxargs); + maxargs = sysconf(_SC_ARG_MAX) / 2; /* Just use half the argument space */ + where_args = alloca(maxargs); if (!where_args) - barf("can't get argument list space"); - perm_args = malloc(maxargs); + cleanup(0), errx(2, "can't get argument list space"); + perm_args = alloca(maxargs); if (!perm_args) - barf("can't get argument list space"); + cleanup(0), errx(2, "can't get argument list space"); strcpy(where_args, STARTSTRING); where_count = sizeof(STARTSTRING)-1; perm_args[0] = 0; last_chdir = 0; + preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; /* Reset the world */ Owner = NULL; @@ -96,43 +124,56 @@ extract_plist(char *home, Package *pkg) if (!Fake) { char try[FILENAME_MAX]; + if (strrchr(p->name,'\'')) + cleanup(0), errx(2, "Bogus filename \"%s\"", p->name); + /* first try to rename it into place */ - sprintf(try, "%s/%s", Directory, p->name); + snprintf(try, FILENAME_MAX, "%s/%s", Directory, p->name); + if (fexists(try)) { + (void)chflags(try, 0); /* XXX hack - if truly immutable, rename fails */ + if (preserve && PkgName) { + char pf[FILENAME_MAX]; + + if (make_preserve_name(pf, FILENAME_MAX, PkgName, try)) { + if (rename(try, pf)) { + warnx( + "unable to back up %s to %s, aborting pkg_add", + try, pf); + rollback(PkgName, home, pkg->head, p); + return; + } + } + } + } 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] == '/') { + /* try to add to list of perms to be changed and run in bulk. */ + if (p->name[0] == '/' || TOOBIG(p->name)) { PUSHOUT(Directory); } - } else { + add_count = snprintf(&perm_args[perm_count], maxargs - perm_count, "'%s' ", p->name); + if (add_count > maxargs - perm_count) + cleanup(0), errx(2, "oops, miscounted strings!"); + perm_count += add_count; + } + else { /* rename failed, try copying with a big tar command */ - if (p->name[0] == '/' || - TOOBIG(p->name) || - last_chdir != Directory) { + if (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!"); + else if (p->name[0] == '/' || TOOBIG(p->name)) { + PUSHOUT(Directory); + } + add_count = snprintf(&where_args[where_count], maxargs - where_count, " '%s'", p->name); + if (add_count > maxargs - where_count) + cleanup(0), errx(2, "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!"); + if (add_count > maxargs - perm_count) + cleanup(0), errx(2, "oops, miscounted strings!"); perm_count += add_count; - if (p->name[0] == '/') { - PUSHOUT(Directory); - } } } break; @@ -143,7 +184,8 @@ extract_plist(char *home, Package *pkg) PUSHOUT(Directory); if (strcmp(p->name, ".")) { if (!Fake && make_hierarchy(p->name) == FAIL) - barf("Unable make directory '%s'.", p->name); + cleanup(0), errx(2, "unable to make directory '%s'", + p->name); Directory = p->name; } else @@ -151,12 +193,15 @@ extract_plist(char *home, Package *pkg) break; case PLIST_CMD: + if (last_file == NULL) + cleanup(0), errx(2, "no last file specified for '%s' command", + p->name); format_cmd(cmd, p->name, Directory, last_file); PUSHOUT(Directory); if (Verbose) printf("extract: execute '%s'\n", cmd); if (!Fake && system(cmd)) - whinge("Command '%s' failed.", cmd); + warnx("command '%s' failed", cmd); break; case PLIST_CHMOD: @@ -180,6 +225,9 @@ extract_plist(char *home, Package *pkg) case PLIST_IGNORE: p = p->next; break; + + default: + break; } p = p->next; } diff --git a/usr.sbin/pkg_install/add/futil.c b/usr.sbin/pkg_install/add/futil.c index 1d1afddc21b..78d2bc676e9 100644 --- a/usr.sbin/pkg_install/add/futil.c +++ b/usr.sbin/pkg_install/add/futil.c @@ -1,7 +1,7 @@ -/* $OpenBSD: futil.c,v 1.3 1997/01/17 07:14:11 millert Exp $ */ +/* $OpenBSD: futil.c,v 1.4 1998/09/07 22:30:13 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: futil.c,v 1.3 1997/01/17 07:14:11 millert Exp $"; +static const char *rcsid = "$OpenBSD: futil.c,v 1.4 1998/09/07 22:30:13 marc Exp $"; #endif /* @@ -24,6 +24,7 @@ static const char *rcsid = "$OpenBSD: futil.c,v 1.3 1997/01/17 07:14:11 millert * */ +#include <err.h> #include "lib.h" #include "add.h" @@ -45,7 +46,7 @@ make_hierarchy(char *dir) if ((cp2 = strchr(cp1, '/')) !=NULL ) *cp2 = '\0'; if (fexists(dir)) { - if (!isdir(dir)) + if (!(isdir(dir) || islinktodir(dir))) return FAIL; } else { @@ -75,22 +76,19 @@ apply_perms(char *dir, char *arg) if (Mode) if (vsystem("cd %s && chmod -R %s %s", cd_to, Mode, arg)) - whinge("Couldn't change modes of '%s' to '%s'.", - arg, Mode); + warnx("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'.", + warnx("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'.", - arg, Owner); + warnx("couldn't change owner of '%s' to '%s'", 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'.", - arg, Group); + warnx("couldn't change group of '%s' to '%s'", arg, Group); } diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c index f07752ebab3..9ee9284d359 100644 --- a/usr.sbin/pkg_install/add/main.c +++ b/usr.sbin/pkg_install/add/main.c @@ -1,7 +1,7 @@ -/* $OpenBSD: main.c,v 1.7 1998/04/07 04:18:45 deraadt Exp $ */ +/* $OpenBSD: main.c,v 1.8 1998/09/07 22:30:13 marc Exp $ */ #ifndef lint -static char *rcsid = "$OpenBSD: main.c,v 1.7 1998/04/07 04:18:45 deraadt Exp $"; +static char *rcsid = "$OpenBSD: main.c,v 1.8 1998/09/07 22:30:13 marc Exp $"; #endif /* @@ -25,6 +25,7 @@ static char *rcsid = "$OpenBSD: main.c,v 1.7 1998/04/07 04:18:45 deraadt Exp $"; * */ +#include <err.h> #include <sys/param.h> #include "lib.h" #include "add.h" @@ -34,7 +35,6 @@ static char Options[] = "hvIRfnp:SMt:"; char *Prefix = NULL; Boolean NoInstall = FALSE; Boolean NoRecord = FALSE; -Boolean Force = FALSE; char *Mode = NULL; char *Owner = NULL; @@ -48,12 +48,14 @@ add_mode_t AddMode = NORMAL; char pkgnames[MAX_PKGS][MAXPATHLEN]; char *pkgs[MAX_PKGS]; +static void usage __P((void)); + int main(int argc, char **argv) { int ch, err; char **start; - char *prog_name = argv[0], *cp; + char *cp; start = argv; while ((ch = getopt(argc, argv, Options)) != -1) { @@ -98,7 +100,7 @@ main(int argc, char **argv) case 'h': case '?': default: - usage(prog_name, NULL); + usage(); break; } } @@ -106,7 +108,7 @@ main(int argc, char **argv) argv += optind; if (argc > MAX_PKGS) { - whinge("Too many packages (max %d).", MAX_PKGS); + warnx("too many packages (max %d)", MAX_PKGS); return(1); } @@ -124,7 +126,7 @@ main(int argc, char **argv) pkgs[ch] = realpath(*argv, pkgnames[ch]); else { /* look for the file in the expected places */ if (!(cp = fileFindByPath(NULL, *argv))) - whinge("Can't find package '%s'.", *argv); + warnx("can't find package '%s'", *argv); else pkgs[ch] = strcpy(pkgnames[ch], cp); } @@ -132,32 +134,25 @@ main(int argc, char **argv) } /* If no packages, yelp */ if (!ch) - usage(prog_name, NULL); + warnx("missing package name(s)"), usage(); else if (ch > 1 && AddMode == MASTER) - usage(prog_name, - "Only one package name may be specified with master mode"); + warnx("only one package name may be specified with master mode"), + usage(); } - if ((err = pkg_perform(pkgs)) != NULL) { + if ((err = pkg_perform(pkgs)) != 0) { if (Verbose) - fprintf(stderr, "%d package addition(s) failed.\n", err); + warnx("%d package addition(s) failed", err); return err; } else return 0; } -void -usage(const char *name, const char *fmt, ...) +static void +usage() { - va_list args; - - va_start(args, fmt); - if (fmt) { - fprintf(stderr, "%s: ", name); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - } - va_end(args); - fprintf(stderr, "usage: %s [-vInfRMS] [-t template] [-p prefix] pkg ...\n", name); + fprintf(stderr, "%s\n%s\n", + "usage: pkg_add [-vInfRMS] [-t template] [-p prefix]", + " pkg-name [pkg-name ...]"); exit(1); } diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c index 166749a82d8..e654ef1db4a 100644 --- a/usr.sbin/pkg_install/add/perform.c +++ b/usr.sbin/pkg_install/add/perform.c @@ -1,7 +1,7 @@ -/* $OpenBSD: perform.c,v 1.4 1998/04/07 05:56:13 marc Exp $ */ +/* $OpenBSD: perform.c,v 1.5 1998/09/07 22:30:13 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1998/04/07 05:56:13 marc Exp $"; +static const char *rcsid = "$OpenBSD: perform.c,v 1.5 1998/09/07 22:30:13 marc Exp $"; #endif /* @@ -24,6 +24,7 @@ static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1998/04/07 05:56:13 marc E * */ +#include <err.h> #include "lib.h" #include "add.h" @@ -33,6 +34,7 @@ static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1998/04/07 05:56:13 marc E static int pkg_do(char *); static int sanity_check(char *); static char LogDir[FILENAME_MAX]; +static int zapLogDir; /* Should we delete LogDir? */ int pkg_perform(char **pkgs) @@ -70,11 +72,10 @@ pkg_do(char *pkg) int code; PackingList p; struct stat sb; - char *isTMP = NULL; - char *cp; int inPlace; code = 0; + zapLogDir = 0; LogDir[0] = '\0'; strcpy(playpen, FirstPen); inPlace = 0; @@ -84,7 +85,7 @@ pkg_do(char *pkg) fgets(playpen, FILENAME_MAX, stdin); playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */ if (chdir(playpen) == FAIL) { - whinge("pkg_add in SLAVE mode can't chdir to %s.", playpen); + warnx("add in SLAVE mode can't chdir to %s", playpen); return 1; } read_plist(&Plist, stdin); @@ -95,14 +96,16 @@ pkg_do(char *pkg) /* Is it an ftp://foo.bar.baz/file.tgz specification? */ if (isURL(pkg)) { if (!(Home = fileGetURL(NULL, pkg))) { - whinge("Unable to fetch `%s' by URL.", pkg); + warnx("unable to fetch `%s' by URL", pkg); return 1; } where_to = Home; strcpy(pkg_fullname, pkg); cfile = fopen(CONTENTS_FNAME, "r"); if (!cfile) { - whinge("Unable to open table of contents file `%s' - not a package?", CONTENTS_FNAME); + warnx( + "unable to open table of contents file `%s' - not a package?", + CONTENTS_FNAME); goto bomb; } read_plist(&Plist, cfile); @@ -112,7 +115,7 @@ pkg_do(char *pkg) strcpy(pkg_fullname, pkg); /* copy for sanity's sake, could remove pkg_fullname */ if (strcmp(pkg, "-")) { if (stat(pkg_fullname, &sb) == FAIL) { - whinge("Can't stat package file '%s'.", pkg_fullname); + warnx("can't stat package file '%s'", pkg_fullname); goto bomb; } #if 0 @@ -122,19 +125,26 @@ pkg_do(char *pkg) #endif extract = extract_contents; } - else + else { extract = NULL; + sb.st_size = 100000; /* Make up a plausible average size */ + } Home = make_playpen(playpen, sb.st_size * 4); if (!Home) - whinge("Unable to make playpen for %d bytes.\n", sb.st_size * 4); + warnx("unable to make playpen for %ld bytes", + (long)(sb.st_size * 4)); where_to = Home; if (unpack(pkg_fullname, extract)) { - whinge("Unable to extract table of contents file from `%s' - not a package?.", pkg_fullname); + warnx( + "unable to extract table of contents file from `%s' - not a package?", + pkg_fullname); goto bomb; } cfile = fopen(CONTENTS_FNAME, "r"); if (!cfile) { - whinge("Unable to open table of contents file `%s' - not a package?", CONTENTS_FNAME); + warnx( + "unable to open table of contents file `%s' - not a package?", + CONTENTS_FNAME); goto bomb; } read_plist(&Plist, cfile); @@ -146,13 +156,12 @@ pkg_do(char *pkg) printf("Doing in-place extraction for %s\n", pkg_fullname); p = find_plist(&Plist, PLIST_CWD); if (p) { - if (!isdir(p->name) && !Fake) { + if (!(isdir(p->name) || islinktodir(p->name)) && !Fake) { if (Verbose) - printf("Desired prefix of %s does not exist, creating..\n", p->name); + printf("Desired prefix of %s does not exist, creating.\n", p->name); vsystem("mkdir -p %s", p->name); if (chdir(p->name) == -1) { - whinge("Unable to change directory to `%s' - no permission?", p->name); - perror("chdir"); + warn("unable to change directory to `%s'", p->name); goto bomb; } } @@ -160,7 +169,9 @@ pkg_do(char *pkg) inPlace = 1; } else { - whinge("No prefix specified in `%s' - this is a bad package!", pkg_fullname); + warnx( + "no prefix specified in `%s' - this is a bad package!", + pkg_fullname); goto bomb; } } @@ -174,11 +185,11 @@ pkg_do(char *pkg) */ if (!extract && !inPlace && min_free(playpen) < sb.st_size * 4) { - whinge("Projected size of %d exceeds available free space.\n" + warnx("projected size of %d exceeds available free space.\n" "Please set your PKG_TMPDIR variable to point to a" "location with more\n" - "free space and try again.", sb.st_size * 4); - whinge("Not extracting %s\ninto %s, sorry!", pkg_fullname, + "free space and try again", sb.st_size * 4); + warnx("not extracting %s\ninto %s, sorry!", pkg_fullname, where_to); goto bomb; } @@ -190,7 +201,7 @@ pkg_do(char *pkg) /* Finally unpack the whole mess. If extract is null we already did so so don't bother doing it again. */ if (extract && unpack(pkg_fullname, NULL)) { - whinge("Unable to extract `%s'!", pkg_fullname); + warnx("unable to extract `%s'!", pkg_fullname); goto bomb; } } @@ -222,58 +233,84 @@ pkg_do(char *pkg) /* See if we're already registered */ sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, PkgName); - if (isdir(LogDir)) { - char tmp[FILENAME_MAX]; - - whinge("Package `%s' already recorded as installed.\n", PkgName); + if ((isdir(LogDir) || islinktodir(LogDir)) && !Force) { + warnx("package `%s' already recorded as installed", PkgName); code = 1; goto success; /* close enough for government work */ } + /* See if there are conflicting packages installed */ + for (p = Plist.head; p ; p = p->next) { + if (p->type != PLIST_PKGCFL) + continue; + if (Verbose) + printf("Package `%s' conflicts with `%s'.\n", PkgName, p->name); + if (!vsystem("/usr/sbin/pkg_info -qe '%s'", p->name)) { + warnx("Conflicting package `%s' installed, please use pkg_delete(1)\n\t first to remove it!\n", p->name); + ++code; + } + } + /* Now check the packing list for dependencies */ for (p = Plist.head; p ; p = p->next) { if (p->type != PLIST_PKGDEP) continue; if (Verbose) printf("Package `%s' depends on `%s'.\n", PkgName, p->name); - if (!Fake && vsystem("pkg_info -e %s", p->name)) { + if (vsystem("/usr/sbin/pkg_info -qe '%s'", p->name)) { char path[FILENAME_MAX], *cp = NULL; - if (!Fake && !isURL(pkg) && !getenv("PKG_ADD_BASE")) { - snprintf(path, FILENAME_MAX, "%s/%s.tgz", Home, p->name); - if (fexists(path)) - cp = path; + if (!Fake) { + if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) { + snprintf(path, FILENAME_MAX, "%s/%s.tgz", Home, p->name); + if (fexists(path)) + cp = path; + else + cp = fileFindByPath(pkg, p->name); + if (cp) { + if (Verbose) + printf("Loading it from %s.\n", cp); + if (vsystem("/usr/sbin/pkg_add %s%s %s%s", + Prefix ? "-p " : "", + Prefix ? Prefix : "", + Verbose ? "-v " : "", cp)) { + warnx("autoload of dependency `%s' failed%s", + cp, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; + } + } else - cp = fileFindByPath(pkg, p->name); - if (cp) { + warnx("add of dependency `%s' failed%s", + p->name, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; + } + else if ((cp = fileGetURL(pkg, p->name)) != NULL) { if (Verbose) - printf("Loading it from %s.\n", cp); - if (vsystem("pkg_add %s", cp)) { - whinge("Autoload of dependency `%s' failed%s", cp, Force ? " (proceeding anyway)" : "!"); + printf("Finished loading %s over FTP.\n", p->name); + if (!fexists(CONTENTS_FNAME)) { + warnx("autoloaded package %s has no %s file?", + p->name, CONTENTS_FNAME); if (!Force) ++code; } + else if (vsystem("(pwd; cat %s) | pkg_add %s%s %s-S", + CONTENTS_FNAME, + Prefix ? "-p " : "", + Prefix ? Prefix : "", + Verbose ? "-v " : "")) { + warnx("add of dependency `%s' failed%s", + p->name, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++code; + } + else if (Verbose) + printf("\t`%s' loaded successfully.\n", p->name); + /* Nuke the temporary playpen */ + leave_playpen(cp); } } - else if (!Fake && (cp = fileGetURL(pkg, p->name)) != NULL) { - if (Verbose) - printf("Finished loading %s over FTP.\n", p->name); - if (!Fake) { - if (!fexists("+CONTENTS")) - whinge("Autoloaded package %s has no +CONTENTS file?", p->name); - else - if (vsystem("(pwd; cat +CONTENTS) | pkg_add %s-S", Verbose ? "-v " : "")) { - whinge("pkg_add of dependency `%s' failed%s", - p->name, Force ? " (proceeding anyway)" : "!"); - if (!Force) - ++code; - } - else if (Verbose) - printf("\t`%s' loaded successfully.\n", p->name); - } - /* Nuke the temporary playpen */ - leave_playpen(cp); - } else { if (Verbose) printf("and was not found%s.\n", Force ? " (proceeding anyway)" : ""); @@ -288,14 +325,17 @@ pkg_do(char *pkg) printf(" - already installed.\n"); } + if (code != 0) + goto bomb; + /* Look for the requirements file */ if (fexists(REQUIRE_FNAME)) { vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ if (Verbose) - printf("Running requirements file first for %s..\n", PkgName); + printf("Running requirements file first for %s.\n", PkgName); if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, PkgName)) { - whinge("Package %s fails requirements %s", pkg_fullname, - Force ? "installing anyway" : "- not installed."); + warnx("package %s fails requirements %s", pkg_fullname, + Force ? "installing anyway" : "- not installed"); if (!Force) { code = 1; goto success; /* close enough for government work */ @@ -307,9 +347,9 @@ pkg_do(char *pkg) if (!NoInstall && fexists(INSTALL_FNAME)) { vsystem("chmod +x %s", INSTALL_FNAME); /* make sure */ if (Verbose) - printf("Running install with PRE-INSTALL for %s..\n", PkgName); + 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."); + warnx("install script returned error status"); unlink(INSTALL_FNAME); code = 1; goto success; /* nothing to uninstall yet */ @@ -322,13 +362,13 @@ pkg_do(char *pkg) if (!Fake && fexists(MTREE_FNAME)) { if (Verbose) - printf("Running mtree for %s..\n", PkgName); + 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) { if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s", MTREE_FNAME, p ? p->name : "/")) - whinge("mtree returned a non-zero status - continuing."); + warnx("mtree returned a non-zero status - continuing"); } unlink(MTREE_FNAME); } @@ -336,9 +376,9 @@ pkg_do(char *pkg) /* Run the installation script one last time? */ if (!NoInstall && fexists(INSTALL_FNAME)) { if (Verbose) - printf("Running install with POST-INSTALL for %s..\n", PkgName); + 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."); + warnx("install script returned error status"); unlink(INSTALL_FNAME); code = 1; goto fail; @@ -353,19 +393,20 @@ pkg_do(char *pkg) umask(022); if (getuid() != 0) - whinge("Not running as root - trying to record install anyway."); + warnx("not running as root - trying to record install anyway"); if (!PkgName) { - whinge("No package name! Can't record package, sorry."); + warnx("no package name! can't record package, sorry"); code = 1; goto success; /* well, partial anyway */ } sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, PkgName); + zapLogDir = 1; if (Verbose) - printf("Attempting to record package into %s..\n", LogDir); + printf("Attempting to record package into %s.\n", LogDir); if (make_hierarchy(LogDir)) { - whinge("Can't record package into '%s', you're on your own!", + warnx("can't record package into '%s', you're on your own!", LogDir); - bzero(LogDir, FILENAME_MAX); + memset(LogDir, 0, FILENAME_MAX); code = 1; goto success; /* close enough for government work */ } @@ -378,7 +419,8 @@ pkg_do(char *pkg) sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME); cfile = fopen(contents, "w"); if (!cfile) { - whinge("Can't open new contents file '%s'! Can't register pkg.", contents); + warnx("can't open new contents file '%s'! can't register pkg", + contents); goto success; /* can't log, but still keep pkg */ } write_plist(&Plist, cfile); @@ -396,22 +438,24 @@ pkg_do(char *pkg) basename_of(p->name), REQUIRED_BY_FNAME); cfile = fopen(contents, "a"); if (!cfile) - whinge("Warning: Can't open dependency file '%s'!\n" - "\tDependency registration is incomplete.", contents); + warnx("can't open dependency file '%s'!\n" + "dependency registration is incomplete", contents); else { fprintf(cfile, "%s\n", PkgName); if (fclose(cfile) == EOF) - warn("Cannot properly close file %s", contents); + warnx("cannot properly close file %s", contents); } } if (Verbose) printf("Package %s registered in %s\n", PkgName, LogDir); } - if (p = find_plist(&Plist, PLIST_DISPLAY)) { + if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) { FILE *fp; char buf[BUFSIZ]; - fp = fopen(p->name, "r"); + + snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name); + fp = fopen(buf, "r"); if (fp) { putc('\n', stdout); while (fgets(buf, sizeof(buf), fp)) @@ -419,7 +463,7 @@ pkg_do(char *pkg) putc('\n', stdout); (void) fclose(fp); } else - warn("Cannot open display file `%s'.", p->name); + warn("cannot open %s as display file", buf); } goto success; @@ -443,19 +487,18 @@ pkg_do(char *pkg) static int sanity_check(char *pkg) { - PackingList p; int code = 0; if (!fexists(CONTENTS_FNAME)) { - whinge("Package %s has no CONTENTS file!", pkg); + warnx("package %s has no CONTENTS file!", pkg); code = 1; } else if (!fexists(COMMENT_FNAME)) { - whinge("Package %s has no COMMENT file!", pkg); + warnx("package %s has no COMMENT file!", pkg); code = 1; } else if (!fexists(DESC_FNAME)) { - whinge("Package %s has no DESC file!", pkg); + warnx("package %s has no DESC file!", pkg); code = 1; } return code; @@ -464,14 +507,22 @@ sanity_check(char *pkg) void cleanup(int signo) { - if (signo) - printf("Signal %d received, cleaning up..\n", signo); - if (Plist.head) { - if (!Fake) - delete_package(FALSE, FALSE, &Plist); - free_plist(&Plist); + static int alreadyCleaning; + void (*oldint)(int); + void (*oldhup)(int); + oldint = signal(SIGINT, SIG_IGN); + oldhup = signal(SIGHUP, SIG_IGN); + + if (!alreadyCleaning) { + alreadyCleaning = 1; + if (signo) + printf("Signal %d received, cleaning up.\n", signo); + if (!Fake && zapLogDir && LogDir[0]) + vsystem("%s -rf %s", REMOVE_CMD, LogDir); + leave_playpen(Home); + if (signo) + exit(1); } - if (!Fake && LogDir[0]) - vsystem("%s -rf %s", REMOVE_CMD, LogDir); - leave_playpen(Home); + signal(SIGINT, oldint); + signal(SIGHUP, oldhup); } diff --git a/usr.sbin/pkg_install/add/pkg_add.1 b/usr.sbin/pkg_install/add/pkg_add.1 index 884a157b342..7d902056677 100644 --- a/usr.sbin/pkg_install/add/pkg_add.1 +++ b/usr.sbin/pkg_install/add/pkg_add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_add.1,v 1.5 1998/09/06 22:23:18 aaron Exp $ +.\" $OpenBSD: pkg_add.1,v 1.6 1998/09/07 22:30:14 marc Exp $ .\" .\" FreeBSD install - a package for the installation and maintainance .\" of non-core utilities. @@ -22,7 +22,7 @@ .Os .Sh NAME .Nm pkg_add -.Nd a utility for installing software package distributions. +.Nd a utility for installing software package distributions .Sh SYNOPSIS .Nm .Op Fl vInfRMS @@ -65,33 +65,35 @@ command to examine the package file. .Ef .Sh OPTIONS -The following command line arguments are supported. +The following command line arguments are supported: .Bl -tag -width indent .It Ar pkg-name [... pkg-name] The named packages are installed. A package name of - will cause .Nm -to read from stdin. +to read from stdin. If the packages are not found in the current +working directory, +.Nm +will search them in each directory named by +.Ev PKG_PATH . .It Fl v -Turns on verbose output. -.Em "Optional." +Turn on verbose output. .It Fl I If an installation script exists for a given package, do not execute it. -.Em "Optional." .It Fl n Don't actually install a package, just report the steps that would be taken if it was. -.Em "Optional." .It Fl R Do not record the installation of a package. This means that you cannot deinstall it later, so only use this option if you know what you are doing! -.Em "Optional." .It Fl f -Forces installation to proceed even if prerequisite packages are not -installed or the requirements script fails. -.Em "Optional." +Force installation to proceed even if prerequisite packages are not +installed or the requirements script fails. Although +.Nm +will still try to find and auto-install missing prerequisite packages, +a failure to find one will not be fatal. .It Fl p Ar prefix -Sets +Set .Ar prefix as the directory in which to extract files from a package. If a package has set its default directory, it will be overridden @@ -100,9 +102,10 @@ by this flag. Note that only the first directive will be replaced, since .Nm has no way of knowing which directory settings are relative and -which are absolute. It is rare, in any case, to see more than one -directory transition made, but when such is the case you -may then wish to look into the use of the +which are absolute. It is rare in any case to see more than one +directory transition made, but when such does happen and you wish +to have control over *all* directory transitions, then you +may then wish to look into the use of .Cm MASTER and .Cm SLAVE @@ -111,7 +114,6 @@ modes (see the and .Fl S options). -.Em "Optional." .It Fl t Ar template Use .Ar template @@ -122,7 +124,7 @@ By default, this is the string .Pa /var/tmp/instmp.XXXXXX , but it may be necessary to override it in the situation where space in your -.Pa /tmp +.Pa /var/tmp directory is limited. Be sure to leave some number of `X' characters for .Xr mkdtemp 3 @@ -133,7 +135,6 @@ You can get a performance boost by setting the staging area to reside on the same disk partition as target directories for package file installation; often this is .Pa /usr . -.Em "Optional." .It Fl M Run in .Cm MASTER @@ -177,7 +178,6 @@ URL pointing at a file available on an ftp site. Thus you may extract files directly from their anonymous ftp locations (e.g. .Nm ftp://ftp.freebsd.org/pub/FreeBSD/packages/shells/bash-1.14.4.tgz). -.Pp Note: If you wish to use .Bf -emphasis active mode @@ -213,29 +213,42 @@ passive mode .Ef connection. .Sh TECHNICAL DETAILS -.Nm -is fairly simple. It extracts each packages' "packing list" -into a special staging directory in /tmp (or $PKG_TMPDIR), parses it, -then runs through the following sequence to fully extract the contents: +.Nm +extracts each package's "packing list" +into a special staging directory in /tmp (or $PKG_TMPDIR if set) +and then runs through the following sequence to fully extract the contents +of the package: .Bl -enum -indent indent .It -Check if the package is already recorded as installed. If so, -terminate installation. +A check is made to determine if the package is already recorded as installed. +If it is, +installation is terminated. .It -Scan all the package dependencies (from +A check is made to determine if the package conflicts (from +.Cm @pkgcfl +directives, see +.Xr pkg_create 1 ) +with an already recorded as installed package. If it is, +installation is terminated. +.It +All package dependencies (from .Cm @pkgdep directives, see .Xr pkg_create 1 ) -and make sure each one is met. If not, print the missing dependencies and -terminate the installation. +are read from the packing list. +If any of these required packages is not currently installed, +an attempt is made to find and install it; +if the missing package cannot be found or installed, +the installation is terminated. .It -Search for any +A search is made for any .Cm @option directives which control how the package is added to the system. -At the time of this writing, the only currently implemented option is -.Cm @option extract-in-place -which will cause the package to be extracted direcly into its -prefix directory without moving through a staging area in /tmp. +The only currently implemented option is +.Cm @option extract-in-place , +which causes the package to be extracted directly into its +prefix directory rather than moving it through a staging area in +.Pa /tmp . .It If .Cm @option extract-in-place @@ -244,46 +257,48 @@ final location, otherwise it is extracted into the staging area. .It If the package contains a .Ar require -file (see +script (see .Xr pkg_create 1 ), -then execute it with the following arguments: -.Bd -filled -offset indent -compact -.Ar <pkg-name> -.Ar INSTALL -.Ed -where -.Ar <pkg-name> -is the name of the package in question and -.Ar INSTALL -is simply a keyword denoting that this is an installation requirements check. +it is executed with the following arguments: +.Bl -tag -width indentindent +.It Ar pkg-name +The name of the package being installed +.It Cm INSTALL +Keyword denoting to the script that it is to run an installation requirements +check. +(The keyword is useful only to scripts which serve multiple functions). +.El +.Pp +If the +.Ar require +script exits with a non-zero status code, the installation is terminated. .It -If an +If the package contains an .Ar install -script exists for the package, it is then executed with the following arguments: -.Bd -filled -offset indent -compact -.Ar <pkg-name> -.Ar PRE-INSTALL -.Ed -where -.Ar <pkg-name> -is the name of the package in question and -.Ar PRE-INSTALL -is a keyword denoting that this is the preinstallation phase. +script, it is executed with the following arguments: +.Bl -tag -width indentindent +.It Ar pkg-name +The name of the package being installed. +.It Cm PRE-INSTALL +Keyword denoting that the script is to perform any actions needed before +the package is installed. +.El +.Pp +If the +.Ar install +script exits with a non-zero status code, the installation is terminated. .It If .Cm @option extract-in-place -is not used, then the packing list (this is the -.Pa +CONTENTS -file) is now used as a guide for moving (or copying, as necessary) files from +is not present in the packing list, +then it is used as a guide for moving (or copying, as necessary) files from the staging area into their final locations. .It If the package contains an .Ar mtreefile -file (see the -.Fl m -option to +file (see .Xr pkg_create 1 ), -then mtree is invoked as +then mtree is invoked as: .Bd -filled -offset indent -compact .Cm mtree .Fl u @@ -306,15 +321,14 @@ directive within this package. .It If an .Ar install -script exists for the package, it is then executed as -.Bd -filled -offset indent -compact -.Cm <script> -.Ar <pkg-name> -.Ar POST-INSTALL -.Ed -This all allows you to write a single -.Ar install -script that does both ``before and after'' actions. +script exists for the package, it is executed with the following arguments: +.Bl -tag -width indentindent +.It Ar pkg_name +The name of the package being installed. +.It Cm POST-INSTALL +Keyword denoting that the script is to perform any actions needed +after the package has been installed. +.El .It After installation is complete, a copy of the packing list, .Ar deinstall @@ -332,7 +346,11 @@ path shown above). Finally, the staging area is deleted and the program terminates. .El .Pp -All the scripts are called with the environment variable +The +.Ar install +and +.Ar require +scripts are called with the environment variable .Ev PKG_PREFIX set to the installation prefix (see the .Fl p @@ -342,20 +360,33 @@ is installed, even if the user might change it with the .Fl p flag to .Cm pkg_add . +.Sh ENVIRONMENT +.Ss PKG_PATH +The value of the +.Ev PKG_PATH +is used if a given package can't be found, it's usually set to +.Pa /usr/pkgsrc/packages/All . +The environment variable +should be a series of entries seperated by colons. Each entry +consists of a directory name. The current directory may be indicated +implicitly by an empty directory name, or explicitly by a single +period. +.Ss PKG_DBDIR +Where to register packages instead of +.Pa /var/db/pkg . .Sh SEE ALSO -.Xr ftp 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , .Xr pkg_info 1 , .Xr mkdtemp 3 , .Xr sysconf 3 , -.Xr mtree 8 , -.Xr pkg_create 1 , -.Xr pkg_delete 1 . +.Xr mtree 8 .Sh AUTHORS .Bl -tag -width indent -compact .It "Jordan Hubbard" -most of the work +Initial work and ongoing development. .It "John Kohl" -refined it for NetBSD +NetBSD refinements. .El .Sh BUGS Hard links between files in a distribution are only preserved if either |