diff options
27 files changed, 1495 insertions, 931 deletions
diff --git a/usr.sbin/pkg_install/README b/usr.sbin/pkg_install/README index a5a517d7752..e6d49ccba3c 100644 --- a/usr.sbin/pkg_install/README +++ b/usr.sbin/pkg_install/README @@ -1,3 +1,6 @@ +# $OpenBSD: README,v 1.2 1998/09/07 22:30:12 marc Exp $ +# (Original from FreeBSD) + 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. 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 diff --git a/usr.sbin/pkg_install/create/create.h b/usr.sbin/pkg_install/create/create.h index 71c616c673a..303442fb0e0 100644 --- a/usr.sbin/pkg_install/create/create.h +++ b/usr.sbin/pkg_install/create/create.h @@ -1,4 +1,4 @@ -/* $OpenBSD: create.h,v 1.1 1996/06/04 07:56:05 niklas Exp $ */ +/* $OpenBSD: create.h,v 1.2 1998/09/07 22:30:14 marc Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -31,15 +31,16 @@ extern char *Install; extern char *DeInstall; extern char *Contents; extern char *Require; -extern char PlayPen[]; +extern char *SrcDir; extern char *ExcludeFrom; extern char *Mtree; extern char *Pkgdeps; +extern char *Pkgcfl; +extern char PlayPen[]; extern int Dereference; extern int PlistOnly; void check_list(char *, Package *); -void usage(const char *, const char *, ...); int pkg_perform(char **); void copy_plist(char *, Package *); diff --git a/usr.sbin/pkg_install/create/main.c b/usr.sbin/pkg_install/create/main.c index 1fee0c38250..e11f7dc1638 100644 --- a/usr.sbin/pkg_install/create/main.c +++ b/usr.sbin/pkg_install/create/main.c @@ -1,7 +1,7 @@ -/* $OpenBSD: main.c,v 1.6 1998/04/07 04:17:49 deraadt Exp $ */ +/* $OpenBSD: main.c,v 1.7 1998/09/07 22:30:14 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: main.c,v 1.6 1998/04/07 04:17:49 deraadt Exp $"; +static const char *rcsid = "$OpenBSD: main.c,v 1.7 1998/09/07 22:30:14 marc Exp $"; #endif /* @@ -15,32 +15,36 @@ static const char *rcsid = "$OpenBSD: main.c,v 1.6 1998/04/07 04:17:49 deraadt E * */ +#include <err.h> #include "lib.h" #include "create.h" -static char Options[] = "YNOhvf:p:P:c:d:i:k:r:t:X:D:m:"; +static char Options[] = "YNOhvf:p:P:C:c:d:i:k:r:t:X:D:m:s:"; char *Prefix = NULL; char *Comment = NULL; char *Desc = NULL; +char *SrcDir = NULL; char *Display = NULL; char *Install = NULL; char *DeInstall = NULL; char *Contents = NULL; char *Require = NULL; -char PlayPen[FILENAME_MAX]; char *ExcludeFrom = NULL; char *Mtree = NULL; char *Pkgdeps = NULL; +char *Pkgcfl = NULL; +char PlayPen[FILENAME_MAX]; int Dereference = 0; int PlistOnly = 0; +static void usage __P((void)); + int main(int argc, char **argv) { int ch; char **pkgs, **start; - char *prog_name = argv[0]; pkgs = start = argv; while ((ch = getopt(argc, argv, Options)) != -1) @@ -65,6 +69,10 @@ main(int argc, char **argv) Prefix = optarg; break; + case 's': + SrcDir = optarg; + break; + case 'f': Contents = optarg; break; @@ -117,9 +125,13 @@ main(int argc, char **argv) Pkgdeps = optarg; break; + case 'C': + Pkgcfl = optarg; + break; + case '?': default: - usage(prog_name, NULL); + usage(); break; } @@ -132,36 +144,27 @@ main(int argc, char **argv) /* If no packages, yelp */ if (pkgs == start) - usage(prog_name, "Missing package name"); + warnx("missing package name"), usage(); *pkgs = NULL; if (start[1]) - usage(prog_name, "Only one package name allowed\n\t('%s' extraneous)", - start[1]); + warnx("only one package name allowed ('%s' extraneous)", start[1]), + usage(); if (!pkg_perform(start)) { if (Verbose) - fprintf(stderr, "Package creation failed.\n"); + warnx("package creation failed"); return 1; } 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 [-YNOhv] [-P pkgs] [-p prefix] [-f contents] [-i iscript]\n" - " [-k dscript] [-r rscript] [-t template] [-X excludefile]\n" - " [-D displayfile] [-m mtreefile] -d description -f packlist] pkg\n", - name); + fprintf(stderr, "%s\n%s\n%s\n%s\n", +"usage: pkg_create [-YNOhv] [-P dpkgs] [-C cpkgs] [-p prefix] [-f contents]", +" [-i iscript] [-k dscript] [-r rscript] [-t template]", +" [-X excludefile] [-D displayfile] [-m mtreefile]", +" -c comment -d description -f packlist pkg-name"); exit(1); } diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c index 83ceae813a2..53aaf2ca084 100644 --- a/usr.sbin/pkg_install/create/perform.c +++ b/usr.sbin/pkg_install/create/perform.c @@ -1,7 +1,7 @@ -/* $OpenBSD: perform.c,v 1.4 1997/01/17 07:14:13 millert Exp $ */ +/* $OpenBSD: perform.c,v 1.5 1998/09/07 22:30:14 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1997/01/17 07:14:13 millert Exp $"; +static const char *rcsid = "$OpenBSD: perform.c,v 1.5 1998/09/07 22:30:14 marc Exp $"; #endif /* @@ -27,9 +27,10 @@ static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1997/01/17 07:14:13 miller #include "lib.h" #include "create.h" -#include <errno.h> +#include <err.h> #include <signal.h> #include <sys/syslimits.h> +#include <sys/wait.h> #include <unistd.h> static void sanity_check(void); @@ -57,7 +58,8 @@ pkg_perform(char **pkgs) else { pkg_in = fopen(Contents, "r"); if (!pkg_in) - barf("Unable to open contents file '%s' for input.", Contents); + cleanup(0), errx(2, "unable to open contents file '%s' for input", + Contents); } plist.head = plist.tail = NULL; @@ -84,6 +86,30 @@ pkg_perform(char **pkgs) if (Verbose && !PlistOnly) printf(".\n"); } + + /* Put the conflicts directly after the dependencies, if any */ + if (Pkgcfl) { + if (Verbose && !PlistOnly) + printf("Registering conflicts:"); + while (Pkgcfl) { + cp = strsep(&Pkgcfl, " \t\n"); + if (*cp) { + add_plist(&plist, PLIST_PKGCFL, cp); + if (Verbose && !PlistOnly) + printf(" %s", cp); + } + } + if (Verbose && !PlistOnly) + printf(".\n"); + } + + /* If a SrcDir override is set, add it now */ + if (SrcDir) { + if (Verbose && !PlistOnly) + printf("Using SrcDir value of %s\n", SrcDir); + add_plist(&plist, PLIST_SRC, SrcDir); + } + /* Slurp in the packing list */ read_plist(&plist, pkg_in); @@ -104,6 +130,7 @@ pkg_perform(char **pkgs) * hack. It's not a real create in progress. */ if (PlistOnly) { + check_list(home, &plist); write_plist(&plist, stdout); exit(0); } @@ -157,18 +184,13 @@ pkg_perform(char **pkgs) add_plist(&plist, PLIST_MTREE, MTREE_FNAME); } - /* Run through the list again, picking up extra "local" items */ - /* check_list(".", &plist); */ - /* copy_plist(".", &plist); */ - /* mark_plist(&plist); */ - /* Finally, write out the packing list */ fp = fopen(CONTENTS_FNAME, "w"); if (!fp) - barf("Can't open file %s for writing.", CONTENTS_FNAME); + cleanup(0), errx(2, "can't open file %s for writing", CONTENTS_FNAME); write_plist(&plist, fp); if (fclose(fp)) - barf("Error while closing %s.", CONTENTS_FNAME); + cleanup(0), errx(2, "error while closing %s", CONTENTS_FNAME); /* And stick it into a tar ball */ make_dist(home, pkg, suffix, &plist); @@ -177,7 +199,7 @@ pkg_perform(char **pkgs) free(Comment); free(Desc); free_plist(&plist); - cleanup(0); + leave_playpen(home); return TRUE; /* Success */ } @@ -186,10 +208,9 @@ make_dist(char *home, char *pkg, char *suffix, Package *plist) { char tball[FILENAME_MAX]; PackingList p; - int ret, max, len; - /* XXX - The next one should be - allocated dynamically */ - char *args[4096]; /* Much more than enough. */ + int ret; +#define DIST_MAX_ARGS 4096 + char *args[DIST_MAX_ARGS]; /* Much more than enough. */ int nargs = 0; int pipefds[2]; FILE *totar; @@ -238,6 +259,8 @@ make_dist(char *home, char *pkg, char *suffix, Package *plist) args[nargs++] = MTREE_FNAME; for (p = plist->head; p; p = p->next) { + if (nargs > (DIST_MAX_ARGS - 2)) + errx(2, "too many args for tar command"); if (p->type == PLIST_FILE) args[nargs++] = p->name; else if (p->type == PLIST_CWD || p->type == PLIST_SRC) { @@ -248,24 +271,34 @@ make_dist(char *home, char *pkg, char *suffix, Package *plist) p = p->next; } args[nargs] = NULL; - execv("/bin/tar", args); - barf("Failed to execute tar command: %s", strerror(errno)); + /* fork/exec tar to create the package */ + + pid = fork(); + if ( pid < 0 ) + err(2, "failed to fork"); + else if ( pid == 0 ) { + execv("/bin/tar", args); + err(2, "failed to execute tar command"); + } wait(&ret); /* assume either signal or bad exit is enough for us */ if (ret) - barf("tar command failed with code %d", ret); + cleanup(0), errx(2, "tar command failed with code %d", ret); } static void sanity_check() { if (!Comment) - barf("Required package comment string is missing (-c comment)."); + cleanup(0), errx(2, + "required package comment string is missing (-c comment)"); if (!Desc) - barf("Required package description string is missing (-d desc)."); + cleanup(0), errx(2, + "required package description string is missing (-d desc)"); if (!Contents) - barf("Required package contents list is missing (-f [-]file)."); + cleanup(0), errx(2, + "required package contents list is missing (-f [-]file)"); } @@ -273,5 +306,20 @@ sanity_check() void cleanup(int sig) { - leave_playpen(home); + static int alreadyCleaning; + void (*oldint)(int); + void (*oldhup)(int); + oldint = signal(SIGINT, SIG_IGN); + oldhup = signal(SIGHUP, SIG_IGN); + + if (!alreadyCleaning) { + alreadyCleaning = 1; + if (sig) + printf("Signal %d received, cleaning up.\n", sig); + leave_playpen(home); + if (sig) + exit(1); + } + signal(SIGINT, oldint); + signal(SIGHUP, oldhup); } diff --git a/usr.sbin/pkg_install/create/pkg_create.1 b/usr.sbin/pkg_install/create/pkg_create.1 index bdf2b70ca10..7681dc5fd07 100644 --- a/usr.sbin/pkg_install/create/pkg_create.1 +++ b/usr.sbin/pkg_install/create/pkg_create.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_create.1,v 1.3 1996/12/29 12:18:29 graichen Exp $ +.\" $OpenBSD: pkg_create.1,v 1.4 1998/09/07 22:30:14 marc Exp $ .\" .\" FreeBSD install - a package for the installation and maintainance .\" of non-core utilities. @@ -16,6 +16,7 @@ .\" .\" .\" @(#)pkg_create.1 +.\" from FreeBSD Id: pkg_create.1,v 1.19 1997/05/02 22:00:05 max Exp .\" .\" hacked up by John Kohl for NetBSD--fixed a few bugs, extended keywords, .\" added dependency tracking, etc. @@ -28,11 +29,12 @@ .Os .Sh NAME .Nm pkg_create -.Nd a utility for creating software package distributions. +.Nd a utility for creating software package distributions .Sh SYNOPSIS .Nm .Op Fl YNOhv -.Op Fl P Ar pkgs +.Op Fl P Ar dpkgs +.Op Fl C Ar cpkgs .Op Fl p Ar prefix .Op Fl f Ar contents .Op Fl i Ar iscript @@ -42,6 +44,7 @@ .Op Fl X Ar excludefile .Op Fl D Ar displayfile .Op Fl m Ar mtreefile +.Fl c Ar comment .Fl d Ar description .Fl f Ar packlist .Ar pkg-name @@ -56,7 +59,7 @@ do so. It is more expected that you will use a front-end tool for the job rather than muddling through it yourself. Nonetheless, a short description of the input syntax is included in this document. .Sh OPTIONS -The following command line options are supported. +The following command line options are supported: .Bl -tag -width indent .It Fl f Ar packinglist Fetch ``packing list'' for package from the file @@ -68,7 +71,6 @@ if is a .Cm - (dash). -.Em "Mandatory." .It Fl c Ar [-]desc Fetch package ``one line description'' from file .Ar desc @@ -77,17 +79,14 @@ or, if preceded by the argument itself. This string should also give some idea of which version of the product (if any) the package represents. -.Em "Mandatory." .It Fl d Ar [-]desc Fetch long description for package from file .Ar desc or, if preceded by .Cm - , the argument itself. -.Em "Mandatory." .It Fl Y Assume a default answer of `Yes' for any questions asked. -.Em "Optional." .It Fl N Assume a default answer of `No' for any questions asked. .It Fl O @@ -96,49 +95,49 @@ Go into a `packing list Only' mode. This is a custom hack for the and is used to do `fake pkg_add' operations when a port is installed. In such cases, it is necessary to know what the final, adjusted packing list will look like. -.Em "Optional." .It Fl v -Turns on verbose output. -.Em "Optional." +Turn on verbose output. .It Fl h -Forces tar to follow symbolic links, so that the files they point to +Force tar to follow symbolic links, so that the files they point to are dumped, rather than the links themselves. .It Fl i Ar iscript -Sets +Set .Ar iscript to be the install procedure for the package. This can be any executable program (or shell script). It will be invoked automatically when the package is later installed. -.Em "Optional." -.It Fl P Ar pkgs -Sets the initial package dependency list to -.Ar pkgs. +.It Fl P Ar dpkgs +Set the initial package dependency list to +.Ar dpkgs . This is assumed to be a whitespace separated list of package names and is meant as a convenient shorthand for specifying multiple .Cm @pkgdep directives in the packing list (see PACKING LIST DETAILS section below). -.Em "Optional." +.It Fl C Ar cpkgs +Set the initial package conflict list to +.Ar cpkgs . +This is assumed to be a whitespace separated list of package names +and is meant as a convenient shorthand for specifying multiple +.Cm @pkgcfl +directives in the packing list (see PACKING LIST DETAILS section below). .It Fl p Ar prefix -Sets +Set .Ar prefix as the initial directory ``base'' to start from in selecting files for the package. -.Em "Optional." .It Fl k Ar dscript -Sets +Set .Ar dscript to be the de-install procedure for the package. This can be any executable program (or shell script). It will be invoked automatically when the package is later (if ever) de-installed. -.Em "Optional." .It Fl r Ar rscript -Sets +Set .Ar rscript to be the ``requirements'' procedure for the package. This can be any executable program (or shell script). It will be invoked automatically at installation/deinstallation time to determine whether or not installation/deinstallation should proceed. -.Em "Optional." .It Fl t Ar template Use .Ar template @@ -153,7 +152,6 @@ directory is limited. Be sure to leave some number of `X' characters for .Xr mktemp 3 to fill in with a unique ID. -.Em "Optional." .It Fl X Ar excludefile Pass .Ar excludefile @@ -206,14 +204,14 @@ installed with. This is done by imbeding specialized command sequences in the packing list. Briefly described, these sequences are: .Bl -tag -width indent -compact .It Cm @cwd Ar directory -Sets the internal directory pointer to point to +Set the internal directory pointer to point to .Ar directory . All subsequent filenames will be assumed relative to this directory. Note: .Cm @cd is also an alias for this command. .It Cm @srcdir Ar directory -Sets the internal directory pointer for _creation only_ to +Set the internal directory pointer for _creation only_ to .Ar directory . That is to say that it overrides .Cm @cwd @@ -223,7 +221,7 @@ Execute .Ar command as part of the unpacking process. If .Ar command -contains a any of the following sequences somewhere in it, they will +contains any of the following sequences somewhere in it, they will be expanded inline. For the following examples, assume that .Cm @cwd is set to @@ -235,17 +233,17 @@ and the last extracted file was Expands to the last filename extracted (as specified), in the example case .Pa bin/emacs .It Cm "%D" -Expands to the current directory prefix, as set with +Expand to the current directory prefix, as set with .Cm @cwd , in the example case .Pa /usr/local . .It Cm "%B" -Expands to the ``basename'' of the fully qualified filename, that +Expand to the ``basename'' of the fully qualified filename, that is the current directory prefix, plus the last filespec, minus the trailing filename. In the example case, that would be .Pa /usr/local/bin . .It Cm "%f" -Expands to the ``filename'' part of the fully qualified name, or +Expand to the ``filename'' part of the fully qualified name, or the converse of .Cm %B , being in the example case, @@ -269,22 +267,34 @@ removable). The advantage of using over a deinstallation script is that you can use the ``special sequence expansion'' to get at files regardless of where they've been potentially redirected (see -.Fl p ) +.Fl p ) . .It Cm @mode Ar mode -Sets default permission for all subsequently extracted files to +Set default permission for all subsequently extracted files to .Ar mode . Format is the same as that used by the .Cm chmod command (well, considering that it's later handed off to it, that's no surprise). Use without an arg to set back to default (extraction) permissions. +.It Cm @option Ar option +Set internal package options, the only two currently supported ones +being +.Ar extract-in-place , +which tells the pkg_add command not to extract the package's tarball +into a staging area but rather directly into the target +hierarchy (this is typically meant to be used only by distributions +or other special package types), and +.Ar preserve , +which tells pkg_add to move any existing files out of the way, +preserving the previous contents (which are also resurrected on +pkg_delete, so caveat emptor). .It Cm @owner Ar user -Sets default ownership for all subsequently extracted files to +Set default ownership for all subsequently extracted files to .Ar user . Use without an arg to set back to default (extraction) ownership. .It Cm @group Ar group -Sets default group ownership for all subsequently extracted files to +Set default group ownership for all subsequently extracted files to .Ar group . Use without an arg to set back to default (extraction) group ownership. @@ -305,7 +315,7 @@ file, so you can pack a specialized datafile in with a distribution for your install script (or something) yet have the installer ignore it. .It Cm @name Ar name -Sets the name of the package. This is mandatory and is usually +Set the name of the package. This is mandatory and is usually put at the top. This name is potentially different than the name of the file it came in, and is used when keeping track of the package for later deinstallation. Note that @@ -341,7 +351,7 @@ as the file to be displayed at install time (see .Fl D above). .It Cm @pkgdep Ar pkgname -Declares a dependency on the +Declare a dependency on the .Ar pkgname package. The .Ar pkgname @@ -351,6 +361,16 @@ installed, and this package must be deinstalled before the package is deinstalled. Multiple .Cm @pkgdep directives may be used if the package depends on multiple other packages. +.It Cm @pkgcfl Ar pkgcflname +Declare a conflict to the +.Ar pkgcflname +package. The +.Ar pkgcflname +package must +.Cm not +be installed if +.Ar pkgname +package gets installed cause they install the same files and thus conflict. .El .Sh SEE ALSO .Xr pkg_add 1 , @@ -360,7 +380,8 @@ directives may be used if the package depends on multiple other packages. .Sh HISTORY The .Nm -command first appeared in FreeBSD. +command first appeared in +.Fx . .Sh AUTHORS .Bl -tag -width indent -compact .It "Jordan Hubbard" diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c index fd72b88d666..a8c4c632d2b 100644 --- a/usr.sbin/pkg_install/create/pl.c +++ b/usr.sbin/pkg_install/create/pl.c @@ -1,7 +1,7 @@ -/* $OpenBSD: pl.c,v 1.3 1998/06/23 23:17:22 millert Exp $ */ +/* $OpenBSD: pl.c,v 1.4 1998/09/07 22:30:14 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: pl.c,v 1.3 1998/06/23 23:17:22 millert Exp $"; +static const char *rcsid = "$OpenBSD: pl.c,v 1.4 1998/09/07 22:30:14 marc Exp $"; #endif /* @@ -27,13 +27,13 @@ static const char *rcsid = "$OpenBSD: pl.c,v 1.3 1998/06/23 23:17:22 millert Exp #include "lib.h" #include "create.h" #include <errno.h> +#include <err.h> +#include <md5.h> /* Check a list for files that require preconversion */ void check_list(char *home, Package *pkg) { - char cmd[FILENAME_MAX]; - char name[FILENAME_MAX]; char *where = home; char *there = NULL; PackingList p = pkg->head; @@ -47,15 +47,18 @@ check_list(char *home, Package *pkg) there = p->name; } else if (p->type == PLIST_FILE) { - cmd[0] = '\0'; + char *cp, name[FILENAME_MAX], buf[33]; + sprintf(name, "%s/%s", there ? there : where, p->name); + if ((cp = MD5File(name, buf)) != NULL) { + PackingList tmp = new_plist_entry(); - if (*cmd) { - if (Verbose) - printf("Uncompressing-> %s\n", cmd); - if (system(cmd)) - barf("%s failed!", cmd); - nuke_suffix(p->name); + tmp->name = copy_string(strconcat("MD5:", cp)); + tmp->type = PLIST_COMMENT; + tmp->next = p->next; + tmp->prev = p; + p->next = tmp; + p = tmp; } } p = p->next; @@ -84,7 +87,7 @@ trylink(const char *from, const char *to) if (where_count > sizeof(STARTSTRING)-1) { \ strcat(where_args, "|tar xpf -"); \ if (system(where_args)) \ - barf("can't invoke tar pipeline"); \ + cleanup(0), errx(2, "can't invoke tar pipeline"); \ memset(where_args, 0, maxargs); \ last_chdir = NULL; \ strcpy(where_args, STARTSTRING); \ @@ -111,7 +114,7 @@ copy_plist(char *home, Package *plist) and sh -c */ where_args = malloc(maxargs); if (!where_args) - barf("can't get argument list space"); + cleanup(0), errx(2, "can't get argument list space"); memset(where_args, 0, maxargs); strcpy(where_args, STARTSTRING); @@ -171,8 +174,8 @@ copy_plist(char *home, Package *plist) p->name); last_chdir = home; } - if (add_count >= maxargs - where_count) - barf("oops, miscounted strings!"); + if (add_count > maxargs - where_count) + cleanup(0), errx(2, "oops, miscounted strings!"); where_count += add_count; } /* @@ -205,8 +208,8 @@ copy_plist(char *home, Package *plist) " -C %s %s", mythere ? mythere : where, p->name); - if (add_count >= maxargs - where_count) - barf("oops, miscounted strings!"); + if (add_count > maxargs - where_count) + cleanup(0), errx(2, "oops, miscounted strings!"); where_count += add_count; last_chdir = (mythere ? mythere : where); } diff --git a/usr.sbin/pkg_install/delete/main.c b/usr.sbin/pkg_install/delete/main.c index e31df41ae12..6c889f9e44e 100644 --- a/usr.sbin/pkg_install/delete/main.c +++ b/usr.sbin/pkg_install/delete/main.c @@ -1,7 +1,8 @@ -/* $OpenBSD: main.c,v 1.6 1998/04/07 04:17:51 deraadt Exp $ */ +/* $OpenBSD: main.c,v 1.7 1998/09/07 22:30:15 marc Exp $ */ +#include <sys/cdefs.h> #ifndef lint -static char *rcsid = "$OpenBSD: main.c,v 1.6 1998/04/07 04:17:51 deraadt Exp $"; +static char *rcsid = "$OpenBSD: main.c,v 1.7 1998/09/07 22:30:15 marc Exp $"; #endif /* @@ -25,6 +26,7 @@ static char *rcsid = "$OpenBSD: main.c,v 1.6 1998/04/07 04:17:51 deraadt Exp $"; * */ +#include <err.h> #include "lib.h" #include "delete.h" @@ -33,14 +35,14 @@ static char Options[] = "hvDdnfp:"; char *Prefix = NULL; Boolean NoDeInstall = FALSE; Boolean CleanDirs = FALSE; -Boolean Force = FALSE; + +static void usage __P((void)); int main(int argc, char **argv) { int ch, error; char **pkgs, **start; - char *prog_name = argv[0]; pkgs = start = argv; while ((ch = getopt(argc, argv, Options)) != -1) @@ -73,7 +75,7 @@ main(int argc, char **argv) case 'h': case '?': default: - usage(prog_name, NULL); + usage(); break; } @@ -87,31 +89,22 @@ main(int argc, char **argv) /* If no packages, yelp */ if (pkgs == start) - usage(prog_name, "Missing package name(s)"); + warnx("missing package name(s)"), usage(); *pkgs = NULL; if (!Fake && getuid() != 0) - errx(1, "You must be root to delete packages."); + errx(1, "you must be root to delete packages"); if ((error = pkg_perform(start)) != 0) { if (Verbose) - fprintf(stderr, "%d package deletion(s) failed.\n", error); + warnx("%d package deletion(s) failed", error); return error; } 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 [-vDdnf] [-p prefix] pkg ...\n", name); + fprintf(stderr, "usage: pkg_delete [-vDdnf] [-p prefix] pkg-name ...\n"); exit(1); } diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c index 0478d86b566..f973f57e90a 100644 --- a/usr.sbin/pkg_install/delete/perform.c +++ b/usr.sbin/pkg_install/delete/perform.c @@ -1,7 +1,7 @@ -/* $OpenBSD: perform.c,v 1.3 1997/06/17 08:38:03 deraadt Exp $ */ +/* $OpenBSD: perform.c,v 1.4 1998/09/07 22:30:15 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: perform.c,v 1.3 1997/06/17 08:38:03 deraadt Exp $"; +static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1998/09/07 22:30:15 marc Exp $"; #endif /* @@ -24,6 +24,7 @@ static const char *rcsid = "$OpenBSD: perform.c,v 1.3 1997/06/17 08:38:03 deraad * */ +#include <err.h> #include "lib.h" #include "delete.h" @@ -61,33 +62,34 @@ pkg_do(char *pkg) sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, pkg); if (!fexists(LogDir)) { - whinge("No such package '%s' installed.", pkg); + warnx("no such package '%s' installed", pkg); return 1; } if (!getcwd(home, FILENAME_MAX)) - barf("Unable to get current working directory!"); + cleanup(0), errx(2, "unable to get current working directory!"); if (chdir(LogDir) == FAIL) { - whinge("Unable to change directory to %s! Deinstall failed.", LogDir); + warnx("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)" : "" ); + warnx("package `%s' is required by these other packages\n" + "and may not be deinstalled%s:", + pkg, 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); + warnx("cannot open requirements file `%s'", REQUIRED_BY_FNAME); if (!Force) return 1; } sanity_check(LogDir); cfile = fopen(CONTENTS_FNAME, "r"); if (!cfile) { - whinge("Unable to open '%s' file.", CONTENTS_FNAME); + warnx("unable to open '%s' file", CONTENTS_FNAME); return 1; } /* If we have a prefix, add it now */ @@ -96,17 +98,18 @@ pkg_do(char *pkg) read_plist(&Plist, cfile); fclose(cfile); p = find_plist(&Plist, PLIST_CWD); - if (p) - setenv(PKG_PREFIX_VNAME, p->name, 1); - else - unsetenv(PKG_PREFIX_VNAME); + if (!p) { + warnx("package '%s' doesn't have a prefix", pkg); + return 1; + } + setenv(PKG_PREFIX_VNAME, p->name, 1); if (fexists(REQUIRE_FNAME)) { if (Verbose) 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 %s", pkg, - Force ? "." : "- not deleted."); + warnx("package %s fails requirements %s", pkg, + Force ? "" : "- not deleted"); if (!Force) return 1; } @@ -117,22 +120,24 @@ pkg_do(char *pkg) else { vsystem("chmod +x %s", DEINSTALL_FNAME); /* make sure */ if (vsystem("./%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) { - whinge("De-Install script returned error status."); + warnx("deinstall script returned error status"); if (!Force) return 1; } } } if (chdir(home) == FAIL) - barf("Toto! This doesn't look like Kansas anymore!"); + cleanup(0), errx(2, "Toto! This doesn't look like Kansas anymore!"); if (!Fake) { /* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */ if (delete_package(FALSE, CleanDirs, &Plist) == FAIL) - warn("Couldn't entirely delete package (perhaps the packing list is\n" - "incorrectly specified?)\n"); + warnx( + "couldn't entirely delete package (perhaps the packing list is\n" + "incorrectly specified?)"); if (vsystem("%s -r %s", REMOVE_CMD, LogDir)) { - whinge("Couldn't remove log entry in %s, de-install failed.", LogDir); - return 1; + warnx("couldn't remove log entry in %s, deinstall failed", LogDir); + if (!Force) + return 1; } } for (p = Plist.head; p ; p = p->next) { @@ -151,13 +156,16 @@ static void sanity_check(char *pkg) { if (!fexists(CONTENTS_FNAME)) - barf("Installed package %s has no %s file!", pkg, CONTENTS_FNAME); + cleanup(0), errx(2, "installed package %s has no %s file!", + pkg, CONTENTS_FNAME); } void cleanup(int sig) { /* Nothing to do */ + if(sig) /* in case this is ever used as a signal handler */ + exit(1); } static void @@ -174,21 +182,21 @@ undepend(PackingList p, char *pkgname) p->name, REQUIRED_BY_FNAME); fp = fopen(fname, "r"); if (fp == NULL) { - whinge("Couldn't open dependency file `%s'", fname); + warnx("couldn't open dependency file `%s'", fname); return; } sprintf(ftmp, "%s.XXXXXXXXXX", fname); s = mkstemp(ftmp); if (s == -1) { fclose(fp); - whinge("Couldn't open temp file `%s'", ftmp); + warnx("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); + warnx("couldn't fdopen temp file `%s'", ftmp); remove(ftmp); return; } @@ -200,18 +208,18 @@ undepend(PackingList p, char *pkgname) } (void) fclose(fp); if (fchmod(s, 0644) == FAIL) { - whinge("Error changing permission of temp file `%s'", ftmp); + warnx("error changing permission of temp file `%s'", ftmp); fclose(fpwr); remove(ftmp); return; } if (fclose(fpwr) == EOF) { - whinge("Error closing temp file `%s'", ftmp); + warnx("error closing temp file `%s'", ftmp); remove(ftmp); return; } if (rename(ftmp, fname) == -1) - warn("Error renaming `%s' to `%s'", ftmp, fname); + warn("error renaming `%s' to `%s'", ftmp, fname); remove(ftmp); /* just in case */ return; } diff --git a/usr.sbin/pkg_install/delete/pkg_delete.1 b/usr.sbin/pkg_install/delete/pkg_delete.1 index 2009bbf6714..44b20bf25af 100644 --- a/usr.sbin/pkg_install/delete/pkg_delete.1 +++ b/usr.sbin/pkg_install/delete/pkg_delete.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_delete.1,v 1.2 1996/10/08 01:21:02 michaels Exp $ +.\" $OpenBSD: pkg_delete.1,v 1.3 1998/09/07 22:30:15 marc Exp $ .\" .\" FreeBSD install - a package for the installation and maintainance .\" of non-core utilities. @@ -15,14 +15,14 @@ .\" Jordan K. Hubbard .\" .\" -.\" @(#)pkg_delete.1 +.\" from FreeBSD: @(#)pkg_delete.1 .\" .Dd November 25, 1994 .Dt pkg_delete 1 .Os .Sh NAME .Nm pkg_delete -.Nd a utility for deleting previously installed software package distributions. +.Nd a utility for deleting previously installed software package distributions .Sh SYNOPSIS .Nm .Op Fl vDdnf @@ -64,28 +64,24 @@ command to examine the installed package control files. .Ef .Sh OPTIONS -The following command line options are supported. +The following command line options are supported: .Bl -tag -width indent .It Ar pkg-name ... The named packages are deinstalled. .It Fl v -Turns on verbose output. -.Em "Optional." +Turn on verbose output. .It Fl D If a deinstallation script exists for a given package, do not execute it. -.Em "Optional." .It Fl n Don't actually deinstall a package, just report the steps that would be taken if it were. -.Em "Optional." .It Fl p Ar prefix -Sets +Set .Ar prefix as the directory in which to delete files from any installed packages which do not explicitly set theirs. For most packages, the prefix will be set automatically to the installed location by .Xr pkg_add 1 . -.Em "Optional." .It Fl d Remove empty directories created by file cleanup. By default, only files/directories explicitly listed in a package's contents (either as @@ -95,11 +91,9 @@ directive) will be removed at deinstallation time. This option tells .Nm to also remove any directories that were emptied as a result of removing the package. -.Em "Optional." .It Fl f Force removal of the package, even if a dependency is recorded or the deinstall or require script fails. -.Em "Optional." .El .Pp @@ -129,7 +123,7 @@ then this is executed first as (where .Ar pkg-name is the name of the package in question and -.I DEINSTALL +.Ar DEINSTALL is a keyword denoting that this is a deinstallation) to see whether or not deinstallation should continue. A non-zero exit status means no, unless the diff --git a/usr.sbin/pkg_install/info/main.c b/usr.sbin/pkg_install/info/main.c index 2246465b677..f3598cbcf61 100644 --- a/usr.sbin/pkg_install/info/main.c +++ b/usr.sbin/pkg_install/info/main.c @@ -1,7 +1,7 @@ -/* $OpenBSD: main.c,v 1.9 1998/04/07 04:17:52 deraadt Exp $ */ +/* $OpenBSD: main.c,v 1.10 1998/09/07 22:30:15 marc Exp $ */ #ifndef lint -static char *rcsid = "$OpenBSD: main.c,v 1.9 1998/04/07 04:17:52 deraadt Exp $"; +static char *rcsid = "$OpenBSD: main.c,v 1.10 1998/09/07 22:30:15 marc Exp $"; #endif /* @@ -25,24 +25,26 @@ static char *rcsid = "$OpenBSD: main.c,v 1.9 1998/04/07 04:17:52 deraadt Exp $"; * */ +#include <err.h> #include "lib.h" #include "info.h" -static char Options[] = "acdDe:fikrRpLqImvhl:"; +static char Options[] = "acDde:fIikLl:mpqRrvh"; int Flags = 0; Boolean AllInstalled = FALSE; Boolean Quiet = FALSE; -char *InfoPrefix = ""; -char PlayPen[FILENAME_MAX]; -char *CheckPkg = NULL; +char *InfoPrefix = ""; +char PlayPen[FILENAME_MAX]; +char *CheckPkg = NULL; + +static void usage __P((void)); int main(int argc, char **argv) { int ch; char **pkgs, **start; - char *prog_name = argv[0]; pkgs = start = argv; while ((ch = getopt(argc, argv, Options)) != -1) @@ -51,37 +53,30 @@ main(int argc, char **argv) AllInstalled = TRUE; break; - case 'v': - Verbose = TRUE; - /* Reasonable definition of 'everything' */ - Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL | - SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE; - break; - - case 'I': - Flags |= SHOW_INDEX; - break; - - case 'p': - Flags |= SHOW_PREFIX; - break; - case 'c': Flags |= SHOW_COMMENT; break; + case 'D': + Flags |= SHOW_DISPLAY; + break; + case 'd': Flags |= SHOW_DESC; break; - case 'D': - Flags |= SHOW_DISPLAY; + case 'e': + CheckPkg = optarg; break; case 'f': Flags |= SHOW_PLIST; break; + case 'I': + Flags |= SHOW_INDEX; + break; + case 'i': Flags |= SHOW_INSTALL; break; @@ -90,76 +85,78 @@ main(int argc, char **argv) Flags |= SHOW_DEINSTALL; break; - case 'r': - Flags |= SHOW_REQUIRE; - break; - - case 'R': - Flags |= SHOW_REQBY; - break; - case 'L': Flags |= SHOW_FILES; break; + case 'l': + InfoPrefix = optarg; + break; + case 'm': Flags |= SHOW_MTREE; break; - case 'l': - InfoPrefix = optarg; + case 'p': + Flags |= SHOW_PREFIX; break; case 'q': Quiet = TRUE; break; - case 't': - strncpy(PlayPen, optarg, FILENAME_MAX); + case 'R': + Flags |= SHOW_REQBY; break; - case 'e': - CheckPkg = optarg; + case 'r': + Flags |= SHOW_REQUIRE; + break; + + case 'v': + Verbose = TRUE; + /* Reasonable definition of 'everything' */ + Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL | + SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE; break; case 'h': case '?': default: - usage(prog_name, NULL); - break; + usage(); + /* NOTREACHED */ } argc -= optind; argv += optind; + if (argc == 0 && !Flags) { + /* No argument or flags specified - assume -Ia */ + Flags = SHOW_INDEX; + AllInstalled = TRUE; + } + + /* Set some reasonable defaults */ + if (!Flags) + Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY; + /* Get all the remaining package names, if any */ while (*argv) *pkgs++ = *argv++; - /* Set some reasonable defaults */ - if (!Flags) { - Flags |= SHOW_INDEX; - if (pkgs == start) - AllInstalled = TRUE; - } + /* If no packages, yelp */ + if (pkgs == start && !AllInstalled && !CheckPkg) + warnx("missing package name(s)"), usage(); *pkgs = NULL; return pkg_perform(start); } -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 [-a] [-cdDikrRpLqImv] [-e package] [-l prefix] pkg ...\n", - name); + fprintf(stderr, "%s\n%s\n%s\n", + "usage: pkg_info [-cDdfIikLmpqRrvh] [-e package] [-l prefix]", + " pkg-name [pkg-name ...]", + " pkg_info -a [flags]"); exit(1); } diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c index ab042c59ecf..6f288bcd7f8 100644 --- a/usr.sbin/pkg_install/info/perform.c +++ b/usr.sbin/pkg_install/info/perform.c @@ -1,7 +1,7 @@ -/* $OpenBSD: perform.c,v 1.3 1997/12/14 09:42:19 gene Exp $ */ +/* $OpenBSD: perform.c,v 1.4 1998/09/07 22:30:15 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: perform.c,v 1.3 1997/12/14 09:42:19 gene Exp $"; +static const char *rcsid = "$OpenBSD: perform.c,v 1.4 1998/09/07 22:30:15 marc Exp $"; #endif /* @@ -27,186 +27,355 @@ static const char *rcsid = "$OpenBSD: perform.c,v 1.3 1997/12/14 09:42:19 gene E #include "lib.h" #include "info.h" +#include <sys/types.h> +#include <sys/stat.h> + +#include <err.h> #include <signal.h> +#include <dirent.h> +#include <fnmatch.h> +#include <ctype.h> -static int pkg_do(char *); +static char *Home; -int -pkg_perform(char **pkgs) +static int +pkg_do(char *pkg) { - int i, err_cnt = 0; - char *tmp; - - signal(SIGINT, cleanup); - - tmp = getenv(PKG_DBDIR); - if (!tmp) - tmp = DEF_LOG_DIR; - /* Overriding action? */ - if (AllInstalled || CheckPkg) { - if (isdir(tmp)) { - DIR *dirp; - struct dirent *dp; - - dirp = opendir(tmp); - if (dirp) { - for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { - if (CheckPkg) { - if (!strcmp(dp->d_name, CheckPkg)) - return 0; + Boolean installed = FALSE, isTMP = FALSE; + char log_dir[FILENAME_MAX]; + char fname[FILENAME_MAX]; + Package plist; + FILE *fp; + struct stat sb; + char *cp = NULL; + int code = 0; + + if (isURL(pkg)) { + if ((cp = fileGetURL(NULL, pkg)) != NULL) { + strcpy(fname, cp); + isTMP = TRUE; + } + } else if (fexists(pkg) && isfile(pkg)) { + int len; + + if (*pkg != '/') { + if (!getcwd(fname, FILENAME_MAX)) + upchuck("getcwd"); + len = strlen(fname); + snprintf(&fname[len], FILENAME_MAX - len, "/%s", pkg); + } else + strcpy(fname, pkg); + cp = fname; + } else { + if ((cp = fileFindByPath(NULL, pkg)) != NULL) + strncpy(fname, cp, FILENAME_MAX); + } + if (cp) { + if (isURL(pkg)) { + /* file is already unpacked by fileGetURL() */ + strcpy(PlayPen, cp); + } else { + /* + * Apply a crude heuristic to see how much space the package will + * take up once it's unpacked. I've noticed that most packages + * compress an average of 75%, but we're only unpacking the + files so + * be very optimistic. + */ + if (stat(fname, &sb) == FAIL) { + warnx("can't stat package file '%s'", fname); + code = 1; + goto bail; + } + Home = make_playpen(PlayPen, sb.st_size / 2); + if (unpack(fname, "+*")) { + warnx("error during unpacking, no info for '%s' available", pkg); + code = 1; + goto bail; } - else - err_cnt += pkg_do(dp->d_name); - } - } - (void)closedir(dirp); - if (CheckPkg) - return 1; - } - else - ++err_cnt; - } else if (CheckPkg) - return 1; /* no dir -> not installed! */ - - } - for (i = 0; pkgs[i]; i++) - err_cnt += pkg_do(pkgs[i]); - return err_cnt; + } + } + /* + * It's not an ininstalled package, try and find it among the + * installed + */ + else { + char *tmp; + + sprintf(log_dir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + pkg); + if (!fexists(log_dir)) { + warnx("can't find package `%s' installed or in a file!", pkg); + return 1; + } + if (chdir(log_dir) == FAIL) { + warnx("can't change directory to '%s'!", log_dir); + return 1; + } + installed = TRUE; + } + + /* Suck in the contents list */ + plist.head = plist.tail = NULL; + fp = fopen(CONTENTS_FNAME, "r"); + if (!fp) { + warnx("unable to open %s file", CONTENTS_FNAME); + code = 1; + goto bail; + } + /* If we have a prefix, add it now */ + read_plist(&plist, fp); + fclose(fp); + + /* + * Index is special info type that has to override all others to make + * any sense. + */ + if (Flags & SHOW_INDEX) { + char tmp[FILENAME_MAX]; + + snprintf(tmp, FILENAME_MAX, "%-19s ", pkg); + show_index(tmp, COMMENT_FNAME); + } else { + /* Start showing the package contents */ + if (!Quiet) + 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) + show_files("Files:\n", &plist); + if (!Quiet) + puts(InfoPrefix); + } + free_plist(&plist); +bail: + leave_playpen(Home); + if (isTMP) + unlink(fname); + return code; +} + +/* use fnmatch to do a glob-style match */ +/* returns 0 if found, 1 if not (1) */ +static int +globmatch(char *pkgspec, char *dbdir, int quiet) +{ + /* Using glob-match */ + struct dirent *dp; + int found; + DIR *dirp; + + found = 0; + if ((dirp = opendir(dbdir)) == (DIR *) NULL) { + warnx("can't opendir package dir '%s'", dbdir); + return !0; + } + while ((dp = readdir(dirp)) != (struct dirent *) NULL) { + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { + continue; + } + if (fnmatch(pkgspec, dp->d_name, FNM_PERIOD) == 0) { + if (!quiet) + printf("%s\n", dp->d_name); + found = 1; + } + } + closedir(dirp); + return !found; } -static char *Home; +enum { + GT, + GE, + LT, + LE +}; +/* compare two dewey decimal numbers */ static int -pkg_do(char *pkg) +deweycmp(char *a, int op, char *b) { - Boolean installed = FALSE, isTMP = FALSE; - char log_dir[FILENAME_MAX]; - char fname[FILENAME_MAX]; - Package plist; - FILE *fp; - struct stat sb; - char *cp = NULL; - int code = 0; - - if (isURL(pkg)) { - if ((cp = fileGetURL(NULL, pkg)) != NULL) { - strncpy(fname, cp, FILENAME_MAX); - isTMP = TRUE; + int ad; + int bd; + int cmp; + + for (;;) { + if (*a == 0 && *b == 0) { + cmp = 0; + break; + } + ad = bd = 0; + for ( ; *a && *a != '.' ; a++) { + ad = (ad * 10) + (*a - '0'); + } + for ( ; *b && *b != '.' ; b++) { + bd = (bd * 10) + (*b - '0'); + } + if ((cmp = ad - bd) != 0) { + break; + } + if (*a == '.') { + a++; + } + if (*b == '.') { + b++; + } } - } - else if (fexists(pkg) && isfile(pkg)) { - int len; - - if (*pkg != '/') { - if (!getcwd(fname, FILENAME_MAX)) - upchuck("getcwd"); - len = strlen(fname); - snprintf(&fname[len], FILENAME_MAX - len, "/%s", pkg); + return (op == GE) ? cmp >= 0 : (op == GT) ? cmp > 0 : (op == LE) ? cmp <= 0 : cmp < 0; +} + +/* match on a relation against dewey decimal numbers */ +/* returns 0 if found, 1 if not (!) */ +static int +deweymatch(char *name, int op, char *ver, char *dbdir, int quiet) +{ + struct dirent *dp; + char *cp; + DIR *dirp; + int ret; + int n; + + n = strlen(name); + ret = 1; + if ((dirp = opendir(dbdir)) == (DIR *) NULL) { + warnx("can't opendir package dir '%s'", dbdir); + return 1; } - else - strncpy(fname, pkg, FILENAME_MAX); - cp = fname; - } - else { - if ((cp = fileFindByPath(NULL, pkg)) != NULL) - strncpy(fname, cp, FILENAME_MAX); - } - if (cp) { - /* - * Apply a crude heuristic to see how much space the package will - * take up once it's unpacked. I've noticed that most packages - * compress an average of 75%, but we're only unpacking the + files so - * be very optimistic. - */ - if (stat(fname, &sb) == FAIL) { - whinge("Can't stat package file '%s'.", fname); - code = 1; - goto bail; + while ((dp = readdir(dirp)) != (struct dirent *) NULL) { + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { + continue; + } + if ((cp = strrchr(dp->d_name, '-')) != (char *) NULL) { + if (strncmp(dp->d_name, name, cp - dp->d_name) == 0 && n == cp - dp->d_name) { + if (deweycmp(cp + 1, op, ver)) { + if (!quiet) + printf("%s\n", dp->d_name); + ret = 0; + } + } + } } - Home = make_playpen(PlayPen, sb.st_size / 2); - if (unpack(fname, "+*")) { - whinge("Error during unpacking, no info for '%s' available.", pkg); - code = 1; - goto bail; + closedir(dirp); + return ret; +} + +/* do a match on a package pattern in dbdir */ +/* returns 0 if found, 1 if not (!) */ +static int +matchname(char *pkgspec, char *dbdir, int quiet) +{ + struct stat st; + char buf[FILENAME_MAX]; + char *sep; + char *last; + char *alt; + char *cp; + int error; + int cnt; + int ret; + + if ((sep = strchr(pkgspec, '{')) != (char *) NULL) { + /* emulate csh-type alternates */ + (void) strncpy(buf, pkgspec, sep - pkgspec); + alt = &buf[sep - pkgspec]; + for (last = NULL, cnt = 0, cp = sep ; *cp && !last ; cp++) { + if (*cp == '{') { + cnt++; + } else if (*cp == '}' && --cnt == 0 && last == NULL) { + last = cp + 1; + } + } + if (cnt != 0) { + warnx("Malformed alternate `%s'", pkgspec); + return 1; + } + for (ret = 1, cp = sep + 1 ; *sep != '}' ; cp = sep + 1) { + for (cnt = 0, sep = cp ; cnt > 0 || (cnt == 0 && *sep != '}' && *sep != ',') ; sep++) { + if (*sep == '{') { + cnt++; + } else if (*sep == '}') { + cnt--; + } + } + (void) snprintf(alt, sizeof(buf) - (alt - buf), "%.*s%s", (int)(sep - cp), cp, last); + if (matchname(buf, dbdir, quiet) == 0) { + ret = 0; + } + } + return ret; } - } - /* It's not an ininstalled package, try and find it among the installed */ - else { - char *tmp; - - sprintf(log_dir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, - pkg); - if (!fexists(log_dir)) { - whinge("Can't find package `%s' installed or in a file!", pkg); - return 1; + if ((sep = strpbrk(pkgspec, "<>")) != (char *) NULL) { + /* perform relational dewey match on version number */ + (void) snprintf(buf, sizeof(buf), "%.*s", (int)(sep - pkgspec), pkgspec); + cnt = (*sep == '>') ? (*(sep + 1) == '=') ? GE : GT : (*(sep + 1) == '=') ? LE : LT; + cp = (cnt == GE || cnt == LE) ? sep + 2 : sep + 1; + return deweymatch(buf, cnt, cp, dbdir, quiet); } - if (chdir(log_dir) == FAIL) { - whinge("Can't change directory to '%s'!", log_dir); - return 1; + if (strpbrk(pkgspec, "*?[]") != (char *) NULL) { + return globmatch(pkgspec, dbdir, quiet); } - installed = TRUE; - } - - /* Suck in the contents list */ - plist.head = plist.tail = NULL; - fp = fopen(CONTENTS_FNAME, "r"); - if (!fp) { - whinge("Unable to open %s file.", CONTENTS_FNAME); - code = 1; - goto bail; - } - /* If we have a prefix, add it now */ - read_plist(&plist, fp); - fclose(fp); - - /* - * Index is special info type that has to override all others to make - * any sense. - */ - if (Flags & SHOW_INDEX) { - char tmp[FILENAME_MAX]; - - snprintf(tmp, FILENAME_MAX, "%-19s ", pkg); - show_index(tmp, COMMENT_FNAME); - } - else { - /* Start showing the package contents */ - if (!Quiet) - 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) - show_files("Files:\n", &plist); - if (!Quiet) - puts(InfoPrefix); - } - free_plist(&plist); - bail: - leave_playpen(Home); - if (isTMP) - unlink(fname); - return code; + /* No shell meta character given - simple check */ + (void) snprintf(buf, sizeof(buf), "%s/%s", dbdir, pkgspec); + error = (lstat(buf, &st) < 0); + if (!error && !quiet) + printf("%s\n", pkgspec); + return error; } void cleanup(int sig) { - leave_playpen(Home); + leave_playpen(Home); + exit(1); +} + +int +pkg_perform(char **pkgs) +{ + int i, err_cnt = 0; + char *tmp; + + signal(SIGINT, cleanup); + + tmp = getenv(PKG_DBDIR); + if (!tmp) + tmp = DEF_LOG_DIR; + /* Overriding action? */ + if (CheckPkg) { + return matchname(CheckPkg, tmp, Quiet); + } else if (AllInstalled) { + struct dirent *dp; + DIR *dirp; + + if (!(isdir(tmp) || islinktodir(tmp))) + return 1; + if ((dirp = opendir(tmp)) != (DIR *) NULL) { + while ((dp = readdir(dirp)) != (struct dirent *) NULL) { + if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { + err_cnt += pkg_do(dp->d_name); + } + } + (void) closedir(dirp); + } + } else { + for (i = 0; pkgs[i]; i++) { + err_cnt += pkg_do(pkgs[i]); + } + } + return err_cnt; } diff --git a/usr.sbin/pkg_install/info/pkg_info.1 b/usr.sbin/pkg_install/info/pkg_info.1 index 4da127b855b..c937e751770 100644 --- a/usr.sbin/pkg_install/info/pkg_info.1 +++ b/usr.sbin/pkg_install/info/pkg_info.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg_info.1,v 1.2 1996/10/08 01:21:03 michaels Exp $ +.\" $OpenBSD: pkg_info.1,v 1.3 1998/09/07 22:30:16 marc Exp $ .\" .\" FreeBSD install - a package for the installation and maintainance .\" of non-core utilities. @@ -17,103 +17,153 @@ .\" .\" @(#)pkg_info.1 .\" -.Dd November 25, 1994 -.Dt pkg_info 1 -.Os +.Dd August 22, 1998 +.Dt PKG_INFO 1 +.Os FreeBSD .Sh NAME .Nm pkg_info -.Nd a utility for displaying information on software packages. +.Nd a utility for displaying information on software packages .Sh SYNOPSIS .Nm pkg_info -.Op Fl cdDikrRpLqImv +.Op Fl cDdfIikLmpqRrvh .Op Fl e Ar package .Op Fl l Ar prefix .Ar pkg-name [pkg-name ...] .Nm pkg_info -.Fl a -.Op Ar flags +.Op Fl a Ar flags .Sh DESCRIPTION The .Nm -command is used to dump out information for packages, either packed up in -files or already installed on the system -with the +command is used to dump out information for packages, which may be either +packed up in files or already installed on the system with the .Xr pkg_create 1 command. -.Sh OPTIONS -The following command line options are supported. +.Pp +The +.Ar pkg-name +may be the name of an installed package, the pathname to a package +distribution file, or a URL to an ftp-available package. +.Pp +The following command-line options are supported: .Bl -tag -width indent -.It Ar pkg-name ... -The named packages are described. A package name may either be the name of -an installed package, the pathname to a package distribution file or a -URL to an ftp available package. .It Fl a -Show all currently installed packages. -.It Fl v -Turns on verbose output. -.It Fl p -Show the installation prefix for each package. -.It Fl q -Be ``quiet'' in emitting report headers and such, just dump the -raw info (basically, assume a non-human reading). +Show information for all currently installed packages. .It Fl c -Show the comment (one liner) field for each package. -.It Fl d -Show the long description field for each package. +Show the one-line comment field for each package. .It Fl D -Show the install-message file for each package. +Show the install-message file (if any) for each package. +.It Fl d +Show the long-description field for each package. +.It Fl e Ar pkg-name +If the package identified by +.Ar pkg-name +is currently installed, return 0, otherwise return 1. +If the given pkg-name contains a +shell metacharacter, it will be matched against all installed +packages using +.Xr fnmatch 3 , +and any packages found installed are printed to stdout, one name per +line. +.Xr csh 1 +style {,} alternates have also been implemented. +Dewey decimal numbers can also be matched in a relational manner, +using the +.Pa >=, <=, > +and +.Pa < +operators. +For example, +.Pa pkg_info -e 'name>=1.3' +will match versions 1.3 and later of the +.Pa name +package. +This printing can be turned off using the +.Fl q +option. +This option +allows you to test for the presence of another (perhaps +prerequisite) package from a script. .It Fl f Show the packing list instructions for each package. +.It Fl I +Show the index entry for each package. .It Fl i Show the install script (if any) for each package. .It Fl k Show the de-install script (if any) for each package. -.It Fl r -Show the requirements script (if any) for each package. -.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. -.It Fl e Ar pkg-name -If the package identified by -.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. .It Fl l Ar str -Prefix each information catagory header (see +Prefix each information category header (see .Fl q ) shown with .Ar str . -This is primarily of use to front-end programs who want to request a +This is primarily of use to front-end programs that 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. -.It Fl t Ar template -Use -.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 -.Pa /tmp -directory is limited. Be sure to leave some number of `X' characters -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 -.Pa /tmp -indeed to overflow it. -.Ed +.It Fl m +Show the mtree file (if any) for each package. +.It Fl p +Show the installation prefix for each package. +.It Fl q +Be ``quiet'' in emitting report headers and such, just dump the +raw info (basically, assume a non-human reading). +.It Fl R +Show which packages are required by each package. +.It Fl r +Show the requirements script (if any) for each package. +.It Fl v +Turn on verbose output. +.El +.Sh ENVIRONMENT +.Bl -tag -width PKG_DBDIR +.It Ev PKG_DBDIR +The standard package database directory, +.Pa /var/db/pkg , +can be overridden by specifying an alternative directory in the +.Ev PKG_DBDIR +environment variable. +.It Ev PKG_PATH +This can be used to specify a colon-separated list of paths to search for +package files. The current directory is always searched first, even if +.Ev PKG_PATH +is set. If +.Ev PKG_PATH +is used, the suffix +.Pa .tgz +is automatically appended to the +.Ar pkg-name , +whereas searching in the current directory uses +.Ar pkg-name +literally. +.It Ev PKG_TMPDIR , Ev TMPDIR +These are tried in turn (if set) as candidate directories in which +to create a ``staging area'' for any files extracted by +.Nm +from package files. If neither +.Ev PKG_TMPDIR +nor +.Ev TMPDIR +yields a suitable scratch directory, +.Pa /var/tmp , +.Pa /tmp , +and +.Pa /usr/tmp +are tried in turn. Note that +.Pa /usr/tmp +may be created, if it doesn't already exist. +.Pp +Since +.Nm +requires very little information to be extracted from any package +files examined, it is unlikely that these environment variables would +ever need to be used to work around limited available space in the +default locations. +.El .Sh TECHNICAL DETAILS Package info is either extracted from package files named on the command line, or from already installed package information diff --git a/usr.sbin/pkg_install/info/show.c b/usr.sbin/pkg_install/info/show.c index 464e3532896..35a21dd64b1 100644 --- a/usr.sbin/pkg_install/info/show.c +++ b/usr.sbin/pkg_install/info/show.c @@ -1,7 +1,7 @@ -/* $OpenBSD: show.c,v 1.2 1996/06/04 08:43:40 niklas Exp $ */ +/* $OpenBSD: show.c,v 1.3 1998/09/07 22:30:16 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: show.c,v 1.2 1996/06/04 08:43:40 niklas Exp $"; +static const char *rcsid = "$OpenBSD: show.c,v 1.3 1998/09/07 22:30:16 marc Exp $"; #endif /* @@ -24,6 +24,8 @@ static const char *rcsid = "$OpenBSD: show.c,v 1.2 1996/06/04 08:43:40 niklas Ex * */ +#include <err.h> + #include "lib.h" #include "info.h" @@ -40,7 +42,7 @@ show_file(char *title, char *fname) if (!fp) printf("ERROR: show_file: Can't open '%s' for reading!\n", fname); else { - while (n = fread(line, 1, 1024, fp)) + while ((n = fread(line, 1, 1024, fp)) != 0) fwrite(line, 1, n, stdout); fclose(fp); } @@ -52,13 +54,12 @@ show_index(char *title, char *fname) { FILE *fp; char line[MAXINDEXSIZE+2]; - int i,n; if (!Quiet) printf("%s%s", InfoPrefix, title); fp = fopen(fname, "r"); if (!fp) { - whinge("show_file: Can't open '%s' for reading.", fname); + warnx("show_file: can't open '%s' for reading", fname); return; } if(fgets(line, MAXINDEXSIZE+1, fp)) { @@ -107,6 +108,10 @@ show_plist(char *title, Package *plist, plist_t type) printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name); break; + case PLIST_UNEXEC: + printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name); + break; + case PLIST_CHMOD: printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n", p->name ? p->name : "(clear default)"); @@ -157,7 +162,8 @@ show_plist(char *title, Package *plist, plist_t type) break; default: - barf("Unknown command type %d (%s)\n", p->type, p->name); + cleanup(0); + errx(2, "unknown command type %d (%s)", p->type, p->name); break; } p = p->next; @@ -190,6 +196,9 @@ show_files(char *title, Package *plist) case PLIST_IGNORE: ign = TRUE; break; + + default: + break; } p = p->next; } diff --git a/usr.sbin/pkg_install/lib/exec.c b/usr.sbin/pkg_install/lib/exec.c index 175925c28ed..bf7d614d845 100644 --- a/usr.sbin/pkg_install/lib/exec.c +++ b/usr.sbin/pkg_install/lib/exec.c @@ -1,7 +1,7 @@ -/* $OpenBSD: exec.c,v 1.3 1998/06/23 23:17:20 millert Exp $ */ +/* $OpenBSD: exec.c,v 1.4 1998/09/07 22:30:16 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: exec.c,v 1.3 1998/06/23 23:17:20 millert Exp $"; +static const char *rcsid = "$OpenBSD: exec.c,v 1.4 1998/09/07 22:30:16 marc Exp $"; #endif /* @@ -24,6 +24,7 @@ static const char *rcsid = "$OpenBSD: exec.c,v 1.3 1998/06/23 23:17:20 millert E * */ +#include <err.h> #include "lib.h" /* @@ -42,13 +43,13 @@ vsystem(const char *fmt, ...) maxargs -= 32; /* some slop for the sh -c */ cmd = malloc(maxargs); if (!cmd) { - whinge("vsystem can't alloc arg space"); + warnx("vsystem can't alloc arg space"); return 1; } va_start(args, fmt); - if (vsnprintf(cmd, maxargs, fmt, args) >= maxargs) { - whinge("vsystem args are too long"); + if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) { + warnx("vsystem args are too long"); return 1; } #ifdef DEBUG diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c index ce62da5ee69..8f8ac44328c 100644 --- a/usr.sbin/pkg_install/lib/file.c +++ b/usr.sbin/pkg_install/lib/file.c @@ -1,7 +1,7 @@ -/* $OpenBSD: file.c,v 1.5 1998/04/07 07:11:33 deraadt Exp $ */ +/* $OpenBSD: file.c,v 1.6 1998/09/07 22:30:16 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: file.c,v 1.5 1998/04/07 07:11:33 deraadt Exp $"; +static const char *rcsid = "$OpenBSD: file.c,v 1.6 1998/09/07 22:30:16 marc Exp $"; #endif /* @@ -25,10 +25,17 @@ static const char *rcsid = "$OpenBSD: file.c,v 1.5 1998/04/07 07:11:33 deraadt E */ #include "lib.h" -#include "ftp.h" + +#include <sys/wait.h> + +#include <err.h> +#include <netdb.h> #include <pwd.h> #include <time.h> +FILE * +ftpGetURL(char *url, char *user, char *passwd, int *retcode); + /* Quick check to see if a file exists */ Boolean fexists(char *fname) @@ -45,17 +52,32 @@ isdir(char *fname) { struct stat sb; - if (stat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode)) + if (lstat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode)) return TRUE; else return FALSE; } +/* Check if something is a link to a directory */ +Boolean +islinktodir(char *fname) +{ + struct stat sb; + + if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode)) + if (stat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode)) + return TRUE; /* link to dir! */ + else + return FALSE; /* link to non-dir */ + else + return FALSE; /* non-link */ +} + /* Check to see if file is a dir, and is empty */ Boolean isemptydir(char *fname) { - if (isdir(fname)) { + if (isdir(fname) || islinktodir(fname)) { DIR *dirp; struct dirent *dp; @@ -125,7 +147,7 @@ fileURLHost(char *fname, char *where, int max) /* Don't ever call this on a bad URL! */ fname += strlen("ftp://"); /* Do we have a place to stick our work? */ - if (ret = where) { + if ((ret = where) != NULL) { while (*fname && *fname != '/' && max--) *where++ = *fname++; *where = '\0'; @@ -150,7 +172,7 @@ fileURLFilename(char *fname, char *where, int max) /* Don't ever call this on a bad URL! */ fname += strlen("ftp://"); /* Do we have a place to stick our work? */ - if (ret = where) { + if ((ret = where) != NULL) { while (*fname && *fname != '/') ++fname; if (*fname == '/') { @@ -166,7 +188,6 @@ fileURLFilename(char *fname, char *where, int max) return fname; } -#define HOSTNAME_MAX 64 /* * Try and fetch a file by URL, returning the directory name for where * it's unpacked, if successful. @@ -174,24 +195,20 @@ fileURLFilename(char *fname, char *where, int max) char * fileGetURL(char *base, char *spec) { - char host[HOSTNAME_MAX], file[FILENAME_MAX], dir[FILENAME_MAX]; - char pword[HOSTNAME_MAX + 40], *uname, *cp, *rp, *tmp; + char host[MAXHOSTNAMELEN], file[FILENAME_MAX]; + char pword[MAXHOSTNAMELEN + 40], *uname, *cp, *rp; char fname[FILENAME_MAX]; char pen[FILENAME_MAX]; struct passwd *pw; - FTP_t ftp; + FILE *ftp; pid_t tpid; - int fd, fd2, i, len = 0; - char ch; - time_t start, stop; + int i, status; char *hint; rp = NULL; /* Special tip that sysinstall left for us */ hint = getenv("PKG_ADD_BASE"); if (!isURL(spec)) { - int len; - if (!base && !hint) return NULL; /* We've been given an existing URL (that's known-good) and now we need @@ -209,6 +226,7 @@ fileGetURL(char *base, char *spec) *(cp + 1) = '\0'; strcat(cp, "All/"); strcat(cp, spec); + strcat(cp, ".tgz"); } else return NULL; @@ -221,16 +239,15 @@ fileGetURL(char *base, char *spec) } else strcpy(fname, spec); - ftp = FtpInit(); - cp = fileURLHost(fname, host, HOSTNAME_MAX); + cp = fileURLHost(fname, host, MAXHOSTNAMELEN); if (!*cp) { - whinge("URL `%s' has bad host part!", fname); + warnx("URL `%s' has bad host part!", fname); return NULL; } cp = fileURLFilename(fname, file, FILENAME_MAX); if (!*cp) { - whinge("URL `%s' has bad filename part!", fname); + warnx("URL `%s' has bad filename part!", fname); return NULL; } @@ -240,59 +257,49 @@ fileGetURL(char *base, char *spec) /* Make up a convincing "password" */ pw = getpwuid(getuid()); if (!pw) { - whinge("Can't get user name for ID %d\n.", getuid()); + warnx("can't get user name for ID %d", getuid()); strcpy(pword, "joe@"); } - else - snprintf(pword, HOSTNAME_MAX + 40, "%s@%s", pw->pw_name, host); + else { + char me[MAXHOSTNAMELEN + 1]; - if (Verbose) - printf("Trying to log into %s as %s.\n", host, uname); - FtpOpen(ftp, host, uname, pword); - if (getenv("FTP_ACTIVE_MODE") == NULL) - FtpPassive(ftp, TRUE); - - strcpy(dir, file); - for (i = strlen(dir); i && dir[i] != '/'; i--); - dir[i] = '\0'; - - if (dir[0]) { - if (Verbose) printf("FTP: chdir to %s\n", dir); - FtpChdir(ftp, dir); + gethostname(me, sizeof me); + me[sizeof(me) - 1] = '\0'; + snprintf(pword, sizeof pword, "%s@%s", pw->pw_name, me); } - FtpBinary(ftp, TRUE); - if (Verbose) printf("FTP: trying to get %s\n", basename_of(file)); - tmp = basename_of(file); - if (!strstr(tmp, ".tgz")) - tmp = strconcat(tmp, ".tgz"); - fd = FtpGet(ftp, tmp); - if (fd >= 0) { + if (Verbose) + printf("Trying to fetch %s.\n", fname); + ftp = ftpGetURL(fname, uname, pword, &status); + if (ftp) { pen[0] = '\0'; - if (rp = make_playpen(pen, 0)) { + if ((rp = make_playpen(pen, 0)) != NULL) { + rp=pen; /* XXX - pen is dynamic; make static? */ if (Verbose) printf("Extracting from FTP connection into %s\n", pen); tpid = fork(); if (!tpid) { - dup2(fd, 0); + dup2(fileno(ftp), 0); i = execl("/bin/tar", "tar", Verbose ? "-xzvf" : "-xzf", "-", 0); - if (Verbose) - printf("tar command returns %d status\n", i); exit(i); } else { int pstat; - close(fd); + fclose(ftp); tpid = waitpid(tpid, &pstat, 0); + if (Verbose) + printf("tar command returns %d status\n", WEXITSTATUS(pstat)); } } else printf("Error: Unable to construct a new playpen for FTP!\n"); + fclose(ftp); } else - printf("Error: FTP Unable to get %s\n", basename_of(file)); - FtpEOF(ftp); - FtpClose(ftp); + printf("Error: FTP Unable to get %s: %s\n", + fname, + status ? "Error while performing FTP" : + hstrerror(h_errno)); return rp; } @@ -309,15 +316,16 @@ fileFindByPath(char *base, char *fname) if (base) { strcpy(tmp, base); - cp = strrchr(fname, '/'); + cp = strrchr(tmp, '/'); if (cp) { *cp = '\0'; /* chop name */ - cp = strrchr(fname, '/'); + cp = strrchr(tmp, '/'); } if (cp) { *(cp + 1) = '\0'; strcat(cp, "All/"); strcat(cp, fname); + strcat(cp, ".tgz"); if (fexists(tmp)) return tmp; } @@ -341,20 +349,61 @@ fileGetContents(char *fname) struct stat sb; int fd; - if (stat(fname, &sb) == FAIL) - barf("Can't stat '%s'.", fname); + if (stat(fname, &sb) == FAIL) { + cleanup(0); + errx(2, "can't stat '%s'", fname); + } contents = (char *)malloc(sb.st_size + 1); fd = open(fname, O_RDONLY, 0); - 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 %qd bytes.", fname, sb.st_size); + if (fd == FAIL) { + cleanup(0); + errx(2, "unable to open '%s' for reading", fname); + } + if (read(fd, contents, sb.st_size) != sb.st_size) { + cleanup(0); + errx(2, "short read on '%s' - did not get %qd bytes", + fname, (long long)sb.st_size); + } close(fd); contents[sb.st_size] = '\0'; return contents; } +/* Takes a filename and package name, returning (in "try") the canonical "preserve" + * name for it. + */ +Boolean +make_preserve_name(char *try, int max, char *name, char *file) +{ + int len, i; + + if ((len = strlen(file)) == 0) + return FALSE; + else + i = len - 1; + strncpy(try, file, max); + if (try[i] == '/') /* Catch trailing slash early and save checking in the loop */ + --i; + for (; i; i--) { + if (try[i] == '/') { + try[i + 1]= '.'; + strncpy(&try[i + 2], &file[i + 1], max - i - 2); + break; + } + } + if (!i) { + try[0] = '.'; + strncpy(try + 1, file, max - 1); + } + /* I should probably be called rude names for these inline assignments */ + strncat(try, ".", max -= strlen(try)); + strncat(try, name, max -= strlen(name)); + strncat(try, ".", max--); + strncat(try, "backup", max -= 6); + return TRUE; +} + /* Write the contents of "str" to a file */ void write_file(char *name, char *str) @@ -363,13 +412,20 @@ write_file(char *name, char *str) int len; fp = fopen(name, "w"); - if (!fp) - barf("Can't fopen '%s' for writing.", name); + if (!fp) { + cleanup(0); + errx(2, "cannot fopen '%s' for writing", name); + } len = strlen(str); - if (fwrite(str, 1, len, fp) != len) - barf("Short fwrite on '%s', tried to write %d bytes.", name, len); - if (fclose(fp)) - barf("failure to fclose '%s'.", name); + if (fwrite(str, 1, len, fp) != len) { + cleanup(0); + errx(2, "short fwrite on '%s', tried to write %d bytes", + name, len); + } + if (fclose(fp)) { + cleanup(0); + errx(2, "failure to fclose '%s'", name); + } } void @@ -381,8 +437,10 @@ copy_file(char *dir, char *fname, char *to) snprintf(cmd, FILENAME_MAX, "cp -p -r %s %s", fname, to); else snprintf(cmd, FILENAME_MAX, "cp -p -r %s/%s %s", dir, fname, to); - if (vsystem(cmd)) - barf("Couldn't perform '%s'", cmd); + if (vsystem(cmd)) { + cleanup(0); + errx(2, "could not perform '%s'", cmd); + } } void @@ -394,8 +452,10 @@ move_file(char *dir, char *fname, char *to) snprintf(cmd, FILENAME_MAX, "mv %s %s", fname, to); else snprintf(cmd, FILENAME_MAX, "mv %s/%s %s", dir, fname, to); - if (vsystem(cmd)) - barf("Couldn't perform '%s'", cmd); + if (vsystem(cmd)) { + cleanup(0); + errx(2, "could not perform '%s'", cmd); + } } /* @@ -424,8 +484,10 @@ copy_hierarchy(char *dir, char *fname, Boolean to) #ifdef DEBUG printf("Using '%s' to copy trees.\n", cmd); #endif - if (system(cmd)) - barf("copy_file: Couldn't perform '%s'", cmd); + if (system(cmd)) { + cleanup(0); + errx(2, "copy_file: could not perform '%s'", cmd); + } } /* Unpack a tar file */ @@ -451,7 +513,7 @@ unpack(char *pkg, char *flist) strcpy(args, "z"); strcat(args, "xpf"); if (vsystem("tar %s %s %s", args, pkg, flist ? flist : "")) { - whinge("Tar extract of %s failed!", pkg); + warnx("tar extract of %s failed!", pkg); return 1; } return 0; @@ -515,3 +577,49 @@ format_cmd(char *buf, char *fmt, char *dir, char *name) } *buf = '\0'; } + + +/* This is as ftpGetURL from FreeBSD's ftpio.c, except that it uses + * OpenBSD's ftp command to do all FTP, which will DTRT for proxies, + * etc. + */ +FILE * +ftpGetURL(char *url, char *user, char *passwd, int *retcode) +{ + FILE *ftp; + pid_t pid_ftp; + int p[2]; + + *retcode=0; + + if( pipe(p) < 0){ + *retcode = 1; + return NULL; + } + + pid_ftp = fork(); + if(pid_ftp < 0){ + *retcode = 1; + return NULL; + } + if(pid_ftp == 0){ + /* child */ + dup2(p[1],1); + close(p[1]); + + execl("/usr/bin/ftp","ftp","-V","-o","-",url,NULL); + exit(1); + }else{ + /* parent */ + ftp = fdopen(p[0],"r"); + + close(p[1]); + + if(ftp < 0){ + *retcode = 1; + return NULL; + } + } + + return ftp; +} diff --git a/usr.sbin/pkg_install/lib/global.c b/usr.sbin/pkg_install/lib/global.c index c5137e6bb37..c86f21a7934 100644 --- a/usr.sbin/pkg_install/lib/global.c +++ b/usr.sbin/pkg_install/lib/global.c @@ -1,7 +1,7 @@ -/* $OpenBSD: global.c,v 1.2 1996/06/04 08:43:44 niklas Exp $ */ +/* $OpenBSD: global.c,v 1.3 1998/09/07 22:30:16 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: global.c,v 1.2 1996/06/04 08:43:44 niklas Exp $"; +static const char *rcsid = "$OpenBSD: global.c,v 1.3 1998/09/07 22:30:16 marc Exp $"; #endif /* @@ -30,6 +30,7 @@ static const char *rcsid = "$OpenBSD: global.c,v 1.2 1996/06/04 08:43:44 niklas /* These are global for all utils */ Boolean Verbose = FALSE; Boolean Fake = FALSE; +Boolean Force = FALSE; int AutoAnswer = FALSE; diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h index f09d8228033..15d31a40d28 100644 --- a/usr.sbin/pkg_install/lib/lib.h +++ b/usr.sbin/pkg_install/lib/lib.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lib.h,v 1.1 1996/06/04 07:56:13 niklas Exp $ */ +/* $OpenBSD: lib.h,v 1.2 1998/09/07 22:30:16 marc Exp $ */ /* * FreeBSD install - a package for the installation and maintainance @@ -24,16 +24,17 @@ #define _INST_LIB_LIB_H_ /* Includes */ +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/file.h> + +#include <ctype.h> +#include <dirent.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <unistd.h> -#include <ctype.h> -#include <dirent.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/file.h> /* Macros */ #define SUCCESS (0) @@ -62,27 +63,27 @@ #define PKG_DBDIR "PKG_DBDIR" /* The names of our "special" files */ -#define CONTENTS_FNAME "+CONTENTS" -#define COMMENT_FNAME "+COMMENT" -#define DESC_FNAME "+DESC" -#define INSTALL_FNAME "+INSTALL" -#define DEINSTALL_FNAME "+DEINSTALL" -#define REQUIRE_FNAME "+REQUIRE" +#define CONTENTS_FNAME "+CONTENTS" +#define COMMENT_FNAME "+COMMENT" +#define DESC_FNAME "+DESC" +#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 DISPLAY_FNAME "+DISPLAY" +#define MTREE_FNAME "+MTREE_DIRS" -#define CMD_CHAR '@' /* prefix for extended PLIST cmd */ +#define CMD_CHAR '@' /* prefix for extended PLIST cmd */ /* The name of the "prefix" environment variable given to scripts */ #define PKG_PREFIX_VNAME "PKG_PREFIX" 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_DISPLAY, + PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, PLIST_IGNORE, + PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY, PLIST_PKGDEP, PLIST_MTREE, PLIST_DIR_RM, PLIST_IGNORE_INST, - PLIST_OPTION + PLIST_OPTION, PLIST_PKGCFL }; typedef enum _plist_t plist_t; @@ -109,7 +110,7 @@ void cleanup(int); char *make_playpen(char *, size_t); char *where_playpen(void); void leave_playpen(char *); -size_t min_free(char *); +off_t min_free(char *); /* String */ char *get_dash_string(char **); @@ -123,6 +124,9 @@ char *strconcat(char *, char *); /* File */ Boolean fexists(char *); Boolean isdir(char *); +Boolean islinktodir(char *); +Boolean isemptydir(char *fname); +Boolean isemptyfile(char *fname); Boolean isfile(char *); Boolean isempty(char *); Boolean isURL(char *); @@ -131,6 +135,7 @@ char *fileURLFilename(char *, char *, int); char *fileURLHost(char *, char *, int); char *fileFindByPath(char *, char *); char *fileGetContents(char *); +Boolean make_preserve_name(char *, int, char *, char *); void write_file(char *, char *); void copy_file(char *, char *, char *); void move_file(char *, char *, char *); @@ -156,18 +161,19 @@ void mark_plist(Package *); void csum_plist_entry(char *, PackingList); void add_plist(Package *, plist_t, char *); void add_plist_top(Package *, plist_t, char *); +void delete_plist(Package *pkg, Boolean all, plist_t type, char *name); void write_plist(Package *, FILE *); void read_plist(Package *, FILE *); int plist_cmd(char *, char **); int delete_package(Boolean, Boolean, Package *); /* For all */ -void usage(const char *, const char *, ...); int pkg_perform(char **); /* Externs */ extern Boolean Verbose; extern Boolean Fake; +extern Boolean Force; extern int AutoAnswer; #endif /* _INST_LIB_LIB_H_ */ diff --git a/usr.sbin/pkg_install/lib/msg.c b/usr.sbin/pkg_install/lib/msg.c index 999bfaea477..2c8a839e9e3 100644 --- a/usr.sbin/pkg_install/lib/msg.c +++ b/usr.sbin/pkg_install/lib/msg.c @@ -1,7 +1,7 @@ -/* $OpenBSD: msg.c,v 1.2 1996/06/04 08:43:44 niklas Exp $ */ +/* $OpenBSD: msg.c,v 1.3 1998/09/07 22:30:17 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: msg.c,v 1.2 1996/06/04 08:43:44 niklas Exp $"; +static const char *rcsid = "$OpenBSD: msg.c,v 1.3 1998/09/07 22:30:17 marc Exp $"; #endif /* @@ -25,42 +25,15 @@ static const char *rcsid = "$OpenBSD: msg.c,v 1.2 1996/06/04 08:43:44 niklas Exp * */ +#include <err.h> #include "lib.h" /* Die a relatively simple death */ void -upchuck(const char *err) +upchuck(const char *errstr) { - fprintf(stderr, "Fatal error during execution: "); - perror(err); cleanup(0); - exit(1); -} - -/* Die a more complex death */ -void -barf(const char *err, ...) -{ - va_list args; - - va_start(args, err); - vfprintf(stderr, err, args); - fputc('\n', stderr); - va_end(args); - cleanup(0); - exit(2); -} - -/* Get annoyed about something but don't go to pieces over it */ -void -whinge(const char *err, ...) -{ - va_list args; - - va_start(args, err); - vfprintf(stderr, err, args); - fputc('\n', stderr); - va_end(args); + err(1, "fatal error during execution: %s", errstr); } /* @@ -80,8 +53,10 @@ y_or_n(Boolean def, const char *msg, ...) * collected on stdin */ tty = fopen("/dev/tty", "r"); - if (!tty) - barf("Can't open /dev/tty!\n"); + if (!tty) { + cleanup(0); + errx(1, "can't open /dev/tty!"); + } while (ch != 'Y' && ch != 'N') { vfprintf(stderr, msg, args); if (def) diff --git a/usr.sbin/pkg_install/lib/pen.c b/usr.sbin/pkg_install/lib/pen.c index 31b35e22f5f..893b6bbf60e 100644 --- a/usr.sbin/pkg_install/lib/pen.c +++ b/usr.sbin/pkg_install/lib/pen.c @@ -1,7 +1,7 @@ -/* $OpenBSD: pen.c,v 1.6 1998/04/25 05:09:07 millert Exp $ */ +/* $OpenBSD: pen.c,v 1.7 1998/09/07 22:30:17 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: pen.c,v 1.6 1998/04/25 05:09:07 millert Exp $"; +static const char *rcsid = "$OpenBSD: pen.c,v 1.7 1998/09/07 22:30:17 marc Exp $"; #endif /* @@ -24,6 +24,7 @@ static const char *rcsid = "$OpenBSD: pen.c,v 1.6 1998/04/25 05:09:07 millert Ex * */ +#include <err.h> #include "lib.h" #include <sys/signal.h> #include <sys/param.h> @@ -59,9 +60,11 @@ find_play_pen(char *pen, size_t sz) else if ((stat("/usr/tmp", &sb) == SUCCESS || mkdir("/usr/tmp", 01777) == SUCCESS) && min_free("/usr/tmp") >= sz) strcpy(pen, "/usr/tmp/instmp.XXXXXXXXXX"); else { - barf("Can't find enough temporary space to extract the files, please set\n" - "your PKG_TMPDIR environment variable to a location with at least %d bytes\n" - "free.", sz); + cleanup(0); + errx(2, +"can't find enough temporary space to extract the files, please set your\n" +"PKG_TMPDIR environment variable to a location with at least %lu bytes\n" +"free", (u_long)sz); return NULL; } return pen; @@ -74,29 +77,27 @@ find_play_pen(char *pen, size_t sz) char * make_playpen(char *pen, size_t sz) { - - if (!find_play_pen(pen, sz)) { + if (!find_play_pen(pen, sz)) return NULL; - } + if (!mkdtemp(pen)) { - barf("Can't mkdtemp '%s'.", pen); - return NULL; + cleanup(0); + errx(2, "can't mkdtemp '%s'", pen); } if (chmod(pen, 0755) == FAIL) { - barf("Can't chmod 0755 '%s'.", pen); - return NULL; + cleanup(0); + errx(2, "can't chmod '%s'", pen); } - if (Verbose) { if (sz) - fprintf(stderr, "Requested space: %d bytes, free space: %d bytes in %s\n", (int)sz, min_free(pen), pen); + fprintf(stderr, "Requested space: %lu bytes, free space: %qd bytes in %s\n", (u_long)sz, (long long)min_free(pen), pen); } if (min_free(pen) < sz) { rmdir(pen); - barf("Not enough free space to create: `%s'\n" + cleanup(0); + errx(2, "not enough free space to create '%s'.\n" "Please set your PKG_TMPDIR environment variable to a location\n" - "with more space and\ntry the command again.", pen); - return NULL; + "with more space and\ntry the command again", pen); } if (Current[0]) strcpy(Previous, Current); @@ -104,8 +105,10 @@ make_playpen(char *pen, size_t sz) upchuck("getcwd"); return NULL; } - if (chdir(pen) == FAIL) - barf("Can't chdir to '%s'.", pen); + if (chdir(pen) == FAIL) { + cleanup(0); + errx(2, "can't chdir to '%s'", pen); + } strcpy(Current, pen); return Previous; } @@ -118,11 +121,16 @@ leave_playpen(char *save) /* Don't interrupt while we're cleaning up */ oldsig = signal(SIGINT, SIG_IGN); - if (Previous[0] && chdir(Previous) == FAIL) - barf("Can't chdir back to '%s'.", Previous); - else if (Current[0] && strcmp(Current, Previous)) { + if (Previous[0] && chdir(Previous) == FAIL) { + cleanup(0); + errx(2, "can't chdir back to '%s'", Previous); + } else if (Current[0] && strcmp(Current, Previous)) { + if (strcmp(Current,"/")==0) { + fprintf(stderr,"PANIC: About to rm -rf / (not doing so, aborting)\n"); + abort(); + } if (vsystem("rm -rf %s", Current)) - whinge("Couldn't remove temporary dir '%s'", Current); + warnx("couldn't remove temporary dir '%s'", Current); strcpy(Current, Previous); } if (save) @@ -132,14 +140,14 @@ leave_playpen(char *save) signal(SIGINT, oldsig); } -size_t +off_t min_free(char *tmpdir) { struct statfs buf; if (statfs(tmpdir, &buf) != 0) { - perror("Error in statfs"); + warn("statfs"); return -1; } - return buf.f_bavail * buf.f_bsize; + return (off_t)buf.f_bavail * (off_t)buf.f_bsize; } diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c index b901fc28cdf..e3844ed5721 100644 --- a/usr.sbin/pkg_install/lib/plist.c +++ b/usr.sbin/pkg_install/lib/plist.c @@ -1,6 +1,6 @@ -/* $OpenBSD: plist.c,v 1.3 1997/01/17 07:14:16 millert Exp $ */ +/* $OpenBSD: plist.c,v 1.4 1998/09/07 22:30:17 marc Exp $ */ #ifndef lint -static const char *rcsid = "$OpenBSD: plist.c,v 1.3 1997/01/17 07:14:16 millert Exp $"; +static const char *rcsid = "$OpenBSD: plist.c,v 1.4 1998/09/07 22:30:17 marc Exp $"; #endif /* @@ -24,6 +24,8 @@ static const char *rcsid = "$OpenBSD: plist.c,v 1.3 1997/01/17 07:14:16 millert */ #include "lib.h" +#include <err.h> +#include <md5.h> /* Add an item to a packing list */ void @@ -148,7 +150,7 @@ new_plist_entry(void) PackingList ret; ret = (PackingList)malloc(sizeof(struct _plist)); - bzero(ret, sizeof(struct _plist)); + memset(ret, 0, sizeof(struct _plist)); return ret; } @@ -221,6 +223,8 @@ plist_cmd(char *s, char **arg) return PLIST_DISPLAY; else if (!strcmp(cmd, "pkgdep")) return PLIST_PKGDEP; + else if (!strcmp(cmd, "pkgcfl")) + return PLIST_PKGCFL; else if (!strcmp(cmd, "mtree")) return PLIST_MTREE; else if (!strcmp(cmd, "dirrm")) @@ -239,17 +243,19 @@ read_plist(Package *pkg, FILE *fp) int cmd; while (fgets(pline, FILENAME_MAX, fp)) { - int len = strlen(pline) - 1; + int len = strlen(pline); - while (isspace(pline[len])) - pline[len--] = '\0'; - if (len <= 0) + while (len && isspace(pline[len - 1])) + pline[--len] = '\0'; + if (!len) continue; cp = pline; if (pline[0] == CMD_CHAR) { cmd = plist_cmd(pline + 1, &cp); - if (cmd == FAIL) - barf("Bad command '%s'", pline); + if (cmd == FAIL) { + warnx("Unrecognised PLIST command `%s'", pline); + continue; + } if (*cp == '\0') cp = NULL; } @@ -320,6 +326,10 @@ write_plist(Package *pkg, FILE *fp) fprintf(fp, "%cpkgdep %s\n", CMD_CHAR, plist->name); break; + case PLIST_PKGCFL: + fprintf(fp, "%cpkgcfl %s\n", CMD_CHAR, plist->name); + break; + case PLIST_MTREE: fprintf(fp, "%cmtree %s\n", CMD_CHAR, plist->name); break; @@ -333,7 +343,8 @@ write_plist(Package *pkg, FILE *fp) break; default: - barf("Unknown command type %d (%s)\n", plist->type, plist->name); + cleanup(0); + errx(2, "unknown command type %d (%s)", plist->type, plist->name); break; } plist = plist->next; @@ -349,51 +360,102 @@ write_plist(Package *pkg, FILE *fp) int delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) { - PackingList p = pkg->head; + PackingList p; char *Where = ".", *last_file = ""; Boolean fail = SUCCESS; + Boolean preserve; + char tmp[FILENAME_MAX], *name = NULL; - if (!p) - return FAIL; - while (p) { - if (p->type == PLIST_CWD) { + preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; + for (p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_NAME: + name = p->name; + break; + + case PLIST_IGNORE: + p = p->next; + break; + + case PLIST_CWD: Where = p->name; if (Verbose) printf("Change working directory to %s\n", Where); - } - else if (p->type == PLIST_UNEXEC) { - char cmd[FILENAME_MAX]; + break; - format_cmd(cmd, p->name, Where, last_file); + case PLIST_UNEXEC: + format_cmd(tmp, p->name, Where, last_file); if (Verbose) - printf("Execute `%s'\n", cmd); - if (!Fake && system(cmd)) { - whinge("unexec command for `%s' failed.", cmd); + printf("Execute `%s'\n", tmp); + if (!Fake && system(tmp)) { + warnx("unexec command for `%s' failed", tmp); fail = FAIL; } - } - else if (p->type == PLIST_IGNORE) - p = p->next; - else if (p->type == PLIST_FILE || p->type == PLIST_DIR_RM) { - char full_name[FILENAME_MAX]; + break; - sprintf(full_name, "%s/%s", Where, p->name); - if (isdir(full_name) && p->type == PLIST_FILE) { - warn("Attempting to delete directory `%s' as a file\n" - "This packing list is incorrect - ignoring delete request.\n", full_name); + case PLIST_FILE: + last_file = p->name; + sprintf(tmp, "%s/%s", Where, p->name); + if (isdir(tmp)) { + warnx("attempting to delete directory `%s' as a file\n" + "this packing list is incorrect - ignoring delete request", tmp); } else { + if (p->next && p->next->type == PLIST_COMMENT && !strncmp(p->next->name, "MD5:", 4)) { + char *cp, buf[33]; + + if ((cp = MD5File(tmp, buf)) != NULL) { + /* Mismatch? */ + if (strcmp(cp, p->next->name + 4)) { + if (Verbose) + printf("%s fails original MD5 checksum - %s\n", + tmp, Force ? "deleted anyway." : "not deleted."); + if (!Force) { + fail = FAIL; + continue; + } + } + } + } if (Verbose) - printf("Delete %s %s\n", !isdir(full_name) ? "file" : " directory", full_name); + printf("Delete file %s\n", tmp); + if (!Fake) { + if (delete_hierarchy(tmp, ign_err, nukedirs)) + fail = FAIL; + if (preserve && name) { + char tmp2[FILENAME_MAX]; + + if (make_preserve_name(tmp2, FILENAME_MAX, name, tmp)) { + if (fexists(tmp2)) { + if (rename(tmp2, tmp)) + warn("preserve: unable to restore %s as %s", + tmp2, tmp); + } + } + } + } + } + break; - if (!Fake && delete_hierarchy(full_name, ign_err, p->type == PLIST_DIR_RM ? FALSE : nukedirs)) { - whinge("Unable to completely remove file '%s'", full_name); + case PLIST_DIR_RM: + sprintf(tmp, "%s/%s", Where, p->name); + if (!isdir(tmp)) { + warnx("attempting to delete file `%s' as a directory\n" + "this packing list is incorrect - ignoring delete request", tmp); + } + else { + if (Verbose) + printf("Delete directory %s\n", tmp); + if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) { + warnx("unable to completely remove directory '%s'", tmp); fail = FAIL; } } last_file = p->name; + break; + default: + break; } - p = p->next; } return fail; } @@ -415,14 +477,19 @@ delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) cp1 = cp2 = dir; if (!fexists(dir)) { if (!ign_err) - whinge("%s `%s' doesn't really exist.", isdir(dir) ? "Directory" : "File", dir); - } else if (nukedirs) { + warnx("%s `%s' doesn't really exist", + isdir(dir) ? "directory" : "file", dir); + return !ign_err; + } + else if (nukedirs) { if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir)) return 1; - } else if (isdir(dir)) { + } + else if (isdir(dir)) { if (RMDIR(dir) && !ign_err) return 1; - } else { + } + else { if (REMOVE(dir, ign_err)) return 1; } @@ -434,11 +501,12 @@ delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) *cp2 = '\0'; if (!isemptydir(dir)) return 0; - if (RMDIR(dir) && !ign_err) + if (RMDIR(dir) && !ign_err) { if (!fexists(dir)) - whinge("Directory `%s' doesn't really exist.", dir); + warnx("directory `%s' doesn't really exist", dir); else return 1; + } /* back up the pathname one component */ if (cp2) { cp1 = dir; diff --git a/usr.sbin/pkg_install/tkpkg b/usr.sbin/pkg_install/tkpkg index 7e11719df70..656d90f78ff 100644 --- a/usr.sbin/pkg_install/tkpkg +++ b/usr.sbin/pkg_install/tkpkg @@ -1,32 +1,6 @@ #!/usr/local/bin/wish -f -#$OpenBSD: tkpkg,v 1.1 1996/06/04 07:56:02 niklas Exp $ -# -#$Log: tkpkg,v $ -#Revision 1.1 1996/06/04 07:56:02 niklas -#add package tools from FreeBSD -# -#Revision 1.2 1994/12/06 00:51:21 jkh -#Many of John T. Kohl's patches from NetBSD. Thanks, John! -#Submitted by: jkohl -# -# Revision 1.1 1994/01/06 08:16:20 jkh -# Cleaning house. -# -# Revision 1.1 1993/09/04 17:06:09 jkh -# Added Rich's wish front-end. -# -# Revision 1.6 1993/09/03 23:37:22 rich -# warn user if no tar archives are found in the current directory. -# removed the revision string from the lower text frame. -# -# Revision 1.5 1993/09/03 15:48:04 rich -# glob for .tar.gz, .tar.z and .tar.Z looking for archives -# -# Revision 1.4 1993/08/28 15:53:59 rich -# added version and date info to lower text window. -# -# Revision 1.3 1993/08/28 15:47:12 rich -# filtered out ^Ls in pkg_* output. +#$OpenBSD: tkpkg,v 1.2 1998/09/07 22:30:12 marc Exp $ +# from FreeBSD Id: tkpkg,v 1.4 1997/02/22 16:09:13 peter Exp # # set pkgname "" @@ -57,7 +31,7 @@ scrollbar .f.s -relief sunken -command ".f.t yview" pack append .f .f.s {right filly} .f.t {left expand fill} bind .frame.list <Double-Button-1> \ - {foreach i [selection get] {do_description $i}} + { do_description [selection get] } pack append . .menu {top fill} \ .f {bottom expand fill} \ .frame {bottom expand fill} |