diff options
author | schmonz <schmonz@pkgsrc.org> | 2002-12-20 18:13:52 +0000 |
---|---|---|
committer | schmonz <schmonz@pkgsrc.org> | 2002-12-20 18:13:52 +0000 |
commit | 55c0604b89b34ae6d16219723abcde3111975fed (patch) | |
tree | 78c74b24300afe90e8e1596d6cb82ecb3f530138 | |
parent | c7a5a7d2fb3005ea184ee858e63fdde9c9ce1226 (diff) | |
download | pkgsrc-55c0604b89b34ae6d16219723abcde3111975fed.tar.gz |
Import autoconf'd pkg_install source from
othersrc/bootstrap-pkgsrc/pkg_install into ${FILESDIR}.
Using autoconf greatly simplifies maintenance of this package across
multiple platforms. Placing the extracted source under ${FILESDIR}
will eventually let us use the same source for bootstrapping as
well, though we're not ready for this yet.
65 files changed, 17009 insertions, 0 deletions
diff --git a/pkgtools/pkg_install/files/Makefile.in b/pkgtools/pkg_install/files/Makefile.in new file mode 100644 index 00000000000..9aa6d5409b3 --- /dev/null +++ b/pkgtools/pkg_install/files/Makefile.in @@ -0,0 +1,39 @@ +# $NetBSD: Makefile.in,v 1.1.1.1 2002/12/20 18:13:52 schmonz Exp $ +# Original from FreeBSD, no rcs id. + +all: libdir adddir admindir createdir deletedir infodir + +libdir: + cd lib && ${MAKE} +adddir: + cd add && ${MAKE} +admindir: + cd admin && ${MAKE} +createdir: + cd create && ${MAKE} +deletedir: + cd delete && ${MAKE} +infodir: + cd info && ${MAKE} + +install: all + @MKDIR@ -p @prefix@/sbin + cd add && ${MAKE} install + cd admin && ${MAKE} install + cd create && ${MAKE} install + cd delete && ${MAKE} install + cd info && ${MAKE} install + +clean: + cd lib && ${MAKE} clean + cd add && ${MAKE} clean + cd admin && ${MAKE} clean + cd create && ${MAKE} clean + cd delete && ${MAKE} clean + cd info && ${MAKE} clean + +distclean: clean + rm -f config.log config.status config.cache + rm -f Makefile */Makefile + rm -f lib/lib.h lib/config.h + diff --git a/pkgtools/pkg_install/files/README b/pkgtools/pkg_install/files/README new file mode 100644 index 00000000000..d9690897850 --- /dev/null +++ b/pkgtools/pkg_install/files/README @@ -0,0 +1,18 @@ +# $NetBSD: README,v 1.1.1.1 2002/12/20 18:13:52 schmonz Exp $ +# Original from FreeBSD, no rcs id. + +This is the pkg_install suite of tools for doing maintainance of +software "packages". More documentation is available in the man pages +for each individual command. + +This code was written by Jordan Hubbard for FreeBSD, snatched and +mildly reshaped by John Kohl in NetBSD and the changes taken back into +FreeBSD again by Jordan, who then proceeded to add another couple +of dozen features on top. Whee! :-) + +In another round of enhancements, NetBSD changes were added by +Alistair Crooks and Hubert Feyrer, Thorsten Frueauf and Christian E. +Hopps. + +When making snapshots, please modify PKGTOOLS_VERSION in lib/version.h +to that day's date. diff --git a/pkgtools/pkg_install/files/TODO b/pkgtools/pkg_install/files/TODO new file mode 100644 index 00000000000..9234464024a --- /dev/null +++ b/pkgtools/pkg_install/files/TODO @@ -0,0 +1,16 @@ +To Do +===== +add man page installation + +Done +==== +Do correct GNU Makefile-ish things +make a real mkdtemp thing +get rid of BINDIR +get rid of TAR_CMD +REMOVE_CMD -> RM +RMDIR_CMD -> RMDIR +use MKDIR for mkdir -p uses via vsystem. Use mkdir(2) for all other uses. +add digest files if MD5File not in -lc or -lmd +try it on Darwin +use full pathnames for utilities which are executed by vsystem() diff --git a/pkgtools/pkg_install/files/add/Makefile.in b/pkgtools/pkg_install/files/add/Makefile.in new file mode 100644 index 00000000000..c12c60c41c9 --- /dev/null +++ b/pkgtools/pkg_install/files/add/Makefile.in @@ -0,0 +1,40 @@ +# $NetBSD: Makefile.in,v 1.1.1.1 2002/12/20 18:13:54 schmonz Exp $ +# Original from FreeBSD, no rcs id. + +PREFIX= @prefix@ +INSTALL= @INSTALL@ + +mandir= ${PREFIX}/man +mandircat1= ${mandir}/cat1 + +CC= @CC@ +CCLD= $(CC) +LIBS= @LIBS@ -linstall +CPPFLAGS= @CPPFLAGS@ +DEFS= @DEFS@ -I. -I@srcdir@ -I../lib +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ -L../lib + +LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ +COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) + +PROG= pkg_add + +SRCS= main.c perform.c futil.c extract.c verify.c +OBJS= main.o perform.o futil.o extract.o verify.o + +all: ${PROG} + +${PROG}: ${OBJS} + ${LINK} ${OBJS} ${LIBS} + +.c.o: + $(COMPILE) -c $< -o $@ + +clean: + rm -f ${OBJS} ${PROG} + +install: + ${INSTALL} ${PROG} ${PREFIX}/sbin + ${INSTALL} -m 755 -d ${mandircat1} + ${INSTALL} -m 444 ${PROG}.cat1 ${mandircat1}/${PROG}.1 diff --git a/pkgtools/pkg_install/files/add/add.h b/pkgtools/pkg_install/files/add/add.h new file mode 100644 index 00000000000..6452a2a7e9c --- /dev/null +++ b/pkgtools/pkg_install/files/add/add.h @@ -0,0 +1,48 @@ +/* $NetBSD: add.h,v 1.1.1.1 2002/12/20 18:13:54 schmonz 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 + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the add command. + * + */ + +#ifndef _INST_ADD_H_INCLUDE +#define _INST_ADD_H_INCLUDE + +typedef enum { + NORMAL, MASTER, SLAVE +} add_mode_t; + +extern char *Prefix; +extern Boolean NoInstall; +extern Boolean NoRecord; +extern Boolean Force; +extern char *Mode; +extern char *Owner; +extern char *Group; +extern char *Directory; +extern char *PkgName; +extern char FirstPen[]; +extern add_mode_t AddMode; + +int make_hierarchy(char *); +int extract_plist(char *, package_t *); +void apply_perms(char *, char *); + +#endif /* _INST_ADD_H_INCLUDE */ diff --git a/pkgtools/pkg_install/files/add/extract.c b/pkgtools/pkg_install/files/add/extract.c new file mode 100644 index 00000000000..911dd696ae0 --- /dev/null +++ b/pkgtools/pkg_install/files/add/extract.c @@ -0,0 +1,353 @@ +/* $NetBSD: extract.c,v 1.1.1.1 2002/12/20 18:13:55 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "FreeBSD - Id: extract.c,v 1.17 1997/10/08 07:45:35 charnier Exp"; +#else +__RCSID("$NetBSD: extract.c,v 1.1.1.1 2002/12/20 18:13:55 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the package extraction code for the add module. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" +#include "add.h" + +#define TAR_ARGS " cf - " +#define TARX_CMD "|" TAR_FULLPATHNAME " xpf - -C " + +/* + * This macro is used to determine if the 'where_args' buffer is big enough to add the + * current string (usually a filename) plus some extra commands (the contents of TARX_CMD, and + * the directory name stored in 'Directory'). + * + * The string " 'str'" will be added so we need room for the string plus 3 chars plus the other arguments. + * + * In addition, we will add " 'srt'" to the perm_args buffer so we need to ensure that there is room + * for that. + */ +#define TOOBIG(str) ((strlen(str) + 3 + strlen(TARX_CMD) + strlen(Directory) + where_count >= maxargs) \ + || (strlen(str) + 3 + perm_count >= maxargs)) + +#define PUSHOUT(todir) /* push out string */ \ + if (where_count > sizeof(TAR_FULLPATHNAME) + sizeof(TAR_ARGS)-1) { \ + strcat(where_args, TARX_CMD); \ + strcat(where_args, todir); \ + if (system(where_args)) { \ + cleanup(0); \ + errx(2, "can not invoke %lu byte %s pipeline: %s", \ + (u_long)strlen(where_args), TAR_FULLPATHNAME, \ + where_args); \ + } \ + strcpy(where_args, TAR_FULLPATHNAME TAR_ARGS); \ + where_count = strlen(where_args); \ + } \ + if (perm_count) { \ + apply_perms(todir, perm_args); \ + perm_args[0] = 0; \ + perm_count = 0; \ + } + + +static void +rollback(char *name, char *home, plist_t *start, plist_t *stop) +{ + plist_t *q; + char try[FILENAME_MAX], bup[FILENAME_MAX], *dir; + + dir = home; + for (q = start; q != stop; q = q->next) { + if (q->type == PLIST_FILE) { + (void) snprintf(try, sizeof(try), "%s/%s", dir, q->name); + if (make_preserve_name(bup, sizeof(bup), name, try) && fexists(bup)) { +#ifdef HAVE_CHFLAGS + (void) chflags(try, 0); +#endif + (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; + } + } +} + + +/* + * Return 0 on error, 1 for success. + */ +int +extract_plist(char *home, package_t *pkg) +{ + plist_t *p = pkg->head; + 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) / 2; /* Just use half the argument space */ + where_args = malloc(maxargs); + if (!where_args) { + cleanup(0); + errx(2, "can't get argument list space"); + } + perm_args = malloc(maxargs); + if (!perm_args) { + cleanup(0); + errx(2, "can't get argument list space"); + } + strcpy(where_args, TAR_FULLPATHNAME TAR_ARGS); + /* + * we keep track of how many characters are stored in 'where_args' with 'where_count'. + * Note this doesn't include the trailing null character. + */ + where_count = strlen(where_args); + + perm_args[0] = 0; + /* + * we keep track of how many characters are stored in 'perm__args' with 'perm_count'. + * Note this doesn't include the trailing null character. + */ + perm_count = 0; + + last_chdir = 0; + preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; + + /* Reset the world */ + Owner = NULL; + Group = NULL; + Mode = NULL; + last_file = NULL; + Directory = home; + + /* Open Package Database for writing */ + if (pkgdb_open(0) == -1) { + cleanup(0); + err(1, "can't open pkgdb"); + } + /* Do it */ + while (p) { + char cmd[FILENAME_MAX]; + + switch (p->type) { + case PLIST_NAME: + PkgName = p->name; + if (Verbose) + printf("extract: Package name is %s\n", p->name); + break; + + case PLIST_FILE: + last_file = p->name; + if (Verbose) + printf("extract: %s/%s\n", Directory, p->name); + 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 */ + (void) snprintf(try, sizeof(try), "%s/%s", Directory, p->name); + if (fexists(try)) { +#ifdef HAVE_CHFLAGS + (void) chflags(try, 0); /* XXX hack - if truly immutable, rename fails */ +#endif + if (preserve && PkgName) { + char pf[FILENAME_MAX]; + + if (make_preserve_name(pf, sizeof(pf), 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 0; + } + } + } + } + if (rename(p->name, try) == 0) { + /* note in pkgdb */ + { + char *s, t[FILENAME_MAX]; + int rc; + + (void) snprintf(t, sizeof(t), "%s/%s", Directory, p->name); + + s = pkgdb_retrieve(t); +#ifdef PKGDB_DEBUG + printf("pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ +#endif + if (s) + warnx("Overwriting %s - pkg %s bogus/conflicting?", t, s); + else { + rc = pkgdb_store(t, PkgName); +#ifdef PKGDB_DEBUG + printf("pkgdb_store(\"%s\", \"%s\") = %d\n", t, PkgName, rc); /* pkgdb-debug - HF */ +#endif + + } + } + + /* try to add to list of perms to be changed and run in bulk. */ + if (p->name[0] == '/' || TOOBIG(p->name)) { + PUSHOUT(Directory); + } + /* note, if the following line is modified, TOOBIG must be adjusted accordingly */ + 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 (last_chdir != Directory) { + PUSHOUT(last_chdir); + last_chdir = Directory; + } else if (p->name[0] == '/' || TOOBIG(p->name)) { + PUSHOUT(Directory); + } + /* note, if the following line is modified, TOOBIG must be adjusted accordingly */ + 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; + /* note, if the following line is modified, TOOBIG must be adjusted accordingly */ + 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; + + /* note in pkgdb */ + /* XXX would be better to store in PUSHOUT, but + * that would probably affect too much code I prefer + * not to touch - HF */ + { + char *s, t[FILENAME_MAX], *u; + int rc; + + if (p->name[0] == '/') + u = p->name; + else { + (void) snprintf(t, sizeof(t), "%s/%s", Directory, p->name); + u = t; + } + + s = pkgdb_retrieve(t); +#ifdef PKGDB_DEBUG + printf("pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ +#endif + if (s) + warnx("Overwriting %s - pkg %s bogus/conflicting?", t, s); + else { + rc = pkgdb_store(t, PkgName); +#ifdef PKGDB_DEBUG + printf("pkgdb_store(\"%s\", \"%s\") = %d\n", t, PkgName, rc); /* pkgdb-debug - HF */ +#endif + } + } + } + } + break; + + case PLIST_CWD: + if (Verbose) + printf("extract: CWD to %s\n", p->name); + PUSHOUT(Directory); + if (strcmp(p->name, ".")) { + if (!Fake && make_hierarchy(p->name) == FAIL) { + cleanup(0); + errx(2, "unable to make directory '%s'", p->name); + } + Directory = p->name; + } else + Directory = home; + break; + + case PLIST_CMD: + if (last_file == NULL && strchr(p->name, '%') != NULL) { + cleanup(0); + errx(2, "no last file specified for '%s' command", p->name); + } + format_cmd(cmd, sizeof(cmd), p->name, Directory, last_file); + PUSHOUT(Directory); + if (Verbose) + printf("extract: execute '%s'\n", cmd); + if (!Fake && system(cmd)) + warnx("command '%s' failed", cmd); + break; + + case PLIST_CHMOD: + PUSHOUT(Directory); + Mode = p->name; + break; + + case PLIST_CHOWN: + PUSHOUT(Directory); + Owner = p->name; + break; + + case PLIST_CHGRP: + PUSHOUT(Directory); + Group = p->name; + break; + + case PLIST_COMMENT: + break; + + case PLIST_IGNORE: + p = p->next; + break; + + default: + break; + } + p = p->next; + } + PUSHOUT(Directory); + pkgdb_close(); + free(perm_args); + free(where_args); + return 1; +} diff --git a/pkgtools/pkg_install/files/add/futil.c b/pkgtools/pkg_install/files/add/futil.c new file mode 100644 index 00000000000..2cbbfee9603 --- /dev/null +++ b/pkgtools/pkg_install/files/add/futil.c @@ -0,0 +1,107 @@ +/* $NetBSD: futil.c,v 1.1.1.1 2002/12/20 18:13:55 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: futil.c,v 1.7 1997/10/08 07:45:39 charnier Exp"; +#else +__RCSID("$NetBSD: futil.c,v 1.1.1.1 2002/12/20 18:13:55 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous file access utilities. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" +#include "add.h" + +/* + * Assuming dir is a desired directory name, make it and all intervening + * directories necessary. + */ +int +make_hierarchy(char *dir) +{ + char *cp1, *cp2; + + if (dir[0] == '/') + cp1 = cp2 = dir + 1; + else + cp1 = cp2 = dir; + while (cp2) { + if ((cp2 = strchr(cp1, '/')) != NULL) + *cp2 = '\0'; + if (fexists(dir)) { + if (!(isdir(dir) || islinktodir(dir))) + return FAIL; + } else { + if (mkdir(dir, 0755) < 0) { + return FAIL; + } + apply_perms(NULL, dir); + } + /* Put it back */ + if (cp2) { + *cp2 = '/'; + cp1 = cp2 + 1; + } + } + return SUCCESS; +} + +/* + * Using permission defaults, apply them as necessary + */ +void +apply_perms(char *dir, char *arg) +{ + char *cd_to; + + if (!dir || *arg == '/')/* absolute path? */ + cd_to = "/"; + else + cd_to = dir; + + if (Mode) + if (vsystem("cd %s && %s -R %s %s", cd_to, CHMOD_CMD, Mode, arg)) + warnx("couldn't change modes of '%s' to '%s'", arg, Mode); + if (Owner && Group) { + if (vsystem("cd %s && %s -R %s.%s %s", cd_to, CHOWN_CMD, Owner, Group, arg)) + warnx("couldn't change owner/group of '%s' to '%s.%s'", + arg, Owner, Group); + return; + } + if (Owner) { + if (vsystem("cd %s && %s -R %s %s", cd_to, CHOWN_CMD, Owner, arg)) + warnx("couldn't change owner of '%s' to '%s'", arg, Owner); + return; + } else if (Group) + if (vsystem("cd %s && %s -R %s %s", cd_to, CHGRP_CMD, Group, arg)) + warnx("couldn't change group of '%s' to '%s'", arg, Group); +} diff --git a/pkgtools/pkg_install/files/add/main.c b/pkgtools/pkg_install/files/add/main.c new file mode 100644 index 00000000000..8a4bb49fff9 --- /dev/null +++ b/pkgtools/pkg_install/files/add/main.c @@ -0,0 +1,197 @@ +/* $NetBSD: main.c,v 1.1.1.1 2002/12/20 18:13:55 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char *rcsid = "from FreeBSD Id: main.c,v 1.16 1997/10/08 07:45:43 charnier Exp"; +#else +__RCSID("$NetBSD: main.c,v 1.1.1.1 2002/12/20 18:13:55 schmonz Exp $"); +#endif +#endif +#endif + +/* + * + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the add module. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +#include "lib.h" +#include "add.h" +#include "verify.h" + +static char Options[] = "hVvIRfnp:SMs:t:u"; + +char *Prefix = NULL; +Boolean NoInstall = FALSE; +Boolean NoRecord = FALSE; + +char *Mode = NULL; +char *Owner = NULL; +char *Group = NULL; +char *PkgName = NULL; +char *Directory = NULL; +char FirstPen[FILENAME_MAX]; +add_mode_t AddMode = NORMAL; +int upgrade = 0; + +static void +usage(void) +{ + (void) fprintf(stderr, "%s\n%s\n", + "usage: pkg_add [-hVvInfRMSu] [-t template] [-p prefix]", + " [-s verification-type] pkg-name [pkg-name ...]"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, error=0; + lpkg_head_t pkgs; + struct rlimit rlim; + int rc; + + setprogname(argv[0]); + + while ((ch = getopt(argc, argv, Options)) != -1) { + switch (ch) { + case 'v': + Verbose = TRUE; + break; + + case 'p': + Prefix = optarg; + break; + + case 'I': + NoInstall = TRUE; + break; + + case 'R': + NoRecord = TRUE; + break; + + case 'f': + Force = TRUE; + break; + + case 'n': + Fake = TRUE; + Verbose = TRUE; + break; + + case 's': + set_verification(optarg); + break; + + case 't': + strcpy(FirstPen, optarg); + break; + + case 'S': + AddMode = SLAVE; + break; + + case 'M': + AddMode = MASTER; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case 'u': + upgrade = 1; + break; + case 'h': + case '?': + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + path_create(getenv("PKG_PATH")); + TAILQ_INIT(&pkgs); + + if (AddMode != SLAVE) { + /* Get all the remaining package names, if any */ + for (ch = 0; *argv; ch++, argv++) { + lpkg_t *lpp; + + if (IS_STDIN(*argv)) + lpp = alloc_lpkg("-"); + else + lpp = alloc_lpkg(*argv); + + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } + } else if (!ch) + /* If no packages, yelp */ + warnx("missing package name(s)"), usage(); + else if (ch > 1 && AddMode == MASTER) + warnx("only one package name may be specified with master mode"), + usage(); + + /* Increase # of max. open file descriptors as high as possible */ + rc = getrlimit(RLIMIT_NOFILE, &rlim); + if (rc == -1) { + warn("cannot retrieve max. number of open files resource limit"); + } else { + rlim.rlim_cur = rlim.rlim_max; + rc = setrlimit(RLIMIT_NOFILE, &rlim); + if (rc == -1) { + warn("cannot increase max. number of open files resource limit, try 'ulimit'"); + } else { + if (Verbose) + printf("increasing RLIMIT_NOFILE to max. %ld open files\n", (long)rlim.rlim_cur); + } + } + + error += pkg_perform(&pkgs); + if (error != 0) { + if (Verbose) + warnx("%d package addition(s) failed", error); + exit(1); + } + exit(0); +} diff --git a/pkgtools/pkg_install/files/add/perform.c b/pkgtools/pkg_install/files/add/perform.c new file mode 100644 index 00000000000..2d3b9ccd62c --- /dev/null +++ b/pkgtools/pkg_install/files/add/perform.c @@ -0,0 +1,752 @@ +/* $NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:13:56 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: perform.c,v 1.44 1997/10/13 15:03:46 jkh Exp"; +#else +__RCSID("$NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:13:56 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the add module. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ASSERT_H +#include <assert.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" +#include "add.h" +#include "verify.h" + +#include <signal.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +static char LogDir[FILENAME_MAX]; +static int zapLogDir; /* Should we delete LogDir? */ + +static package_t Plist; +static char *Home; + +static int +sanity_check(const char *pkg) +{ + int errc = 0; + + if (!fexists(CONTENTS_FNAME)) { + warnx("package %s has no CONTENTS file!", pkg); + errc = 1; + } else if (!fexists(COMMENT_FNAME)) { + warnx("package %s has no COMMENT file!", pkg); + errc = 1; + } else if (!fexists(DESC_FNAME)) { + warnx("package %s has no DESC file!", pkg); + errc = 1; + } + return errc; +} + +/* install a pre-requisite package. Returns 1 if it installed it */ +static int +installprereq(const char *name, int *errc) +{ + int ret; + ret = 0; + + if (Verbose) + printf("Loading it from %s.\n", name); + path_setenv("PKG_PATH"); + if (vsystem("%s -s %s %s%s%s %s%s", + ADD_CMD, + get_verification(), + Force ? "-f " : "", + Prefix ? "-p " : "", + Prefix ? Prefix : "", + Verbose ? "-v " : "", + name)) { + warnx("autoload of dependency `%s' failed%s", + name, Force ? " (proceeding anyway)" : "!"); + if (!Force) + ++(*errc); + } else { + ret = 1; + } + + return ret; +} + +/* + * Install a single package + * Returns 0 if everything is ok, >0 else + */ +static int +pkg_do(const char *pkg) +{ + char playpen[FILENAME_MAX]; + char extract_contents[FILENAME_MAX]; + char upgrade_from[FILENAME_MAX]; + char upgrade_via[FILENAME_MAX]; + char upgrade_to[FILENAME_MAX]; + int upgrading = 0; + char *where_to, *tmp, *extract; + char *dbdir; + const char *exact; + FILE *cfile; + int errc; + plist_t *p; + struct stat sb; + int inPlace; + int rc; + + errc = 0; + zapLogDir = 0; + LogDir[0] = '\0'; + strcpy(playpen, FirstPen); + inPlace = 0; + dbdir = (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR; + + /* make sure dbdir actually exists! */ + if (!(isdir(dbdir) || islinktodir(dbdir))) { + if (vsystem("%s -p -m 755 %s", MKDIR, dbdir)) { + errx(1, "Database-dir %s cannot be generated, aborting.", + dbdir); + } + } + + /* Are we coming in for a second pass, everything already extracted? + * (Slave mode) */ + if (!pkg) { + fgets(playpen, FILENAME_MAX, stdin); + playpen[strlen(playpen) - 1] = '\0'; /* remove newline! */ + if (chdir(playpen) == FAIL) { + warnx("add in SLAVE mode can't chdir to %s", playpen); + return 1; + } + read_plist(&Plist, stdin); + where_to = playpen; + } + /* Nope - do it now */ + else { + const char *tmppkg; + + tmppkg = fileFindByPath(pkg); + if (tmppkg == NULL) { + warnx("no pkg found for '%s', sorry.", pkg); + return 1; + } + + pkg = tmppkg; + + if (IS_URL(pkg)) { + Home = fileGetURL(pkg); + if (Home == NULL) { + warnx("unable to fetch `%s' by URL", pkg); + } + where_to = Home; + + /* make sure the pkg is verified */ + if (!verify(pkg)) { + warnx("Package %s will not be extracted", pkg); + goto bomb; + } + } + else { /* local */ + if (!IS_STDIN(pkg)) { + /* not stdin */ + if (!ispkgpattern(pkg)) { + if (stat(pkg, &sb) == FAIL) { + warnx("can't stat package file '%s'", pkg); + goto bomb; + } + /* make sure the pkg is verified */ + if (!verify(pkg)) { + warnx("Package %s will not be extracted", pkg); + goto bomb; + } + } +#if defined(HAVE_TAR__FAST_READ) + (void) snprintf(extract_contents, sizeof(extract_contents), "--fast-read %s", CONTENTS_FNAME); +#else + (void) snprintf(extract_contents, sizeof(extract_contents), "%s", CONTENTS_FNAME); +#endif + extract = extract_contents; + } else { + /* some values for stdin */ + extract = NULL; + sb.st_size = 100000; /* Make up a plausible average size */ + } + Home = make_playpen(playpen, sizeof(playpen), sb.st_size * 4); + if (!Home) + warnx("unable to make playpen for %ld bytes", + (long) (sb.st_size * 4)); + where_to = Home; + if (unpack(pkg, extract)) { + warnx("unable to extract table of contents file from `%s' - not a package?", + pkg); + goto bomb; + } + } + + cfile = fopen(CONTENTS_FNAME, "r"); + if (!cfile) { + warnx("unable to open table of contents file `%s' - not a package?", + CONTENTS_FNAME); + goto bomb; + } + read_plist(&Plist, cfile); + fclose(cfile); + + if (!IS_URL(pkg)) { + /* Extract directly rather than moving? Oh goodie! */ + if (find_plist_option(&Plist, "extract-in-place")) { + if (Verbose) + printf("Doing in-place extraction for %s\n", pkg); + p = find_plist(&Plist, PLIST_CWD); + if (p) { + if (!(isdir(p->name) || islinktodir(p->name)) && !Fake) { + if (Verbose) + printf("Desired prefix of %s does not exist, creating.\n", p->name); + (void) vsystem("%s -p %s", MKDIR, p->name); + } + if (chdir(p->name) == -1) { + warn("unable to change directory to `%s'", p->name); + goto bomb; + } + where_to = p->name; + inPlace = 1; + } else { + warnx( + "no prefix specified in `%s' - this is a bad package!", + pkg); + goto bomb; + } + } + + /* + * 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%, so multiply by 4 for good measure. + */ + + if (!inPlace && min_free(playpen) < sb.st_size * 4) { + warnx("projected size of %ld exceeds available free space.\n" + "Please set your PKG_TMPDIR variable to point to a location with more\n" + "free space and try again", (long) (sb.st_size * 4)); + warnx("not extracting %s\ninto %s, sorry!", + pkg, where_to); + goto bomb; + } + + /* If this is a direct extract and we didn't want it, stop now */ + if (inPlace && Fake) + goto success; + + /* Finally unpack the whole mess */ + if (unpack(pkg, NULL)) { + warnx("unable to extract `%s'!", pkg); + goto bomb; + } + } + + /* Check for sanity */ + if (sanity_check(pkg)) + goto bomb; + + /* If we're running in MASTER mode, just output the plist and return */ + if (AddMode == MASTER) { + printf("%s\n", where_playpen()); + write_plist(&Plist, stdout, NULL); + return 0; + } + } + + /* + * If we have a prefix, delete the first one we see and add this + * one in place of it. + */ + if (Prefix) { + delete_plist(&Plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&Plist, PLIST_CWD, Prefix); + } + + setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1); + /* Protect against old packages with bogus @name fields */ + PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous"; + + /* See if this package (exact version) is already registered */ + (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName); + if ((isdir(LogDir) || islinktodir(LogDir)) && !Force) { + warnx("package `%s' already recorded as installed", PkgName); + goto success; /* close enough for government work */ + } + + /* See if some other version of us is already installed */ + { + char *s; + + if ((s = strrchr(PkgName, '-')) != NULL) { + char buf[FILENAME_MAX]; + char installed[FILENAME_MAX]; + + /* + * See if the pkg is already installed. If so, we might + * want to upgrade it. + */ + (void) snprintf(buf, sizeof(buf), "%.*s[0-9]*", + (int)(s - PkgName) + 1, PkgName); + if (findmatchingname(dbdir, buf, note_whats_installed, installed) > 0) { + if (upgrade) { + /* + * Upgrade step 1/4: Check if the new version is ok with all pkgs + * that require this pkg + */ + /* TODO */ + + /* + * Upgrade step 2/4: Do the actual update by moving aside + * the +REQUIRED_BY file, deinstalling the old pkg, adding + * the new one and moving the +REQUIRED_BY file back + * into place (finished in step 3/4) + */ + snprintf(upgrade_from, sizeof(upgrade_from), "%s/%s/" REQUIRED_BY_FNAME, + dbdir, installed); + snprintf(upgrade_via, sizeof(upgrade_via), "%s/.%s." REQUIRED_BY_FNAME, + dbdir, installed); + snprintf(upgrade_to, sizeof(upgrade_to), "%s/%s/" REQUIRED_BY_FNAME, + dbdir, PkgName); + + if (Verbose) + printf("Upgrading %s to %s.\n", installed, PkgName); + + if (fexists(upgrade_from)) { /* Are there any dependencies? */ + if (Verbose) + printf("mv %s %s\n", upgrade_from, upgrade_via); + rc = rename(upgrade_from, upgrade_via); + assert(rc == 0); + + upgrading = 1; + } + + if (Verbose) + printf("pkg_delete '%s'\n", installed); + vsystem("%s/sbin/pkg_delete '%s'\n", PREFIX, installed); + + } else { + warnx("other version '%s' already installed", installed); + + errc = 1; + goto success; /* close enough for government work */ + } + } + } + } + + /* See if there are conflicting packages installed */ + for (p = Plist.head; p; p = p->next) { + char installed[FILENAME_MAX]; + + if (p->type != PLIST_PKGCFL) + continue; + if (Verbose) + printf("Package `%s' conflicts with `%s'.\n", PkgName, p->name); + + /* was: */ + /* if (!vsystem("/usr/sbin/pkg_info -qe '%s'", p->name)) { */ + if (findmatchingname(dbdir, p->name, note_whats_installed, installed) > 0) { + warnx("Conflicting package `%s'installed, please use\n" + "\t\"pkg_delete %s\" first to remove it!", installed, installed); + ++errc; + } + } + + /* Quick pre-check if any conflicting dependencies are installed + * (e.g. version X is installed, but version Y is required) + */ + for (p = Plist.head; p; p = p->next) { + char installed[FILENAME_MAX]; + + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Depends pre-scan: `%s' required.\n", p->name); + /* if (vsystem("/usr/sbin/pkg_info -qe '%s'", p->name)) { */ + if (findmatchingname(dbdir, p->name, note_whats_installed, installed) <= 0) { + /* + * required pkg not found. look if it's available with a more liberal + * pattern. If so, this will lead to problems later (check on "some + * other version of us is already installed" will fail, see above), + * and we better stop right now. + */ + char *s; + int skip = -1; + + /* doing this right required to parse the full version(s), + * do a 99% solution here for now */ + if (strchr(p->name, '{')) + continue; /* would remove trailing '}' else */ + + if ((s = strpbrk(p->name, "<>")) != NULL) { + skip = 0; + } else if ((s = strrchr(p->name, '-')) != NULL) { + skip = 1; + } + + if (skip >= 0) { + char buf[FILENAME_MAX]; + + (void) snprintf(buf, sizeof(buf), + skip ? "%.*s[0-9]*" : "%.*s-[0-9]*", + (int)(s - p->name) + skip, p->name); + if (findmatchingname(dbdir, buf, note_whats_installed, installed) > 0) { + warnx("pkg `%s' required, but `%s' found installed.", + p->name, installed); + + if (upgrading) { + printf("HF: upgrade note -- could 'pkg_delete %s', and let the normal\n" + "dependency handling reinstall the updated package, assuming one IS\n" + "available. But then I'd expect proper binary pkgs being available for\n" + "the upgrade case.\n", installed); + } + + if (Force) { + warnx("Proceeding anyways."); + } else { + warnx("Please resolve this conflict!"); + errc = 1; + goto success; /* close enough */ + } + } + } + } + } + + + /* Now check the packing list for dependencies */ + for (exact = NULL, p = Plist.head; p; p = p->next) { + char installed[FILENAME_MAX]; + + if (p->type == PLIST_BLDDEP) { + exact = p->name; + continue; + } + if (p->type != PLIST_PKGDEP) { + exact = NULL; + continue; + } + if (Verbose) + printf("Package `%s' depends on `%s'.\n", PkgName, p->name); + + if (findmatchingname(dbdir, p->name, note_whats_installed, installed) != 1) { + /* required pkg not found - need to pull in */ + if (Fake) { + /* fake install (???) */ + if (Verbose) + printf("Package dependency %s for %s not installed%s\n", p->name, pkg, + Force ? " (proceeding anyway)" : "!"); + } else { + int done = 0; + int errc0 = 0; + + if (exact != NULL) { + /* first try the exact name, from the @blddep */ + done = installprereq(exact, &errc0); + } + if (!done) { + done = installprereq(p->name, &errc0); + } + if (!done && !Force) { + errc += errc0; + } + } + } else if (Verbose) { + printf(" - %s already installed.\n", installed); + } + } + + if (errc != 0) + goto bomb; + + /* Look for the requirements file */ + if (fexists(REQUIRE_FNAME)) { + vsystem("%s +x %s", CHMOD_CMD, REQUIRE_FNAME); /* be sure */ + if (Verbose) + printf("Running requirements file first for %s.\n", PkgName); + if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, PkgName)) { + warnx("package %s fails requirements %s", pkg, + Force ? "installing anyway" : "- not installed"); + if (!Force) { + errc = 1; + goto success; /* close enough for government work */ + } + } + } + + /* If we're really installing, and have an installation file, run it */ + if (!NoInstall && fexists(INSTALL_FNAME)) { + vsystem("%s +x %s", CHMOD_CMD, INSTALL_FNAME); /* make sure */ + if (Verbose) + printf("Running install with PRE-INSTALL for %s.\n", PkgName); + if (!Fake && vsystem("./%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) { + warnx("install script returned error status"); + errc = 1; + goto success; /* nothing to uninstall yet */ + } + } + + /* Now finally extract the entire show if we're not going direct */ + if (!inPlace && !Fake) + if (!extract_plist(".", &Plist)) { + errc = 1; + goto fail; + } + + if (!Fake && fexists(MTREE_FNAME)) { + if (Verbose) + printf("Running mtree for %s.\n", PkgName); + p = find_plist(&Plist, PLIST_CWD); + if (Verbose) + printf("%s -U -f %s -d -e -p %s\n", MTREE, MTREE_FNAME, p ? p->name : "/"); + if (!Fake) { + if (vsystem("%s -U -f %s -d -e -p %s", MTREE, MTREE_FNAME, p ? p->name : "/")) + warnx("mtree returned a non-zero status - continuing"); + } + unlink(MTREE_FNAME); /* remove this line to tar up pkg later - HF */ + } + + /* Run the installation script one last time? */ + if (!NoInstall && fexists(INSTALL_FNAME)) { + if (Verbose) + printf("Running install with POST-INSTALL for %s.\n", PkgName); + if (!Fake && vsystem("./%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) { + warnx("install script returned error status"); + errc = 1; + goto fail; + } + } + + /* Time to record the deed? */ + if (!NoRecord && !Fake) { + char contents[FILENAME_MAX]; + + umask(022); + if (getuid() != 0) + warnx("not running as root - trying to record install anyway"); + if (!PkgName) { + warnx("no package name! can't record package, sorry"); + errc = 1; + goto success; /* well, partial anyway */ + } + (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName); + zapLogDir = 1; /* LogDir contains something valid now */ + if (Verbose) + printf("Attempting to record package into %s.\n", LogDir); + if (make_hierarchy(LogDir)) { + warnx("can't record package into '%s', you're on your own!", + LogDir); + memset(LogDir, 0, sizeof(LogDir)); + errc = 1; + goto success; /* close enough for government work */ + } + /* Make sure pkg_info can read the entry */ + vsystem("%s a+rx %s", CHMOD_CMD, LogDir); + if (fexists(DEINSTALL_FNAME)) + move_file(".", DEINSTALL_FNAME, LogDir); + if (fexists(REQUIRE_FNAME)) + move_file(".", REQUIRE_FNAME, LogDir); + if (fexists(SIZE_PKG_FNAME)) + move_file(".", SIZE_PKG_FNAME, LogDir); + if (fexists(SIZE_ALL_FNAME)) + move_file(".", SIZE_ALL_FNAME, LogDir); + (void) snprintf(contents, sizeof(contents), "%s/%s", LogDir, CONTENTS_FNAME); + cfile = fopen(contents, "w"); + if (!cfile) { + 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, NULL); + fclose(cfile); + move_file(".", DESC_FNAME, LogDir); + move_file(".", COMMENT_FNAME, LogDir); + if (fexists(BUILD_VERSION_FNAME)) + move_file(".", BUILD_VERSION_FNAME, LogDir); + if (fexists(BUILD_INFO_FNAME)) + move_file(".", BUILD_INFO_FNAME, LogDir); + if (fexists(DISPLAY_FNAME)) + move_file(".", DISPLAY_FNAME, LogDir); + + /* register dependencies */ + /* we could save some cycles here if we remembered what we + * installed above (in case we got a wildcard dependency) */ + /* XXX remembering in p->name would NOT be good! */ + for (p = Plist.head; p; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Attempting to record dependency on package `%s'\n", p->name); + (void) snprintf(contents, sizeof(contents), "%s/%s", dbdir, + basename_of(p->name)); + if (ispkgpattern(p->name)) { + char *s; + s = findbestmatchingname(dirname_of(contents), + basename_of(contents)); + if (s != NULL) { + char *t; + t = strrchr(contents, '/'); + strcpy(t + 1, s); + free(s); + } else { + errx(1, "Where did our dependency go?!"); + /* this shouldn't happen... X-) */ + } + } + strcat(contents, "/"); + strcat(contents, REQUIRED_BY_FNAME); + + cfile = fopen(contents, "a"); + if (!cfile) + warnx("can't open dependency file '%s'!\n" + "dependency registration is incomplete", contents); + else { + fprintf(cfile, "%s\n", PkgName); + if (fclose(cfile) == EOF) + 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)) != NULL) { + FILE *fp; + char buf[BUFSIZ]; + + (void) snprintf(buf, sizeof(buf), "%s/%s", LogDir, p->name); + fp = fopen(buf, "r"); + if (fp) { + putc('\n', stdout); + while (fgets(buf, sizeof(buf), fp)) + fputs(buf, stdout); + putc('\n', stdout); + (void) fclose(fp); + } else + warnx("cannot open %s as display file", buf); + } + + goto success; + +bomb: + errc = 1; + goto success; + +fail: + /* Nuke the whole (installed) show, XXX but don't clean directories */ + if (!Fake) + delete_package(FALSE, FALSE, &Plist); + +success: + /* delete the packing list contents */ + free_plist(&Plist); + leave_playpen(Home); + + if (upgrading) { + /* + * Upgrade step 3/4: move back +REQUIRED_BY file + * (see also step 2/4) + */ + rc = rename(upgrade_via, upgrade_to); + assert(rc == 0); + + /* + * Upgrade step 4/4: Fix pkgs that depend on us to + * depend on the new version instead of the old + * one by fixing @pkgdep lines in +CONTENTS files. + */ + /* TODO */ + } + + return errc; +} + +void +cleanup(int signo) +{ + 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", RM, LogDir); + leave_playpen(Home); + if (signo) + exit(1); + } + signal(SIGINT, oldint); + signal(SIGHUP, oldhup); +} + +int +pkg_perform(lpkg_head_t *pkgs) +{ + int err_cnt = 0; + lpkg_t *lpp; + + signal(SIGINT, cleanup); + signal(SIGHUP, cleanup); + + if (AddMode == SLAVE) + err_cnt = pkg_do(NULL); + else { + while ((lpp = TAILQ_FIRST(pkgs)) != NULL) { + path_prepend_from_pkgname(lpp->lp_name); + err_cnt += pkg_do(lpp->lp_name); + path_prepend_clear(); + TAILQ_REMOVE(pkgs, lpp, lp_link); + free_lpkg(lpp); + } + } + + ftp_stop(); + + return err_cnt; +} diff --git a/pkgtools/pkg_install/files/add/pkg_add.1 b/pkgtools/pkg_install/files/add/pkg_add.1 new file mode 100644 index 00000000000..3771adf407d --- /dev/null +++ b/pkgtools/pkg_install/files/add/pkg_add.1 @@ -0,0 +1,512 @@ +.\" $NetBSD: pkg_add.1,v 1.1.1.1 2002/12/20 18:13:57 schmonz Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintainance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_add.1 +.\" +.Dd August 15, 2002 +.Dt PKG_ADD 1 +.Os +.Sh NAME +.Nm pkg_add +.Nd a utility for installing and upgrading software package distributions +.Sh SYNOPSIS +.Nm "" +.Op Fl fIMnRSuVv +.Bk -words +.Op Fl s Ar verification-type +.Ek +.Bk -words +.Op Fl t Ar template +.Ek +.Bk -words +.Op Fl p Ar prefix +.Ek +.Ar \fR[ftp://[\fIuser\fR[:\fIpassword]\fR@]\fIhost\fR[:\fIport\fR]][/\fIpath/\fR]pkg-name ... +.Sh DESCRIPTION +The +.Nm +command is used to extract and upgrade packages that have been +previously created with the +.Xr pkg_create 1 +command. +Packages are prepared collections of pre-built binaries, documentation, +configurations, installation instructions and/or other files. +.Nm +can recursively install other packages that the current package +depends on or requires from both local disk and via FTP. +.Sh WARNING +.Bf -emphasis +Since the +.Nm +command may execute scripts or programs contained within a package file, +your system may be susceptible to ``Trojan horses'' or other subtle +attacks from miscreants who create dangerous package files. +.Pp +You are advised to verify the competence and identity of those who +provide installable package files. +For extra protection, use the digital signatures provided where possible +(see the +.Fl s +option), or, failing that, use the +.Fl M +flag to extract the package file, and inspect its contents and scripts +to ensure it poses no danger to your system's integrity. +Pay particular attention to any +INSTALL, +DEINSTALL, +REQUIRE +or +MTREE_DIRS files, and inspect the +CONTENTS file for +.Cm @cwd , +.Cm @mode +(check for setuid), +.Cm @dirrm , +.Cm @exec , +and +.Cm @unexec +directives, and/or use the +.Xr pkg_info 1 +command to examine the package file. +.Ef +.Sh OPTIONS +The following command line arguments are supported: +.Bl -tag -width indent +.It Ar pkg-name [ ... ] +The named packages are installed. +.Ar pkg-name +may be either a URL or a local pathname, +a package name of "-" will cause +.Nm +to read from stdin. +If the packages are not found in the current +working directory, +.Nm +will search them in each directory named by the +.Ev PKG_PATH +environment variable. +Any dependencies required by the installed package will be searched +in the same location that the original package was installed from. +.It Fl f +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 I +If an installation script exists for a given package, do not execute it. +.It Fl M +Run in +.Cm MASTER +mode. +This is a very specialized mode for running +.Nm +and is meant to be run in conjunction with +.Cm SLAVE +mode. +When run in this mode, +.Nm +does no work beyond extracting the package into a temporary staging +area (see the +.Fl t +option), reading in the packing list, and then dumping it (prefaced by +the current staging area) to stdout where it may be filtered by a +program such as +.Xr sed 1 . +When used in conjunction with +.Cm SLAVE +mode, it allows you to make radical changes to the package structure +before acting on its contents. +.It Fl n +Don't actually install a package, just report the steps that +would be taken if it was. +.It Fl p Ar prefix +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 +by this flag. +Note that only the first +.Cm @cwd +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 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 +modes (see the +.Fl M +and +.Fl S +options). +.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! +.It Fl S +Run in +.Cm SLAVE +mode. +This is a very specialized mode for running +.Nm +and is meant to be run in conjunction with +.Cm MASTER +mode. +When run in this mode, +.Nm +expects the release contents to be already extracted and waiting +in the staging area, the location of which is read as a string +from stdin. +The complete packing list is also read from stdin, +and the contents then acted on as normal. +.It Fl s Ar verification-type +Use a callout to an external program to verify the binary package +being installed against an existing detached signature file. +The signature file must reside in the same directory +as the binary package. +At the present time, the following verification types +are defined: none, gpg and pgp5. +The signature will be verified at install time, and the results +will be displayed. +If the signature type is anything other than none, the user will be asked if +.Nm +should proceed to install the binary package. +The user must then take the decision whether to proceed or not, depending +upon the amount of trust that is placed in the signatory of the binary +package. +Please note that, at the current time, it is not possible to use +the verification feature when using +.Nm +to add a binary package via a URL - the package, and the related +detached signature file, must be local +for the verification to work. +.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 /var/tmp/instmp.XXXXXX , +but it may be necessary to override it in the situation where +space in your +.Pa /var/tmp +directory is limited. +Be sure to leave some number of `X' characters for +.Xr mktemp 3 +to fill in with a unique ID. +.Pp +You can get a performance boost by setting the staging area +.Ar template +to reside on the same disk partition as target directories for package +file installation; often this is +.Pa /usr . +.It Fl u +If the package that's being installed is already installed, either +in the same or a different version, an update is performed. +See below for a more detailed description of the process. +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.El +.Pp +One or more +.Ar pkg-name +arguments may be specified, each being either a file containing the +package (these usually ending with the ``.tgz'' suffix) or a +URL pointing at a file available on an ftp or web site. +Thus you may extract files directly from their anonymous ftp or WWW +locations (e.g. +.Nm +ftp://ftp.netbsd.org/pub/NetBSD/packages/1.5/i386/shells/bash-2.04.tgz). +Note: If you wish to use +.Bf -emphasis +passive mode +.Ef +ftp in such transfers, set +the variable +.Bf -emphasis +FTP_PASSIVE_MODE +.Ef +to some value in your environment. +Otherwise, the more standard ACTIVE mode may be used. +If +.Nm +consistently fails to fetch a package from a site known to work, +it may be because you have a firewall that demands the usage of +.Bf -emphasis +passive mode +.Ef +ftp. +.Sh TECHNICAL DETAILS +.Nm +extracts each package's "packing list" +into a special staging directory in /var/tmp (or $PKG_TMPDIR if set) +and then runs through the following sequence to fully extract the contents +of the package: +.Bl -enum -offset indent +.It +A check is made to determine if the package or another version of it +is already recorded as installed. +If it is, +installation is terminated if the +.Fl u +option is not given. +.Pp +If the +.Fl u +option is given, it's assumed the package should be upgraded instead. +This is prepared by moving an existing +.Pa +REQUIRED_BY +file aside (if it exists), and by running +.Xr pkg_delete 1 +on the installed package. +Installation then proceeds as if the package +was not installed, and restores the +.Pa +REQUIRED_BY +file afterwards. +.It +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 ) +are read from the packing list. +If any of these required packages are 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 +A search is made for any +.Cm @option +directives which control how the package is added to the system. +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 /var/tmp . +.It +If +.Cm @option extract-in-place +is enabled, the package is now extracted directly into its +final location, otherwise it is extracted into the staging area. +.It +If the package contains a +.Ar require +script (see +.Xr pkg_create 1 ) , +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 the package contains an +.Ar install +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 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 +.Xr pkg_create 1 ) , +then mtree is invoked as: +.Bd -filled -offset indent -compact +.Cm mtree +.Fl u +.Fl f +.Ar mtreefile +.Fl d +.Fl e +.Fl p +.Pa prefix +.Ed +where +.Pa prefix +is either the prefix specified with the +.Fl p +flag or, if no +.Fl p +flag was specified, the name of the first directory named by a +.Cm @cwd +directive within this package. +.It +If an +.Ar install +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 +script, description, and display files are copied into +.Pa /var/db/pkg/\*[Lt]pkg-name\*[Gt] +for subsequent possible use by +.Xr pkg_delete 1 . +Any package dependencies are recorded in the other packages' +.Pa /var/db/pkg/\*[Lt]other-pkg\*[Gt]/+REQUIRED_BY +file +(if the environment variable PKG_DBDIR is set, this overrides the +.Pa /var/db/pkg/ +path shown above). +.It +The staging area is deleted and the program terminates. +.It +Finally, if we were upgrading a package, any +.Pa +REQUIRED_BY +file that was moved aside before upgrading was started is now moved +back into place. +.El +.Pp +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 +option above). +This allows a package author to write a script +that reliably performs some action on the directory where the package +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 separated by semicolons. +Each entry consists of a directory name or URL. +The current directory may be indicated implicitly by an empty directory +name, or explicitly by a single period. +FTP URLs may not end with a slash. +.Ss PKG_DBDIR +Where to register packages instead of +.Pa /var/db/pkg . +.Ss PKG_TMPDIR +Staging directory for installing packages, defaults to /var/tmp. +Set to directory with lots of free disk if you run out of +space when installing a binary package. +.Sh EXAMPLES +In all cases, +.Nm +will try to install binary packages listed in dependencies list. +.Pp +You can specify a compiled binary package explicitly on the command line. +.Bd -literal +# pkg_add /usr/pkgsrc/packages/All/tcsh-6.10.00.tgz +.Ed +.Pp +If you omit the version number, +.Nm +will install the latest version available. +With +.Fl v , +.Nm +emits more messages to terminal. +.Bd -literal +# pkg_add -v /usr/pkgsrc/packages/All/unzip +.Ed +.Pp +You can grab a compiled binary package from remote location, by specifying +a URL. +The URL can be put into an environment variable, +.Ev PKG_PATH . +.Bd -literal +# pkg_add -v ftp://ftp.netbsd.org/pub/NetBSD/packages/1.5/i386/All/mozilla-0.8.1.tgz + +# export PKG_PATH=ftp://ftp.netbsd.org/pub/NetBSD/packages/1.5/i386/All +# pkg_add -v mozilla +.Ed +.Sh SEE ALSO +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr mktemp 3 , +.Xr sysconf 3 , +.Xr packages 7 , +.Xr mtree 8 +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +Initial work and ongoing development. +.It "John Kohl" +.Nx +refinements. +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, upgrading, etc. +.El +.Sh BUGS +Hard links between files in a distribution are only preserved if either +(1) the staging area is on the same file system as the target directory of +all the links to the file, or (2) all the links to the file are bracketed by +.Cm @cwd +directives in the contents file, +.Em and +and the link names are extracted with a single +.Cm tar +command (not split between +invocations due to exec argument-space limitations--this depends on the +value returned by +.Fn sysconf _SC_ARG_MAX ) . +.Pp +Pkg upgrading needs a lot more work to be really universal. +.Pp +Sure to be others. diff --git a/pkgtools/pkg_install/files/add/pkg_add.cat1 b/pkgtools/pkg_install/files/add/pkg_add.cat1 new file mode 100644 index 00000000000..0ced1555a5d --- /dev/null +++ b/pkgtools/pkg_install/files/add/pkg_add.cat1 @@ -0,0 +1,305 @@ +PKG_ADD(1) NetBSD Reference Manual PKG_ADD(1) + +NNAAMMEE + ppkkgg__aadddd - a utility for installing and upgrading software package distri- + butions + +SSYYNNOOPPSSIISS + ppkkgg__aadddd [--ffIIMMnnRRSSuuVVvv] [--ss _v_e_r_i_f_i_c_a_t_i_o_n_-_t_y_p_e] [--tt _t_e_m_p_l_a_t_e] [--pp _p_r_e_f_i_x] + [ftp://[_u_s_e_r[:_p_a_s_s_w_o_r_d_]@]_h_o_s_t[:_p_o_r_t]][/_p_a_t_h_/]pkg-name ... + +DDEESSCCRRIIPPTTIIOONN + The ppkkgg__aadddd command is used to extract and upgrade packages that have + been previously created with the pkg_create(1) command. Packages are + prepared collections of pre-built binaries, documentation, configura- + tions, installation instructions and/or other files. ppkkgg__aadddd can recur- + sively install other packages that the current package depends on or re- + quires from both local disk and via FTP. + +WWAARRNNIINNGG + _S_i_n_c_e _t_h_e ppkkgg__aadddd _c_o_m_m_a_n_d _m_a_y _e_x_e_c_u_t_e _s_c_r_i_p_t_s _o_r _p_r_o_g_r_a_m_s _c_o_n_t_a_i_n_e_d _w_i_t_h_- + _i_n _a _p_a_c_k_a_g_e _f_i_l_e_, _y_o_u_r _s_y_s_t_e_m _m_a_y _b_e _s_u_s_c_e_p_t_i_b_l_e _t_o _`_`_T_r_o_j_a_n _h_o_r_s_e_s_'_' _o_r + _o_t_h_e_r _s_u_b_t_l_e _a_t_t_a_c_k_s _f_r_o_m _m_i_s_c_r_e_a_n_t_s _w_h_o _c_r_e_a_t_e _d_a_n_g_e_r_o_u_s _p_a_c_k_a_g_e _f_i_l_e_s_. + + _Y_o_u _a_r_e _a_d_v_i_s_e_d _t_o _v_e_r_i_f_y _t_h_e _c_o_m_p_e_t_e_n_c_e _a_n_d _i_d_e_n_t_i_t_y _o_f _t_h_o_s_e _w_h_o _p_r_o_- + _v_i_d_e _i_n_s_t_a_l_l_a_b_l_e _p_a_c_k_a_g_e _f_i_l_e_s_. _F_o_r _e_x_t_r_a _p_r_o_t_e_c_t_i_o_n_, _u_s_e _t_h_e _d_i_g_i_t_a_l + _s_i_g_n_a_t_u_r_e_s _p_r_o_v_i_d_e_d _w_h_e_r_e _p_o_s_s_i_b_l_e _(_s_e_e _t_h_e --ss _o_p_t_i_o_n_)_, _o_r_, _f_a_i_l_i_n_g _t_h_a_t_, + _u_s_e _t_h_e --MM _f_l_a_g _t_o _e_x_t_r_a_c_t _t_h_e _p_a_c_k_a_g_e _f_i_l_e_, _a_n_d _i_n_s_p_e_c_t _i_t_s _c_o_n_t_e_n_t_s _a_n_d + _s_c_r_i_p_t_s _t_o _e_n_s_u_r_e _i_t _p_o_s_e_s _n_o _d_a_n_g_e_r _t_o _y_o_u_r _s_y_s_t_e_m_'_s _i_n_t_e_g_r_i_t_y_. _P_a_y + _p_a_r_t_i_c_u_l_a_r _a_t_t_e_n_t_i_o_n _t_o _a_n_y _+_I_N_S_T_A_L_L_, _+_D_E_I_N_S_T_A_L_L_, _+_R_E_Q_U_I_R_E _o_r _+_M_T_R_E_E___D_I_R_S + _f_i_l_e_s_, _a_n_d _i_n_s_p_e_c_t _t_h_e _+_C_O_N_T_E_N_T_S _f_i_l_e _f_o_r @@ccwwdd_, @@mmooddee _(_c_h_e_c_k _f_o_r _s_e_t_u_i_d_)_, + @@ddiirrrrmm_, @@eexxeecc_, _a_n_d @@uunneexxeecc _d_i_r_e_c_t_i_v_e_s_, _a_n_d_/_o_r _u_s_e _t_h_e pkg_info(_1) _c_o_m_m_a_n_d + _t_o _e_x_a_m_i_n_e _t_h_e _p_a_c_k_a_g_e _f_i_l_e_. + +OOPPTTIIOONNSS + The following command line arguments are supported: + + _p_k_g_-_n_a_m_e [_._._.] + The named packages are installed. _p_k_g_-_n_a_m_e may be either a URL + or a local pathname, a package name of "-" will cause ppkkgg__aadddd to + read from stdin. If the packages are not found in the current + working directory, ppkkgg__aadddd will search them in each directory + named by the PKG_PATH environment variable. Any dependencies re- + quired by the installed package will be searched in the same lo- + cation that the original package was installed from. + + --ff Force installation to proceed even if prerequisite packages are + not installed or the requirements script fails. Although ppkkgg__aadddd + will still try to find and auto-install missing prerequisite + packages, a failure to find one will not be fatal. + + --II If an installation script exists for a given package, do not exe- + cute it. + + --MM Run in MMAASSTTEERR mode. This is a very specialized mode for running + ppkkgg__aadddd and is meant to be run in conjunction with SSLLAAVVEE mode. + When run in this mode, ppkkgg__aadddd does no work beyond extracting the + package into a temporary staging area (see the --tt option), read- + ing in the packing list, and then dumping it (prefaced by the + current staging area) to stdout where it may be filtered by a + program such as sed(1). When used in conjunction with SSLLAAVVEE + mode, it allows you to make radical changes to the package struc- + ture before acting on its contents. + + --nn Don't actually install a package, just report the steps that + would be taken if it was. + + --pp _p_r_e_f_i_x + Set _p_r_e_f_i_x as the directory in which to extract files from a + package. If a package has set its default directory, it will be + overridden by this flag. Note that only the first @@ccwwdd directive + will be replaced, since ppkkgg__aadddd has no way of knowing which di- + rectory settings are relative and 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* di- + rectory transitions, then you may then wish to look into the use + of MMAASSTTEERR and SSLLAAVVEE modes (see the --MM and --SS options). + + --RR 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! + + --SS Run in SSLLAAVVEE mode. This is a very specialized mode for running + ppkkgg__aadddd and is meant to be run in conjunction with MMAASSTTEERR mode. + When run in this mode, ppkkgg__aadddd expects the release contents to be + already extracted and waiting in the staging area, the location + of which is read as a string from stdin. The complete packing + list is also read from stdin, and the contents then acted on as + normal. + + --ss _v_e_r_i_f_i_c_a_t_i_o_n_-_t_y_p_e + Use a callout to an external program to verify the binary package + being installed against an existing detached signature file. The + signature file must reside in the same directory as the binary + package. At the present time, the following verification types + are defined: none, gpg and pgp5. The signature will be verified + at install time, and the results will be displayed. If the sig- + nature type is anything other than none, the user will be asked + if ppkkgg__aadddd should proceed to install the binary package. The us- + er must then take the decision whether to proceed or not, depend- + ing upon the amount of trust that is placed in the signatory of + the binary package. Please note that, at the current time, it is + not possible to use the verification feature when using ppkkgg__aadddd + to add a binary package via a URL - the package, and the related + detached signature file, must be local for the verification to + work. + + --tt _t_e_m_p_l_a_t_e + Use _t_e_m_p_l_a_t_e as the input to mktemp(3) when creating a ``staging + area.'' By default, this is the string _/_v_a_r_/_t_m_p_/_i_n_s_t_m_p_._X_X_X_X_X_X, + but it may be necessary to override it in the situation where + space in your _/_v_a_r_/_t_m_p directory is limited. Be sure to leave + some number of `X' characters for mktemp(3) to fill in with a + unique ID. + + You can get a performance boost by setting the staging area + _t_e_m_p_l_a_t_e to reside on the same disk partition as target directo- + ries for package file installation; often this is _/_u_s_r. + + --uu If the package that's being installed is already installed, ei- + ther in the same or a different version, an update is performed. + See below for a more detailed description of the process. + + --VV Print version number and exit. + + --vv Turn on verbose output. + + One or more _p_k_g_-_n_a_m_e arguments may be specified, each being either a file + containing the package (these usually ending with the ``.tgz'' suffix) or + a URL pointing at a file available on an ftp or web site. Thus you may + extract files directly from their anonymous ftp or WWW locations (e.g. + ppkkgg__aadddd ftp://ftp.netbsd.org/pub/NetBSD/pack- + ages/1.5/i386/shells/bash-2.04.tgz). Note: If you wish to use _p_a_s_s_i_v_e + _m_o_d_e ftp in such transfers, set the variable _F_T_P___P_A_S_S_I_V_E___M_O_D_E to some + value in your environment. Otherwise, the more standard ACTIVE mode may + be used. If ppkkgg__aadddd consistently fails to fetch a package from a site + known to work, it may be because you have a firewall that demands the us- + age of _p_a_s_s_i_v_e _m_o_d_e ftp. + +TTEECCHHNNIICCAALL DDEETTAAIILLSS + ppkkgg__aadddd extracts each package's "packing list" into a special staging di- + rectory in /var/tmp (or $PKG_TMPDIR if set) and then runs through the + following sequence to fully extract the contents of the package: + + 1. A check is made to determine if the package or another version + of it is already recorded as installed. If it is, installa- + tion is terminated if the --uu option is not given. + + If the --uu option is given, it's assumed the package should be + upgraded instead. This is prepared by moving an existing + _+_R_E_Q_U_I_R_E_D___B_Y file aside (if it exists), and by running + pkg_delete(1) on the installed package. Installation then + proceeds as if the package was not installed, and restores the + _+_R_E_Q_U_I_R_E_D___B_Y file afterwards. + + 2. A check is made to determine if the package conflicts (from + @@ppkkggccffll directives, see pkg_create(1)) with an already record- + ed as installed package. If it is, installation is terminat- + ed. + + 3. All package dependencies (from @@ppkkggddeepp directives, see + pkg_create(1)) are read from the packing list. If any of + these required packages are not currently installed, an at- + tempt is made to find and install it; if the missing package + cannot be found or installed, the installation is terminated. + + 4. A search is made for any @@ooppttiioonn directives which control how + the package is added to the system. The only currently imple- + mented option is @@ooppttiioonn eexxttrraacctt--iinn--ppllaaccee, which causes the + package to be extracted directly into its prefix directory + rather than moving it through a staging area in _/_v_a_r_/_t_m_p. + + 5. If @@ooppttiioonn eexxttrraacctt--iinn--ppllaaccee is enabled, the package is now ex- + tracted directly into its final location, otherwise it is ex- + tracted into the staging area. + + 6. If the package contains a _r_e_q_u_i_r_e script (see pkg_create(1)), + it is executed with the following arguments: + + _p_k_g_-_n_a_m_e The name of the package being installed + + IINNSSTTAALLLL Keyword denoting to the script that it is to run + an installation requirements check. (The key- + word is useful only to scripts which serve mul- + tiple functions). + + If the _r_e_q_u_i_r_e script exits with a non-zero status code, the + installation is terminated. + + 7. If the package contains an _i_n_s_t_a_l_l script, it is executed with + the following arguments: + + _p_k_g_-_n_a_m_e The name of the package being installed. + + PPRREE--IINNSSTTAALLLL Keyword denoting that the script is to perform + any actions needed before the package is in- + stalled. + + If the _i_n_s_t_a_l_l script exits with a non-zero status code, the + installation is terminated. + + 8. If @@ooppttiioonn eexxttrraacctt--iinn--ppllaaccee 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 loca- + tions. + + 9. If the package contains an _m_t_r_e_e_f_i_l_e file (see pkg_create(1)), + then mtree is invoked as: + mmttrreeee --uu --ff _m_t_r_e_e_f_i_l_e --dd --ee --pp _p_r_e_f_i_x + where _p_r_e_f_i_x is either the prefix specified with the --pp flag + or, if no --pp flag was specified, the name of the first direc- + tory named by a @@ccwwdd directive within this package. + + 10. If an _i_n_s_t_a_l_l script exists for the package, it is executed + with the following arguments: + + _p_k_g___n_a_m_e The name of the package being installed. + + PPOOSSTT--IINNSSTTAALLLL Keyword denoting that the script is to perform + any actions needed after the package has been + installed. + + 11. After installation is complete, a copy of the packing list, + _d_e_i_n_s_t_a_l_l script, description, and display files are copied + into _/_v_a_r_/_d_b_/_p_k_g_/_<_p_k_g_-_n_a_m_e_> for subsequent possible use by + pkg_delete(1). Any package dependencies are recorded in the + other packages' _/_v_a_r_/_d_b_/_p_k_g_/_<_o_t_h_e_r_-_p_k_g_>_/_+_R_E_Q_U_I_R_E_D___B_Y file (if + the environment variable PKG_DBDIR is set, this overrides the + _/_v_a_r_/_d_b_/_p_k_g_/ path shown above). + + 12. The staging area is deleted and the program terminates. + + 13. Finally, if we were upgrading a package, any _+_R_E_Q_U_I_R_E_D___B_Y file + that was moved aside before upgrading was started is now moved + back into place. + + The _i_n_s_t_a_l_l and _r_e_q_u_i_r_e scripts are called with the environment variable + PKG_PREFIX set to the installation prefix (see the --pp option above). + This allows a package author to write a script that reliably performs + some action on the directory where the package is installed, even if the + user might change it with the --pp flag to ppkkgg__aadddd. + +EENNVVIIRROONNMMEENNTT + PPKKGG__PPAATTHH + The value of the PKG_PATH is used if a given package can't be found, it's + usually set to _/_u_s_r_/_p_k_g_s_r_c_/_p_a_c_k_a_g_e_s_/_A_l_l. The environment variable should + be a series of entries separated by semicolons. Each entry consists of a + directory name or URL. The current directory may be indicated implicitly + by an empty directory name, or explicitly by a single period. FTP URLs + may not end with a slash. + + PPKKGG__DDBBDDIIRR + Where to register packages instead of _/_v_a_r_/_d_b_/_p_k_g. + + PPKKGG__TTMMPPDDIIRR + Staging directory for installing packages, defaults to /var/tmp. Set to + directory with lots of free disk if you run out of space when installing + a binary package. + +EEXXAAMMPPLLEESS + In all cases, ppkkgg__aadddd will try to install binary packages listed in de- + pendencies list. + + You can specify a compiled binary package explicitly on the command line. + + # pkg_add /usr/pkgsrc/packages/All/tcsh-6.10.00.tgz + + If you omit the version number, ppkkgg__aadddd will install the latest version + available. With --vv, ppkkgg__aadddd emits more messages to terminal. + + # pkg_add -v /usr/pkgsrc/packages/All/unzip + + You can grab a compiled binary package from remote location, by specify- + ing a URL. The URL can be put into an environment variable, PKG_PATH. + + # pkg_add -v ftp://ftp.netbsd.org/pub/NetBSD/packages/1.5/i386/All/mozilla-0.8.1.tgz + + # export PKG_PATH=ftp://ftp.netbsd.org/pub/NetBSD/packages/1.5/i386/All + # pkg_add -v mozilla + +SSEEEE AALLSSOO + pkg_admin(1), pkg_create(1), pkg_delete(1), pkg_info(1), mktemp(3), + sysconf(3), packages(7), mtree(8) + +AAUUTTHHOORRSS + Jordan Hubbard + Initial work and ongoing development. + John Kohl + NetBSD refinements. + Hubert Feyrer + NetBSD wildcard dependency processing, pkgdb, upgrading, etc. + +BBUUGGSS + Hard links between files in a distribution are only preserved if either + (1) the staging area is on the same file system as the target directory + of all the links to the file, or (2) all the links to the file are brack- + eted by @@ccwwdd directives in the contents file, _a_n_d and the link names are + extracted with a single ttaarr command (not split between invocations due to + exec argument-space limitations--this depends on the value returned by + ssyyssccoonnff(___S_C___A_R_G___M_A_X)). + + Pkg upgrading needs a lot more work to be really universal. + + Sure to be others. + +NetBSD 1.6 August 15, 2002 5 diff --git a/pkgtools/pkg_install/files/add/verify.c b/pkgtools/pkg_install/files/add/verify.c new file mode 100644 index 00000000000..278d8da01fe --- /dev/null +++ b/pkgtools/pkg_install/files/add/verify.c @@ -0,0 +1,172 @@ +/* $NetBSD: verify.c,v 1.1.1.1 2002/12/20 18:13:57 schmonz Exp $ */ + +/* + * Copyright (c) 2001 Alistair G. Crooks. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Alistair G. Crooks. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if 0 +#include <sys/cdefs.h> + +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1999 \ + The NetBSD Foundation, Inc. All rights reserved."); +__RCSID("$NetBSD: verify.c,v 1.1.1.1 2002/12/20 18:13:57 schmonz Exp $"); +#endif +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include <unistd.h> + +#include "verify.h" +#include "lib.h" + +enum { + MaxExtensions = 10 +}; + +/* this struct defines a verification type */ +typedef struct ver_t { + const char *name; /* name of type */ + const char *command; /* command to execute to verify */ + const char *extensions[MaxExtensions]; /* signature file extensions */ +} ver_t; + +static char *verification_type; /* the verification type which has been selected */ + +/* called when gpg verification type is selected */ +static int +do_verify(const char *pkgname, const char *cmd, const char *const *extensions) +{ + struct stat st; + const char *const *ep; + char buf[BUFSIZ]; + char f[FILENAME_MAX]; + int i; + + if (cmd == NULL) { + return 1; + } + for (i = 0, ep = extensions ; i < MaxExtensions && *ep ; ep++, i++) { + (void) snprintf(f, sizeof(f), "%s%s", pkgname, *ep); + if (stat(f, &st) == 0) { + (void) fprintf(stderr, "pkg_add: Using signature file: %s\n", f); + if (vsystem(cmd, f) != 0) { + (void) fprintf(stderr, "*** WARNING ***: `%s' has a bad signature\n", f); + return 0; + } + (void) fprintf(stderr, "Proceed with addition of %s: [y/n]? ", pkgname); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + (void) fprintf(stderr, "Exiting now..."); + exit(EXIT_FAILURE); + } + switch(buf[0]) { + case 'Y': + case 'y': + case '1': + return 1; + } + (void) fprintf(stderr, "Package `%s' will not be added\n", pkgname); + return 0; + } + } + (void) fprintf(stderr, "No valid signature file found for `%s'\n", pkgname); + return 0; +} + +/* table holding possible verifications which can be made */ +static const ver_t vertab[] = { + { "none", NULL, { NULL } }, + { "gpg", "gpg --verify %s", { ".sig", ".asc", NULL } }, + { "pgp5", "pgpv %s", { ".sig", ".asc", ".pgp", NULL } }, + { NULL } +}; + +/* set the verification type - usually called during command line processing */ +void +set_verification(const char *type) +{ + if (verification_type) { + (void) free(verification_type); + } + verification_type = strdup(type); +} + +/* return the type of verification that is being used */ +char * +get_verification(void) +{ + const ver_t *vp; + + if (verification_type != NULL) { + for (vp = vertab ; vp->name ; vp++) { + if (strcasecmp(verification_type, vp->name) == 0) { + return verification_type; + } + } + } + return "none"; +} + +/* verify the digital signature (if any) on a package */ +int +verify(const char *pkg) +{ + const ver_t *vp; + + if (verification_type == NULL) { + return do_verify(pkg, NULL, NULL); + } + for (vp = vertab ; vp->name ; vp++) { + if (strcasecmp(verification_type, vp->name) == 0) { + return do_verify(pkg, vp->command, vp->extensions); + } + } + (void) fprintf(stderr, "Can't find `%s' verification details\n", verification_type); + return 0; +} diff --git a/pkgtools/pkg_install/files/add/verify.h b/pkgtools/pkg_install/files/add/verify.h new file mode 100644 index 00000000000..ef155a24896 --- /dev/null +++ b/pkgtools/pkg_install/files/add/verify.h @@ -0,0 +1,40 @@ +/* $NetBSD: verify.h,v 1.1.1.1 2002/12/20 18:13:57 schmonz Exp $ */ + +/* + * Copyright (c) 2001 Alistair G. Crooks. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Alistair G. Crooks. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef VERIFY_H_ +#define VERIFY_H_ + +void set_verification(const char *); +char *get_verification(void); +int verify(const char *); + +#endif /* VERIFY_H_ */ diff --git a/pkgtools/pkg_install/files/admin/Makefile.in b/pkgtools/pkg_install/files/admin/Makefile.in new file mode 100644 index 00000000000..b62d831d155 --- /dev/null +++ b/pkgtools/pkg_install/files/admin/Makefile.in @@ -0,0 +1,39 @@ +# From NetBSD: Makefile,v 1.1 1999/01/19 17:01:58 hubertf Exp + +PREFIX= @prefix@ +INSTALL= @INSTALL@ + +mandir= ${PREFIX}/man +mandircat1= ${mandir}/cat1 + +CC= @CC@ +CCLD= $(CC) +LIBS= @LIBS@ -linstall +CPPFLAGS= @CPPFLAGS@ +DEFS= @DEFS@ -I. -I@srcdir@ -I../lib +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ -L../lib + +LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ +COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) + +PROG= pkg_admin + +SRCS= main.c +OBJS= main.o + +all: ${PROG} + +${PROG}: ${OBJS} + ${LINK} ${OBJS} ${LIBS} + +.c.o: + $(COMPILE) -c $< -o $@ + +clean: + rm -f ${OBJS} ${PROG} + +install: + ${INSTALL} ${PROG} ${PREFIX}/sbin + ${INSTALL} -m 755 -d ${mandircat1} + ${INSTALL} -m 444 ${PROG}.cat1 ${mandircat1}/${PROG}.1 diff --git a/pkgtools/pkg_install/files/admin/README b/pkgtools/pkg_install/files/admin/README new file mode 100644 index 00000000000..74c13e0f1ed --- /dev/null +++ b/pkgtools/pkg_install/files/admin/README @@ -0,0 +1,9 @@ +Some of the options of this utility (add, delete) are *not* intended for +public release. Any work regarding the consistancy of the pkgdb should +be put into pkg_add/pkg_delete, instead of a brute-force "rebuild". + +The "rebuild" should be only needed wen upgrading from non-pkgdb- +pkg_* tools to pkgdb-pkg_* tools. + + + - hubertf diff --git a/pkgtools/pkg_install/files/admin/main.c b/pkgtools/pkg_install/files/admin/main.c new file mode 100644 index 00000000000..14e5a886ea0 --- /dev/null +++ b/pkgtools/pkg_install/files/admin/main.c @@ -0,0 +1,630 @@ +/* $NetBSD: main.c,v 1.1.1.1 2002/12/20 18:13:53 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: main.c,v 1.1.1.1 2002/12/20 18:13:53 schmonz Exp $"); +#endif +#endif + +/* + * Copyright (c) 1999 Hubert Feyrer. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Hubert Feyrer for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <errno.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_MD5GLOBAL_H +#include <md5global.h> +#endif + +#ifdef HAVE_MD5_H +#include <md5.h> +#endif + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#include <stdio.h> + +#include "lib.h" + +void usage(void); + +int filecnt; +int pkgcnt; + +static int checkpattern_fn(const char *, void *); + +/* + * Assumes CWD is in /var/db/pkg/<pkg>! + */ +static void +check1pkg(const char *pkgdir) +{ + FILE *f; + plist_t *p; + package_t Plist; + char *PkgName, *dirp = NULL, *md5file; + char file[FILENAME_MAX]; + char dir[FILENAME_MAX]; + + f = fopen(CONTENTS_FNAME, "r"); + if (f == NULL) + err(1, "can't open %s/%s/%s", _pkgdb_getPKGDB_DIR(), pkgdir, CONTENTS_FNAME); + + Plist.head = Plist.tail = NULL; + read_plist(&Plist, f); + p = find_plist(&Plist, PLIST_NAME); + if (p == NULL) + errx(1, "Package %s has no @name, aborting.", + pkgdir); + PkgName = p->name; + for (p = Plist.head; p; p = p->next) { + switch (p->type) { + case PLIST_FILE: + if (dirp == NULL) { + warnx("dirp not initialized, please send-pr!"); + abort(); + } + + (void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name); + + if (!(isfile(file) || islinktodir(file))) + warnx("%s: File %s is in %s but not on filesystem!", PkgName, file, CONTENTS_FNAME); + else { + if (p->next && + p->next->type == PLIST_COMMENT && + strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) { /* || PLIST_MD5 - HF */ + if ((md5file = MD5File(file, NULL)) != NULL) { + /* Mismatch? */ +#ifdef PKGDB_DEBUG + printf("%s: md5 should=<%s>, is=<%s>\n", + file, p->next->name + ChecksumHeaderLen, md5file); +#endif + if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0) + printf("%s fails MD5 checksum\n", file); + + free(md5file); + } + } + + filecnt++; + } + break; + case PLIST_CWD: + if (strcmp(p->name, ".") != 0) + dirp = p->name; + else { + (void) snprintf(dir, sizeof(dir), "%s/%s", _pkgdb_getPKGDB_DIR(), pkgdir); + dirp = dir; + } + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_SHOW_ALL: + case PLIST_SRC: + case PLIST_CMD: + case PLIST_CHMOD: + case PLIST_CHOWN: + case PLIST_CHGRP: + case PLIST_COMMENT: + case PLIST_NAME: + case PLIST_UNEXEC: + case PLIST_DISPLAY: + case PLIST_PKGDEP: + case PLIST_MTREE: + case PLIST_DIR_RM: + case PLIST_IGNORE_INST: + case PLIST_OPTION: + case PLIST_PKGCFL: + case PLIST_BLDDEP: + break; + } + } + free_plist(&Plist); + fclose(f); + pkgcnt++; +} + +static void +rebuild(void) +{ + DIR *dp; + struct dirent *de; + FILE *f; + plist_t *p; + char *PkgName, dir[FILENAME_MAX], *dirp = NULL; + char *PkgDBDir = NULL, file[FILENAME_MAX]; + + pkgcnt = 0; + filecnt = 0; + + if (unlink(_pkgdb_getPKGDB_FILE()) != 0 && errno != ENOENT) + err(1, "unlink %s", _pkgdb_getPKGDB_FILE()); + + if (pkgdb_open(0) == -1) + err(1, "cannot open pkgdb"); + + setbuf(stdout, NULL); + PkgDBDir = _pkgdb_getPKGDB_DIR(); + chdir(PkgDBDir); +#ifdef PKGDB_DEBUG + printf("PkgDBDir='%s'\n", PkgDBDir); +#endif + dp = opendir("."); + if (dp == NULL) + err(1, "opendir failed"); + while ((de = readdir(dp))) { + package_t Plist; + + if (!isdir(de->d_name)) + continue; + + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) + continue; + +#ifdef PKGDB_DEBUG + printf("%s\n", de->d_name); +#else + printf("."); +#endif + + chdir(de->d_name); + + f = fopen(CONTENTS_FNAME, "r"); + if (f == NULL) + err(1, "can't open %s/%s", de->d_name, CONTENTS_FNAME); + + Plist.head = Plist.tail = NULL; + read_plist(&Plist, f); + p = find_plist(&Plist, PLIST_NAME); + if (p == NULL) + errx(1, "Package %s has no @name, aborting.", + de->d_name); + PkgName = p->name; + for (p = Plist.head; p; p = p->next) { + switch (p->type) { + case PLIST_FILE: + if (dirp == NULL) { + warnx("dirp not initialized, please send-pr!"); + abort(); + } + + (void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name); + + if (!(isfile(file) || islinktodir(file))) + warnx("%s: File %s is in %s but not on filesystem!", + PkgName, file, CONTENTS_FNAME); + else { + pkgdb_store(file, PkgName); + filecnt++; + } + break; + case PLIST_CWD: + if (strcmp(p->name, ".") != 0) + dirp = p->name; + else { + (void) snprintf(dir, sizeof(dir), "%s/%s", PkgDBDir, de->d_name); + dirp = dir; + } + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_SHOW_ALL: + case PLIST_SRC: + case PLIST_CMD: + case PLIST_CHMOD: + case PLIST_CHOWN: + case PLIST_CHGRP: + case PLIST_COMMENT: + case PLIST_NAME: + case PLIST_UNEXEC: + case PLIST_DISPLAY: + case PLIST_PKGDEP: + case PLIST_MTREE: + case PLIST_DIR_RM: + case PLIST_IGNORE_INST: + case PLIST_OPTION: + case PLIST_PKGCFL: + case PLIST_BLDDEP: + break; + } + } + free_plist(&Plist); + fclose(f); + pkgcnt++; + + chdir(".."); + } + closedir(dp); + pkgdb_close(); + + printf("\n"); + printf("Stored %d file%s from %d package%s in %s.\n", + filecnt, filecnt == 1 ? "" : "s", + pkgcnt, pkgcnt == 1 ? "" : "s", + _pkgdb_getPKGDB_FILE()); +} + +static void +checkall(void) +{ + DIR *dp; + struct dirent *de; + + pkgcnt = 0; + filecnt = 0; + + setbuf(stdout, NULL); + chdir(_pkgdb_getPKGDB_DIR()); + + dp = opendir("."); + if (dp == NULL) + err(1, "opendir failed"); + while ((de = readdir(dp))) { + if (!isdir(de->d_name)) + continue; + + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) + continue; + + chdir(de->d_name); + + check1pkg(de->d_name); + printf("."); + + chdir(".."); + } + closedir(dp); + pkgdb_close(); + + + printf("\n"); + printf("Checked %d file%s from %d package%s.\n", + filecnt, (filecnt == 1) ? "" : "s", + pkgcnt, (pkgcnt == 1) ? "" : "s"); +} + +static int +checkpattern_fn(const char *pkg, void *vp) +{ + int rc; + + rc = chdir(pkg); + if (rc == -1) + err(1, "Cannot chdir to %s/%s", _pkgdb_getPKGDB_DIR(), pkg); + + check1pkg(pkg); + printf("."); + + chdir(".."); + + return 0; +} + +static int +lspattern_fn(const char *pkg, void *vp) +{ + char *data = vp; + printf("%s/%s\n", data, pkg); + + return 0; +} + +int +main(int argc, char *argv[]) +{ + setprogname(argv[0]); + + if (argc < 2) + usage(); + + if (strcmp(argv[1], "-V") == 0) { + + show_version(); + /* NOTREACHED */ + + } else if (strcasecmp(argv[1], "pmatch") == 0) { + + char *pattern, *pkg; + + argv++; /* argv[0] */ + argv++; /* "pmatch" */ + + pattern = argv[0]; + pkg = argv[1]; + + if (pattern == NULL || pkg == NULL) { + usage(); + } + + if (pmatch(pattern, pkg)){ + return 0; + } else { + return 1; + } + + } else if (strcasecmp(argv[1], "rebuild") == 0) { + + rebuild(); + printf("Done.\n"); + + } else if (strcasecmp(argv[1], "check") == 0) { + + argv++; /* argv[0] */ + argv++; /* "check" */ + + if (*argv != NULL) { + /* args specified */ + int rc; + + filecnt = 0; + + setbuf(stdout, NULL); + + rc = chdir(_pkgdb_getPKGDB_DIR()); + if (rc == -1) + err(1, "Cannot chdir to %s", _pkgdb_getPKGDB_DIR()); + + while (*argv != NULL) { + if (ispkgpattern(*argv)) { + if (findmatchingname(_pkgdb_getPKGDB_DIR(), *argv, checkpattern_fn, NULL) == 0) + errx(1, "No matching pkg for %s.", *argv); + } else { + rc = chdir(*argv); + if (rc == -1) { + /* found nothing - try 'pkg-[0-9]*' */ + char try[FILENAME_MAX]; + + snprintf(try, sizeof(try), "%s-[0-9]*", *argv); + if (findmatchingname(_pkgdb_getPKGDB_DIR(), try, + checkpattern_fn, NULL) <= 0) { + + errx(1, "cannot find package %s", *argv); + } else { + /* nothing to do - all the work is/was + * done in checkpattern_fn() */ + } + } else { + check1pkg(*argv); + printf("."); + + chdir(".."); + } + } + + argv++; + } + + printf("\n"); + printf("Checked %d file%s from %d package%s.\n", + filecnt, (filecnt == 1) ? "" : "s", + pkgcnt, (pkgcnt == 1) ? "" : "s"); + } else { + checkall(); + } + printf("Done.\n"); + + } else if (strcasecmp(argv[1], "lsall") == 0) { + int saved_wd; + + argv++; /* argv[0] */ + argv++; /* "check" */ + + /* preserve cwd */ + saved_wd=open(".", O_RDONLY); + if (saved_wd == -1) + err(1, "Cannot save working dir"); + + while (*argv != NULL) { + /* args specified */ + int rc; + const char *basep, *dir; + char *cwd; + char base[FILENAME_MAX]; + + dir = dirname_of(*argv); + basep = basename_of(*argv); + snprintf(base, sizeof(base), "%s.t[bg]z", basep); + + fchdir(saved_wd); + rc = chdir(dir); + if (rc == -1) + err(1, "Cannot chdir to %s", _pkgdb_getPKGDB_DIR()); + + cwd = getcwd(NULL, 0); + if (findmatchingname(cwd, base, lspattern_fn, cwd) == -1) + errx(1, "Error in findmatchingname(\"%s\", \"%s\", ...)", + cwd, base); + free(cwd); + + argv++; + } + + close(saved_wd); + + } else if (strcasecmp(argv[1], "lsbest") == 0) { + int saved_wd; + + argv++; /* argv[0] */ + argv++; /* "check" */ + + /* preserve cwd */ + saved_wd=open(".", O_RDONLY); + if (saved_wd == -1) + err(1, "Cannot save working dir"); + + while (*argv != NULL) { + /* args specified */ + int rc; + const char *basep, *dir; + char *cwd; + char base[FILENAME_MAX]; + char *p; + + dir = dirname_of(*argv); + basep = basename_of(*argv); + snprintf(base, sizeof(base), "%s.t[bg]z", basep); + + fchdir(saved_wd); + rc = chdir(dir); + if (rc == -1) + err(1, "Cannot chdir to %s", _pkgdb_getPKGDB_DIR()); + + cwd = getcwd(NULL, 0); + p = findbestmatchingname(cwd, base); + if (p) { + printf("%s/%s\n", cwd, p); + free(p); + } + free(cwd); + + argv++; + } + + close(saved_wd); + + } else if (strcasecmp(argv[1], "list") == 0 || + strcasecmp(argv[1], "dump") == 0) { + + char *key, *val; + + printf("Dumping pkgdb %s:\n", _pkgdb_getPKGDB_FILE()); + + if (pkgdb_open(1) == -1) { + err(1, "cannot open %s", _pkgdb_getPKGDB_FILE()); + } + while ((key = pkgdb_iter())) { + val = pkgdb_retrieve(key); + + printf("file: %-50s pkg: %s\n", key, val); + } + pkgdb_close(); + + } +#ifdef PKGDB_DEBUG + else if (strcasecmp(argv[1], "del") == 0 || + strcasecmp(argv[1], "delete") == 0) { + + int rc; + + if (pkgdb_open(0) == -1) + err(1, "cannot open pkgdb"); + + rc = pkgdb_remove(argv[2]); + if (rc) { + if (errno) + perror("pkgdb_remove"); + else + printf("Key not present in pkgdb.\n"); + } + + pkgdb_close(); + + } else if (strcasecmp(argv[1], "add") == 0) { + + int rc; + + if (pkgdb_open(0) == -1) { + err(1, "cannot open pkgdb"); + } + + rc = pkgdb_store(argv[2], argv[3]); + switch (rc) { + case -1: + perror("pkgdb_store"); + break; + case 1: + printf("Key already present.\n"); + break; + default: + /* 0: everything ok */ + break; + } + + pkgdb_close(); + + } +#endif + else { + usage(); + } + + return 0; +} + +void +usage(void) +{ + printf("usage: pkg_admin [-V] command args ...\n" + "Where 'commands' and 'args' are:\n" + " rebuild - rebuild pkgdb from +CONTENTS files\n" + " check [pkg ...] - check md5 checksum of installed files\n" +#ifdef PKGDB_DEBUG + " add key value - add key & value\n" + " delete key - delete reference to key\n" +#endif + " lsall /path/to/pkgpattern - list all pkgs matching the pattern\n" + " lsbest /path/to/pkgpattern - list pkgs matching the pattern best\n" + " dump - dump database\n" + " pmatch pattern pkg - returns true if pkg matches pattern, false else\n"); + exit(1); +} + +void +cleanup(int signo) +{ + ; +} diff --git a/pkgtools/pkg_install/files/admin/pkg_admin.1 b/pkgtools/pkg_install/files/admin/pkg_admin.1 new file mode 100644 index 00000000000..91c405b3557 --- /dev/null +++ b/pkgtools/pkg_install/files/admin/pkg_admin.1 @@ -0,0 +1,147 @@ +.\" $NetBSD: pkg_admin.1,v 1.1.1.1 2002/12/20 18:13:54 schmonz Exp $ +.\" +.\" Copyright (c) 1999 Hubert Feyrer. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Hubert Feyrer for +.\" the NetBSD Project. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 4, 2002 +.Dt PKG_ADMIN 1 +.Os +.Sh NAME +.Nm pkg_admin +.Nd perform various administrative tasks to the pkg system +.Sh SYNOPSIS +.Nm +.Op Fl V +.Ar command Op args ... +.Sh DESCRIPTION +This command performs various administrative tasks around the +.Nx +Packages System. +Available commands are: +.Pp +.Bl -tag -width check +.It Fl V +Print version number and exit. +.It Cm check Op Ar pkg ... +Use this command to check the files belonging to some or all of the +packages installed on the local machine against their MD5 checksum +noted in their +CONTENTS files. +If no additional argument is given, the files of all installed packages +are checked, else only the named packages will be checked (wildcards can +be used here, see +.Xr pkg_info 1 ) . +.Pp +The packages' +CONTENTS files will be parsed and the MD5 +checksum will be checked for every file found. +A warning message is printed if the expected checksum differs from the +checksum of the file on disk. +.Pp +.It Cm dump +Dump the contents of the package database, similar to +.Cm pkg_info -F . +Columns are printed for the keyfield used in the pkgdb - the filename -, +and the data field - the package the file belongs to. +.It Cm lsall /dir/pkgpattern +.It Cm lsbest /dir/pkgpattern +List all/best package matching pattern in the given directory. +Can be used to work around limitations of /bin/sh and other +filename globbing mechanisms. +This option implements matching of +pkg-wildcards against arbitrary files, useful mainly in the build +system itself. +See +.Xr pkg_info 1 +for a description of the pattern. +.Pp +Example: +.Bd -literal +yui# cd /usr/pkgsrc/packages/i386ELF/All/ +yui# ls unzip* +unzip-5.40.tgz unzip-5.41.tgz +yui# pkg_admin lsall 'unzip*' +unzip-5.40.tgz +unzip-5.41.tgz +yui# pkg_admin lsall 'unzip\*[Ge]5.40' +unzip-5.40.tgz +unzip-5.41.tgz +yui# pkg_admin lsall 'unzip\*[Ge]5.41' +unzip-5.41.tgz +yui# pkg_admin lsbest 'unzip\*[Ge]5.40' +unzip-5.41.tgz +yui# pkg_admin lsall /usr/pkgsrc/packages/i386ELF/All/'{mit,unproven}-pthread*' +/usr/pkgsrc/packages/i386ELF/All/mit-pthreads-1.60b6.tgz +/usr/pkgsrc/packages/i386ELF/All/unproven-pthreads-0.15.tgz +.Ed +.It Cm pmatch pattern pkg +Returns true if pkg matches pattern, false else. +.It Cm rebuild +Rebuild the package database mapping from scratch, scanning +subdirectories in +.Pa /var/db/pkg +for +.Pa +CONTENTS +files, parsing them and writing the resulting absolute pathnames +together with the package they belong to into the package database. +.Pp +This option is intended to be used for upgrading from non-pkgdb-pkg_* +tools to pkgdb-pkg_* tools, further manipulation of the pkgdb will be +done by +.Xr pkg_add 1 , +.Xr pkg_delete 1 , +and +.Xr pkg_create 1 . +.Pp +Needs to be run as root. +.Pp +.El +.Sh ENVIRONMENT +.Bl -tag -width PKG_DBDIR -compact +.It Ev PKG_DBDIR +Where to register packages instead of +.Pa /var/db/pkg . +.El +.Sh FILES +.Bl -tag -width /var/db/pkg/pkgdb.byfile.db -compact +.It Pa /var/db/pkg/pkgdb.byfile.db +.It Pa /var/db/pkg/\*[Lt]pkg\*[Gt]/+CONTENTS +.El +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr packages 7 +.Sh HISTORY +The +.Nm +command first appeared in +.Nx 1.4 . +.Sh AUTHORS +The +.Nm +command was written by Hubert Feyrer. diff --git a/pkgtools/pkg_install/files/admin/pkg_admin.cat1 b/pkgtools/pkg_install/files/admin/pkg_admin.cat1 new file mode 100644 index 00000000000..b8b348004dc --- /dev/null +++ b/pkgtools/pkg_install/files/admin/pkg_admin.cat1 @@ -0,0 +1,92 @@ +PKG_ADMIN(1) NetBSD Reference Manual PKG_ADMIN(1) + +NNAAMMEE + ppkkgg__aaddmmiinn - perform various administrative tasks to the pkg system + +SSYYNNOOPPSSIISS + ppkkgg__aaddmmiinn [--VV] _c_o_m_m_a_n_d [args ...] + +DDEESSCCRRIIPPTTIIOONN + This command performs various administrative tasks around the NetBSD + Packages System. Available commands are: + + --VV Print version number and exit. + + cchheecckk [_p_k_g _._._.] + Use this command to check the files belonging to some or all of + the packages installed on the local machine against their MD5 + checksum noted in their +CONTENTS files. If no additional argu- + ment is given, the files of all installed packages are checked, + else only the named packages will be checked (wildcards can be + used here, see pkg_info(1)). + + The packages' +CONTENTS files will be parsed and the MD5 checksum + will be checked for every file found. A warning message is print- + ed if the expected checksum differs from the checksum of the file + on disk. + + dduummpp Dump the contents of the package database, similar to ppkkgg__iinnffoo --FF. + Columns are printed for the keyfield used in the pkgdb - the file- + name -, and the data field - the package the file belongs to. + + llssaallll //ddiirr//ppkkggppaatttteerrnn + + llssbbeesstt //ddiirr//ppkkggppaatttteerrnn + List all/best package matching pattern in the given directory. + Can be used to work around limitations of /bin/sh and other file- + name globbing mechanisms. This option implements matching of pkg- + wildcards against arbitrary files, useful mainly in the build sys- + tem itself. See pkg_info(1) for a description of the pattern. + + Example: + + yui# cd /usr/pkgsrc/packages/i386ELF/All/ + yui# ls unzip* + unzip-5.40.tgz unzip-5.41.tgz + yui# pkg_admin lsall 'unzip*' + unzip-5.40.tgz + unzip-5.41.tgz + yui# pkg_admin lsall 'unzip>=5.40' + unzip-5.40.tgz + unzip-5.41.tgz + yui# pkg_admin lsall 'unzip>=5.41' + unzip-5.41.tgz + yui# pkg_admin lsbest 'unzip>=5.40' + unzip-5.41.tgz + yui# pkg_admin lsall /usr/pkgsrc/packages/i386ELF/All/'{mit,unproven}-pthread*' + /usr/pkgsrc/packages/i386ELF/All/mit-pthreads-1.60b6.tgz + /usr/pkgsrc/packages/i386ELF/All/unproven-pthreads-0.15.tgz + + ppmmaattcchh ppaatttteerrnn ppkkgg + Returns true if pkg matches pattern, false else. + + rreebbuuiilldd + Rebuild the package database mapping from scratch, scanning subdi- + rectories in _/_v_a_r_/_d_b_/_p_k_g for _+_C_O_N_T_E_N_T_S files, parsing them and + writing the resulting absolute pathnames together with the package + they belong to into the package database. + + This option is intended to be used for upgrading from non-pkgdb- + pkg_* tools to pkgdb-pkg_* tools, further manipulation of the + pkgdb will be done by pkg_add(1), pkg_delete(1), and + pkg_create(1). + + Needs to be run as root. + +EENNVVIIRROONNMMEENNTT + PKG_DBDIR Where to register packages instead of _/_v_a_r_/_d_b_/_p_k_g. + +FFIILLEESS + /var/db/pkg/pkgdb.byfile.db + /var/db/pkg/<pkg>/+CONTENTS + +SSEEEE AALLSSOO + pkg_add(1), pkg_create(1), pkg_delete(1), pkg_info(1), packages(7) + +HHIISSTTOORRYY + The ppkkgg__aaddmmiinn command first appeared in NetBSD 1.4. + +AAUUTTHHOORRSS + The ppkkgg__aaddmmiinn command was written by Hubert Feyrer. + +NetBSD 1.6 August 4, 2002 2 diff --git a/pkgtools/pkg_install/files/configure b/pkgtools/pkg_install/files/configure new file mode 100755 index 00000000000..10500cf59c4 --- /dev/null +++ b/pkgtools/pkg_install/files/configure @@ -0,0 +1,3084 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_default_prefix=/usr/pkg +ac_help="$ac_help + --with-pkgdbdir=DIR Where to put the pkg database (/var/db/pkg)" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=add/add.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + + +# Check whether --with-pkgdbdir or --without-pkgdbdir was given. +if test "${with_pkgdbdir+set}" = set; then + withval="$with_pkgdbdir" + pkgdbdir="$with_pkgdbdir" +else + pkgdbdir="/var/db/pkg" +fi + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:573: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:628: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:658: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:709: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:741: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 752 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:757: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:783: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:788: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:797: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:816: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:850: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +for ac_prog in ar +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:882: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AR="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AR="$ac_cv_prog_AR" +if test -n "$AR"; then + echo "$ac_t""$AR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AR" && break +done + +for ac_prog in chmod +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:916: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_CHMOD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$CHMOD" in + /*) + ac_cv_path_CHMOD="$CHMOD" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_CHMOD="$CHMOD" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_CHMOD="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +CHMOD="$ac_cv_path_CHMOD" +if test -n "$CHMOD"; then + echo "$ac_t""$CHMOD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CHMOD" && break +done + +for ac_prog in chown +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:956: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_CHOWN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$CHOWN" in + /*) + ac_cv_path_CHOWN="$CHOWN" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_CHOWN="$CHOWN" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_CHOWN="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +CHOWN="$ac_cv_path_CHOWN" +if test -n "$CHOWN"; then + echo "$ac_t""$CHOWN" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CHOWN" && break +done + +for ac_prog in chgrp +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:996: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_CHGRP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$CHGRP" in + /*) + ac_cv_path_CHGRP="$CHGRP" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_CHGRP="$CHGRP" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_CHGRP="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +CHGRP="$ac_cv_path_CHGRP" +if test -n "$CHGRP"; then + echo "$ac_t""$CHGRP" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CHGRP" && break +done + +for ac_prog in digest +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1036: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_DIGEST'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$DIGEST" in + /*) + ac_cv_path_DIGEST="$DIGEST" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_DIGEST="$DIGEST" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_DIGEST="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +DIGEST="$ac_cv_path_DIGEST" +if test -n "$DIGEST"; then + echo "$ac_t""$DIGEST" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$DIGEST" && break +done + +for ac_prog in mkdir +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1076: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MKDIR" in + /*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_MKDIR="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +MKDIR="$ac_cv_path_MKDIR" +if test -n "$MKDIR"; then + echo "$ac_t""$MKDIR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$MKDIR" && break +done + +for ac_prog in mtree +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1116: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MTREE'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MTREE" in + /*) + ac_cv_path_MTREE="$MTREE" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_MTREE="$MTREE" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_MTREE="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +MTREE="$ac_cv_path_MTREE" +if test -n "$MTREE"; then + echo "$ac_t""$MTREE" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$MTREE" && break +done + +for ac_prog in rm +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1156: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$RM" in + /*) + ac_cv_path_RM="$RM" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_RM="$RM" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_RM="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +RM="$ac_cv_path_RM" +if test -n "$RM"; then + echo "$ac_t""$RM" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$RM" && break +done + +for ac_prog in rmdir +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1196: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_RMDIR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$RMDIR" in + /*) + ac_cv_path_RMDIR="$RMDIR" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_RMDIR="$RMDIR" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_RMDIR="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +RMDIR="$ac_cv_path_RMDIR" +if test -n "$RMDIR"; then + echo "$ac_t""$RMDIR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$RMDIR" && break +done + +for ac_prog in tar +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1236: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_TAR_FULLPATHNAME'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$TAR_FULLPATHNAME" in + /*) + ac_cv_path_TAR_FULLPATHNAME="$TAR_FULLPATHNAME" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_TAR_FULLPATHNAME="$TAR_FULLPATHNAME" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_TAR_FULLPATHNAME="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +TAR_FULLPATHNAME="$ac_cv_path_TAR_FULLPATHNAME" +if test -n "$TAR_FULLPATHNAME"; then + echo "$ac_t""$TAR_FULLPATHNAME" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$TAR_FULLPATHNAME" && break +done + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1273: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 1288 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1294: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 1305 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1311: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 1322 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1328: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1353: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1358 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1383 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1401 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 1422 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in db1/db.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1460: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1465 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1470: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in assert.h db.h dirent.h err.h fcntl.h fnmatch.h limits.h md5.h md5global.h netdb.h pwd.h regex.h signal.h stdlib.h string.h termios.h time.h unistd.h vis.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1500: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1505 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1510: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in sys/file.h sys/ioctl.h sys/mount.h sys/param.h sys/queue.h sys/resource.h sys/stat.h sys/time.h sys/types.h sys/vfs.h sys/wait.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1540: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1545 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1550: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + +echo $ac_n "checking for MD5File in -lmd""... $ac_c" 1>&6 +echo "configure:1578: checking for MD5File in -lmd" >&5 +ac_lib_var=`echo md'_'MD5File | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lmd $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1586 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char MD5File(); + +int main() { +MD5File() +; return 0; } +EOF +if { (eval echo configure:1597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo md | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lmd $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking for dbopen in -ldb1""... $ac_c" 1>&6 +echo "configure:1625: checking for dbopen in -ldb1" >&5 +ac_lib_var=`echo db1'_'dbopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldb1 $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1633 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dbopen(); + +int main() { +dbopen() +; return 0; } +EOF +if { (eval echo configure:1644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo db1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-ldb1 $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + + +for ac_func in chflags +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1675: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1680 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1703: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in dbopen +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1730: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1735 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in err +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1785: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1790 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in errx +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1840: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1845 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in fgetln +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1895: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1900 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in getprogname +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1950: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1955 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1978: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in mkdtemp +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2005: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2010 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in setenv +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2060: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2065 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in setprogname +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2115: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2120 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2143: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in statfs +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2170: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2175 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2198: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in statvfs +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2225: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2230 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2253: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in strsep +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2280: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2285 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in strlcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2335: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2340 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2363: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in unsetenv +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2390: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2395 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in warn +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2445: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2450 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2473: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in warnx +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2500: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2505 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in MD5File +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2555: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2560 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2583: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:2609: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2614 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:2663: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:2684: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2689 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile lib/Makefile lib/lib.h add/Makefile admin/Makefile create/Makefile delete/Makefile info/Makefile lib/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@pkgdbdir@%$pkgdbdir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC@%$CC%g +s%@RANLIB@%$RANLIB%g +s%@AR@%$AR%g +s%@CHMOD@%$CHMOD%g +s%@CHOWN@%$CHOWN%g +s%@CHGRP@%$CHGRP%g +s%@DIGEST@%$DIGEST%g +s%@MKDIR@%$MKDIR%g +s%@MTREE@%$MTREE%g +s%@RM@%$RM%g +s%@RMDIR@%$RMDIR%g +s%@TAR_FULLPATHNAME@%$TAR_FULLPATHNAME%g +s%@CPP@%$CPP%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile lib/Makefile lib/lib.h add/Makefile admin/Makefile create/Makefile delete/Makefile info/Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="lib/config.h" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <<EOF + +EOF +cat >> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/pkgtools/pkg_install/files/configure.in b/pkgtools/pkg_install/files/configure.in new file mode 100644 index 00000000000..c0d3b6ec96f --- /dev/null +++ b/pkgtools/pkg_install/files/configure.in @@ -0,0 +1,64 @@ +enl Process this file with autoconf to produce a configure script. +AC_INIT(add/add.h) +AC_CONFIG_HEADER(lib/config.h) + +dnl Set the prefix +AC_PREFIX_DEFAULT(/usr/pkg) + +dnl Set the default pkg database dir +AC_ARG_WITH(pkgdbdir, +[ --with-pkgdbdir=DIR Where to put the pkg database (/var/db/pkg)], +[ pkgdbdir="$with_pkgdbdir" ], +[ pkgdbdir="/var/db/pkg" ]) +AC_SUBST(pkgdbdir) + +dnl Checks for programs. +AC_PROG_INSTALL +AC_PROG_CC +AC_PROG_RANLIB +AC_CHECK_PROGS(AR, ar) +AC_PATH_PROGS(CHMOD, chmod) +AC_PATH_PROGS(CHOWN, chown) +AC_PATH_PROGS(CHGRP, chgrp) +AC_PATH_PROGS(DIGEST, digest) +AC_PATH_PROGS(MKDIR, mkdir) +AC_PATH_PROGS(MTREE, mtree) +AC_PATH_PROGS(RM, rm) +AC_PATH_PROGS(RMDIR, rmdir) +AC_PATH_PROGS(TAR_FULLPATHNAME, tar) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(db1/db.h) +AC_CHECK_HEADERS(assert.h db.h dirent.h err.h fcntl.h fnmatch.h limits.h md5.h md5global.h netdb.h pwd.h regex.h signal.h stdlib.h string.h termios.h time.h unistd.h vis.h) +AC_CHECK_HEADERS(sys/file.h sys/ioctl.h sys/mount.h sys/param.h sys/queue.h sys/resource.h sys/stat.h sys/time.h sys/types.h sys/vfs.h sys/wait.h) + +dnl Check for libraries +AC_CHECK_LIB(md, MD5File) +AC_CHECK_LIB(db1, dbopen) + +dnl Check for functions +AC_CHECK_FUNCS(chflags) +AC_CHECK_FUNCS(dbopen) +AC_CHECK_FUNCS(err) +AC_CHECK_FUNCS(errx) +AC_CHECK_FUNCS(fgetln) +AC_CHECK_FUNCS(getprogname) +AC_CHECK_FUNCS(mkdtemp) +AC_CHECK_FUNCS(setenv) +AC_CHECK_FUNCS(setprogname) +AC_CHECK_FUNCS(statfs) +AC_CHECK_FUNCS(statvfs) +AC_CHECK_FUNCS(strsep) +AC_CHECK_FUNCS(strlcpy) +AC_CHECK_FUNCS(unsetenv) +AC_CHECK_FUNCS(warn) +AC_CHECK_FUNCS(warnx) +AC_CHECK_FUNCS(MD5File) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +dnl that's it for now... +AC_OUTPUT(Makefile lib/Makefile lib/lib.h add/Makefile admin/Makefile create/Makefile delete/Makefile info/Makefile) diff --git a/pkgtools/pkg_install/files/create/Makefile.in b/pkgtools/pkg_install/files/create/Makefile.in new file mode 100644 index 00000000000..cd01e38ffa4 --- /dev/null +++ b/pkgtools/pkg_install/files/create/Makefile.in @@ -0,0 +1,39 @@ +# From NetBSD: Makefile,v 1.4 1997/10/17 14:53:47 lukem Exp $ + +PREFIX= @prefix@ +INSTALL= @INSTALL@ + +mandir= ${PREFIX}/man +mandircat1= ${mandir}/cat1 + +CC= @CC@ +CCLD= $(CC) +LIBS= @LIBS@ -linstall +CPPFLAGS= @CPPFLAGS@ +DEFS= @DEFS@ -I. -I@srcdir@ -I../lib +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ -L../lib + +LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ +COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) + +PROG= pkg_create + +SRCS= main.c perform.c pl.c +OBJS= main.o perform.o pl.o + +all: ${PROG} + +${PROG}: ${OBJS} + ${LINK} ${OBJS} ${LIBS} + +.c.o: + $(COMPILE) -c $< -o $@ + +clean: + rm -f ${OBJS} ${PROG} + +install: + ${INSTALL} ${PROG} ${PREFIX}/sbin + ${INSTALL} -m 755 -d ${mandircat1} + ${INSTALL} -m 444 ${PROG}.cat1 ${mandircat1}/${PROG}.1 diff --git a/pkgtools/pkg_install/files/create/create.h b/pkgtools/pkg_install/files/create/create.h new file mode 100644 index 00000000000..1877f7ac7cc --- /dev/null +++ b/pkgtools/pkg_install/files/create/create.h @@ -0,0 +1,57 @@ +/* $NetBSD: create.h,v 1.1.1.1 2002/12/20 18:14:09 schmonz Exp $ */ + +/* from FreeBSD Id: create.h,v 1.13 1997/10/08 07:46:19 charnier Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the create command. + * + */ + +#ifndef _INST_CREATE_H_INCLUDE +#define _INST_CREATE_H_INCLUDE + +extern char *Prefix; +extern char *Comment; +extern char *Desc; +extern char *Display; +extern char *Install; +extern char *DeInstall; +extern char *Contents; +extern char *Require; +extern char *ExcludeFrom; +extern char *Mtree; +extern char *Pkgdeps; +extern char *Pkgcfl; +extern char *BuildVersion; +extern char *BuildInfo; +extern char *SizePkg; +extern char *SizeAll; +extern char *SrcDir; +extern char *realprefix; +extern char PlayPen[]; +extern size_t PlayPenSize; +extern int Dereference; +extern int PlistOnly; +extern int RelativeLinks; +extern int ReorderDirs; +extern int update_pkgdb; + +void check_list(char *, package_t *, const char *); +void copy_plist(char *, package_t *); + +#endif /* _INST_CREATE_H_INCLUDE */ diff --git a/pkgtools/pkg_install/files/create/main.c b/pkgtools/pkg_install/files/create/main.c new file mode 100644 index 00000000000..c4d94393d64 --- /dev/null +++ b/pkgtools/pkg_install/files/create/main.c @@ -0,0 +1,225 @@ +/* $NetBSD: main.c,v 1.1.1.1 2002/12/20 18:14:09 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: main.c,v 1.17 1997/10/08 07:46:23 charnier Exp"; +#else +__RCSID("$NetBSD: main.c,v 1.1.1.1 2002/12/20 18:14:09 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the create module. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" +#include "create.h" + +static const char Options[] = "ORhlVvFf:p:P:C:c:d:i:k:L:r:t:X:D:m:s:S:b:B:UI:"; + +char *Prefix = NULL; +char *Comment = NULL; +char *Desc = NULL; +char *Display = NULL; +char *Install = NULL; +char *DeInstall = NULL; +char *Contents = NULL; +char *Require = NULL; +char *ExcludeFrom = NULL; +char *Mtree = NULL; +char *Pkgdeps = NULL; +char *Pkgcfl = NULL; +char *BuildVersion = NULL; +char *BuildInfo = NULL; +char *SizePkg = NULL; +char *SizeAll = NULL; +char *SrcDir = NULL; +char *realprefix = NULL; +char PlayPen[FILENAME_MAX]; +size_t PlayPenSize = sizeof(PlayPen); +int update_pkgdb = 1; +int Dereference = 0; +int PlistOnly = 0; +int RelativeLinks = 0; +int ReorderDirs = 0; +Boolean File2Pkg = FALSE; + +static void +usage(void) +{ + fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", + "usage: pkg_create [-ORUhlVv] [-P dpkgs] [-C cpkgs] [-p prefix] [-f contents]", + " [-i iscript] [-k dscript] [-r rscript] [-t template]", + " [-X excludefile] [-D displayfile] [-m mtreefile]", + " [-b build-version-file] [-B build-info-file]", + " [-I realprefix]", + " -c comment -d description -f packlist pkg-name"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch; + lpkg_head_t pkgs; + lpkg_t *lpp; + + setprogname(argv[0]); + + while ((ch = getopt(argc, argv, Options)) != -1) + switch (ch) { + case 'v': + Verbose = TRUE; + break; + + case 'I': + realprefix = optarg; + break; + + case 'O': + PlistOnly = 1; + break; + + case 'R': + ReorderDirs = 1; + break; + + case 'U': + update_pkgdb = 0; + break; + + case 'p': + Prefix = optarg; + break; + + case 's': + SizePkg = optarg; + break; + + case 'S': + SizeAll = optarg; + break; + + case 'f': + Contents = optarg; + break; + + case 'c': + Comment = optarg; + break; + + case 'd': + Desc = optarg; + break; + + case 'i': + Install = optarg; + break; + + case 'k': + DeInstall = optarg; + break; + + case 'l': + RelativeLinks = 1; + break; + + case 'L': + SrcDir = optarg; + break; + + case 'r': + Require = optarg; + break; + + case 't': + strcpy(PlayPen, optarg); + break; + + case 'X': + ExcludeFrom = optarg; + break; + + case 'h': + Dereference = 1; + break; + + case 'D': + Display = optarg; + break; + + case 'm': + Mtree = optarg; + break; + + case 'P': + Pkgdeps = optarg; + break; + + case 'C': + Pkgcfl = optarg; + break; + + case 'b': + BuildVersion = optarg; + break; + + case 'B': + BuildInfo = optarg; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case '?': + default: + usage(); + break; + } + + argc -= optind; + argv += optind; + + TAILQ_INIT(&pkgs); + + /* Get all the remaining package names, if any */ + while (*argv) { + lpp = alloc_lpkg(*argv); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + argv++; + } + + /* If no packages, yelp */ + lpp = TAILQ_FIRST(&pkgs); + if (lpp == NULL) + warnx("missing package name"), usage(); + lpp = TAILQ_NEXT(lpp, lp_link); + if (lpp != NULL) + warnx("only one package name allowed ('%s' extraneous)", + lpp->lp_name), + usage(); + if (!pkg_perform(&pkgs)) { + if (Verbose) + warnx("package creation failed"); + return 1; + } else + return 0; +} diff --git a/pkgtools/pkg_install/files/create/perform.c b/pkgtools/pkg_install/files/create/perform.c new file mode 100644 index 00000000000..7e61890175a --- /dev/null +++ b/pkgtools/pkg_install/files/create/perform.c @@ -0,0 +1,417 @@ +/* $NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:14:10 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp"; +#else +__RCSID("$NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:14:10 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the create module. + * + */ + +#include "lib.h" +#include "create.h" + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <signal.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include <unistd.h> + +static char *Home; + +static void +make_dist(const char *home, const char *pkg, const char *suffix, const package_t *plist) +{ + char tball[FILENAME_MAX]; + const plist_t *p; + int ret; + char *args[50]; /* Much more than enough. */ + int nargs = 1; + int pipefds[2]; + FILE *totar; + pid_t pid; + + if ((args[0] = strrchr(TAR_FULLPATHNAME, '/')) == NULL) + args[0] = TAR_FULLPATHNAME; + else + args[0]++; + + if (*pkg == '/') + (void) snprintf(tball, sizeof(tball), "%s.%s", pkg, suffix); + else + (void) snprintf(tball, sizeof(tball), "%s/%s.%s", home, pkg, suffix); + + args[nargs++] = "-c"; + args[nargs++] = "-f"; + args[nargs++] = tball; + if (strstr(suffix, "bz")) { + args[nargs++] = "--use-compress-program"; + args[nargs++] = "bzip2"; + } else if (strchr(suffix, 'z'))/* Compress/gzip? */ + args[nargs++] = "-z"; + if (Dereference) + args[nargs++] = "-h"; + if (ExcludeFrom) { + args[nargs++] = "-X"; + args[nargs++] = ExcludeFrom; + } + args[nargs++] = "-T"; /* Take filenames from file instead of args. */ + args[nargs++] = "-"; /* Use stdin for the file. */ + args[nargs] = NULL; + + if (Verbose) + printf("Creating gzip'd binary package in '%s'\n", tball); + + /* Set up a pipe for passing the filenames, and fork off a tar process. */ + if (pipe(pipefds) == -1) { + cleanup(0); + errx(2, "cannot create pipe"); + } + if ((pid = fork()) == -1) { + cleanup(0); + errx(2, "cannot fork process for %s", TAR_FULLPATHNAME); + } + if (pid == 0) { /* The child */ + dup2(pipefds[0], 0); + close(pipefds[0]); + close(pipefds[1]); + execvp(TAR_FULLPATHNAME, args); + cleanup(0); + errx(2, "failed to execute %s command", TAR_FULLPATHNAME); + } + + /* Meanwhile, back in the parent process ... */ + close(pipefds[0]); + if ((totar = fdopen(pipefds[1], "w")) == NULL) { + cleanup(0); + errx(2, "fdopen failed"); + } + + fprintf(totar, "%s\n", CONTENTS_FNAME); + fprintf(totar, "%s\n", COMMENT_FNAME); + fprintf(totar, "%s\n", DESC_FNAME); + + if (Install) { + fprintf(totar, "%s\n", INSTALL_FNAME); + } + if (DeInstall) { + fprintf(totar, "%s\n", DEINSTALL_FNAME); + } + if (Require) { + fprintf(totar, "%s\n", REQUIRE_FNAME); + } + if (Display) { + fprintf(totar, "%s\n", DISPLAY_FNAME); + } + if (Mtree) { + fprintf(totar, "%s\n", MTREE_FNAME); + } + if (BuildVersion) { + (void) fprintf(totar, "%s\n", BUILD_VERSION_FNAME); + } + if (BuildInfo) { + (void) fprintf(totar, "%s\n", BUILD_INFO_FNAME); + } + if (SizePkg) { + (void) fprintf(totar, "%s\n", SIZE_PKG_FNAME); + } + if (SizeAll) { + (void) fprintf(totar, "%s\n", SIZE_ALL_FNAME); + } + + for (p = plist->head; p; p = p->next) { + if (p->type == PLIST_FILE) { + fprintf(totar, "%s\n", p->name); + } else if (p->type == PLIST_CWD || p->type == PLIST_SRC) { + + /* XXX let PLIST_SRC override PLIST_CWD */ + if (p->type == PLIST_CWD && p->next != NULL && + p->next->type == PLIST_SRC) { + continue; + } + + fprintf(totar, "-C\n%s\n", p->name); + } else if (p->type == PLIST_IGNORE) { + p = p->next; + } + } + + fclose(totar); + wait(&ret); + /* assume either signal or bad exit is enough for us */ + if (ret) { + cleanup(0); + errx(2, "%s command failed with code %d", TAR_FULLPATHNAME, ret); + } +} + +static void +sanity_check(void) +{ + if (!Comment) { + cleanup(0); + errx(2, "required package comment string is missing (-c comment)"); + } + if (!Desc) { + cleanup(0); + errx(2, "required package description string is missing (-d desc)"); + } + if (!Contents) { + cleanup(0); + errx(2, "required package contents list is missing (-f [-]file)"); + } +} + + +/* + * Clean up those things that would otherwise hang around + */ +void +cleanup(int sig) +{ + 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); +} + +int +pkg_perform(lpkg_head_t *pkgs) +{ + const char *pkg; + char *cp; + FILE *pkg_in, *fp; + package_t plist; + char *suffix; /* What we tack on to the end of the finished package */ + lpkg_t *lpp; + char installed[FILENAME_MAX]; + + lpp = TAILQ_FIRST(pkgs); + pkg = lpp->lp_name; /* Only one arg to create */ + + /* Preliminary setup */ + sanity_check(); + if (Verbose && !PlistOnly) + printf("Creating package %s\n", pkg); + get_dash_string(&Comment); + get_dash_string(&Desc); + if (IS_STDIN(Contents)) + pkg_in = stdin; + else { + pkg_in = fopen(Contents, "r"); + if (!pkg_in) { + cleanup(0); + errx(2, "unable to open contents file '%s' for input", Contents); + } + } + plist.head = plist.tail = NULL; + + /* Break the package name into base and desired suffix (if any) */ + if ((cp = strrchr(pkg, '.')) != NULL) { + suffix = cp + 1; + *cp = '\0'; + } else + suffix = "tgz"; + + /* If a SrcDir override is set, add it now */ + if (SrcDir) { + if (Verbose && !PlistOnly) + printf("Using SrcDir value of %s\n", (realprefix) ? realprefix : SrcDir); + add_plist(&plist, PLIST_SRC, SrcDir); + } + + /* Stick the dependencies, if any, at the top */ + if (Pkgdeps) { + if (Verbose && !PlistOnly) + printf("Registering depends:"); + while (Pkgdeps) { + cp = strsep(&Pkgdeps, " \t\n"); + if (*cp) { + if (findmatchingname(_pkgdb_getPKGDB_DIR(), cp, note_whats_installed, installed) > 0) { + add_plist(&plist, PLIST_BLDDEP, installed); + } + add_plist(&plist, PLIST_PKGDEP, cp); + if (Verbose && !PlistOnly) + printf(" %s", cp); + } + } + 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"); + } + + /* Slurp in the packing list */ + read_plist(&plist, pkg_in); + + if (pkg_in != stdin) + fclose(pkg_in); + + /* Prefix should override the packing list */ + if (Prefix) { + delete_plist(&plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&plist, PLIST_CWD, Prefix); + } + /* + * Run down the list and see if we've named it, if not stick in a name + * at the top. + */ + if (find_plist(&plist, PLIST_NAME) == NULL) { + add_plist_top(&plist, PLIST_NAME, basename_of(pkg)); + } + + /* + * We're just here for to dump out a revised plist for the FreeBSD ports + * hack. It's not a real create in progress. + */ + if (PlistOnly) { + check_list(Home, &plist, basename_of(pkg)); + write_plist(&plist, stdout, realprefix); + exit(0); + } + + /* Make a directory to stomp around in */ + Home = make_playpen(PlayPen, PlayPenSize, 0); + signal(SIGINT, cleanup); + signal(SIGHUP, cleanup); + + /* Make first "real contents" pass over it */ + check_list(Home, &plist, basename_of(pkg)); + (void) umask(022); /* make sure gen'ed directories, files + * don't have group or other write bits. */ + + /* Now put the release specific items in */ + add_plist(&plist, PLIST_CWD, "."); + write_file(COMMENT_FNAME, Comment); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, COMMENT_FNAME); + write_file(DESC_FNAME, Desc); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DESC_FNAME); + + if (Install) { + copy_file(Home, Install, INSTALL_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, INSTALL_FNAME); + } + if (DeInstall) { + copy_file(Home, DeInstall, DEINSTALL_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME); + } + if (Require) { + copy_file(Home, Require, REQUIRE_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, REQUIRE_FNAME); + } + if (Display) { + copy_file(Home, Display, DISPLAY_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DISPLAY_FNAME); + add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME); + } + if (Mtree) { + copy_file(Home, Mtree, MTREE_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, MTREE_FNAME); + add_plist(&plist, PLIST_MTREE, MTREE_FNAME); + } + if (BuildVersion) { + copy_file(Home, BuildVersion, BUILD_VERSION_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, BUILD_VERSION_FNAME); + } + if (BuildInfo) { + copy_file(Home, BuildInfo, BUILD_INFO_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, BUILD_INFO_FNAME); + } + if (SizePkg) { + copy_file(Home, SizePkg, SIZE_PKG_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, SIZE_PKG_FNAME); + } + if (SizeAll) { + copy_file(Home, SizeAll, SIZE_ALL_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, SIZE_ALL_FNAME); + } + + /* Finally, write out the packing list */ + fp = fopen(CONTENTS_FNAME, "w"); + if (!fp) { + cleanup(0); + errx(2, "can't open file %s for writing", CONTENTS_FNAME); + } + write_plist(&plist, fp, realprefix); + if (fclose(fp)) { + cleanup(0); + errx(2, "error while closing %s", CONTENTS_FNAME); + } + + /* And stick it into a tar ball */ + make_dist(Home, pkg, suffix, &plist); + + /* Cleanup */ + free(Comment); + free(Desc); + free_plist(&plist); + leave_playpen(Home); + + return TRUE; /* Success */ +} diff --git a/pkgtools/pkg_install/files/create/pkg_create.1 b/pkgtools/pkg_install/files/create/pkg_create.1 new file mode 100644 index 00000000000..71c07f0421d --- /dev/null +++ b/pkgtools/pkg_install/files/create/pkg_create.1 @@ -0,0 +1,528 @@ +.\" $NetBSD: pkg_create.1,v 1.1.1.1 2002/12/20 18:14:10 schmonz Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintainance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)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. +.\" +.\" [jkh] Took John's changes back and made some additional extensions for +.\" better integration with FreeBSD's new ports collection. +.\" +.Dd April 21, 1995 +.Dt PKG_CREATE 1 +.Os +.Sh NAME +.Nm pkg_create +.Nd a utility for creating software package distributions +.Sh SYNOPSIS +.Nm +.Op Fl hlORUVv +.Bk -words +.Op Fl B Ar build-info-file +.Ek +.Bk -words +.Op Fl C Ar cpkgs +.Ek +.Bk -words +.Op Fl D Ar displayfile +.Ek +.Bk -words +.Op Fl P Ar dpkgs +.Ek +.Bk -words +.Op Fl X Ar excludefile +.Ek +.Bk -words +.Op Fl b Ar build-version-file +.Ek +.Bk -words +.Op Fl f Ar contents +.Ek +.Bk -words +.Op Fl i Ar iscript +.Ek +.Bk -words +.Op Fl I Ar realprefix +.Ek +.Bk -words +.Op Fl k Ar dscript +.Ek +.Bk -words +.Op Fl L Ar SrcDir +.Ek +.Bk -words +.Op Fl m Ar mtreefile +.Ek +.Bk -words +.Op Fl p Ar prefix +.Ek +.Bk -words +.Op Fl r Ar rscript +.Ek +.Bk -words +.Op Fl s Ar size-pkg-file +.Ek +.Bk -words +.Op Fl S Ar size-all-file +.Ek +.Bk -words +.Op Fl t Ar template +.Ek +.Bk -words +.Fl c Ar comment +.Ek +.Bk -words +.Fl d Ar description +.Ek +.Bk -words +.Fl f Ar packlist +.Ek +.Ar pkg-name +.Sh DESCRIPTION +The +.Nm +command is used to create packages that will subsequently be fed to +one of the package extraction/info utilities. +The input description and command line arguments for the creation of a +package are not really meant to be human-generated, though it is easy +enough to 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: +.Bl -tag -width indent +.It Fl B Ar build-info-file +Install the file +.Ar build-info-file +so that users of binary packages can see what +.Xr make 1 +definitions +were used to control the build when creating the +binary package. +This allows various build definitions to be retained in a binary package +and viewed wherever it is installed, using +.Xr pkg_info 1 . +.It Fl b Ar build-version-file +Install the file +.Ar build-version-file +so that users of binary packages can see what versions of +the files used to control the build were used when creating the +binary package. +This allows some fine-grained version control information to be retained +in a binary package and viewed wherever it is installed, using +.Xr pkg_info 1 . +.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 c Ar [-]desc +Fetch package ``one line description'' from file +.Ar desc +or, if preceded by +.Cm - , +the argument itself. +This string should also give some idea of which version of the product +(if any) the package represents. +.It Fl D Ar displayfile +Display the file after installing the package. +Useful for things like legal notices on almost-free software, etc. +.It Fl d Ar [-]desc +Fetch long description for package from file +.Ar desc +or, if preceded by +.Cm - , +the argument itself. +.It Fl f Ar packinglist +Fetch ``packing list'' for package from the file +.Ar packinglist +or +.Cm stdin +if +.Ar packinglist +is a +.Cm - +(dash). +.It Fl h +Force tar to follow symbolic links, so that the files they point to +are dumped, rather than the links themselves. +.It Fl I Ar realprefix +Provide the real prefix, as opposed to the staging prefix, for use in +staged installations of packages. +.It Fl i Ar iscript +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. +.It Fl k Ar dscript +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. +.It Fl L Ar SrcDir +This sets the package's @src directive; see below for a description +of what this does. +.It Fl l +Check that any symbolic links which are to be placed in the package are +relative to the current prefix. +This means using +.Xr unlink 2 +and +.Xr symlink 2 +to remove and re-link +any symbolic links which are targeted at full path names. +.It Fl m Ar mtreefile +Run +.Xr mtree 8 +with input from mtreefile before the package is installed. +Mtree is invoked as +.Cm mtree +.Fl u +.Fl f +.Ar mtreefile +.Fl d +.Fl e +.Fl p +.Pa prefix , +where +.Pa prefix +is the name of the first directory named by a +.Cm @cwd +directive. +.It Fl O +Go into a `packing list Only' mode. +This is used to do `fake pkg_add' operations when a package is installed. +In such cases, it is necessary to know what the final, adjusted packing +list will look like. +.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). +In addition, the exact versions of the packages referred to in the +.Ar dpkgs +list will be added to the packing list in the form of +.Cm @blddep +directives. +.It Fl p Ar prefix +Set +.Ar prefix +as the initial directory ``base'' to start from in selecting files for +the package. +.It Fl R +Re-order any directories in the pkg/PLIST file into reverse alphabetic +order, so that child directories will automatically be removed before +parent directories. +.It Fl r Ar rscript +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. +.It Fl S Ar size-all-file +Store the given file for later querying with the +.Xr pkg_info 1 +.Ar -S +flag. +The file is expected to contain the size (in bytes) of all files of +this package plus any required packages added up and stored as a +ASCII string, terminated by a newline. +.It Fl s Ar size-pkg-file +Store the given file for later querying with the +.Xr pkg_info 1 +.Ar -s +flag. +The file is expected to contain the the size (in bytes) of all files of +this package added up and stored as a ASCII string, terminated by a newline. +.It Fl t Ar template +Use +.Ar template +as the input to +.Xr mktemp 3 . +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. +.It Fl U +Do not update the package file database with any file information. +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.It Fl X Ar excludefile +Pass +.Ar excludefile +as a +.Fl -exclude-from +argument to +.Cm tar +when creating final package. +See +.Cm tar +man page (or run +.Cm tar +with +.Fl -help +flag) for further information on using this flag. +.El +.Sh PACKING LIST DETAILS +The ``packing list'' format (see +.Fl f ) +is fairly simple, being +nothing more than a single column of filenames to include in the +package. +However, since absolute pathnames are generally a bad idea +for a package that could be installed potentially anywhere, there is +another method of specifying where things are supposed to go +and, optionally, what ownership and mode information they should be +installed with. +This is done by embedding specialized command sequences +in the packing list. +Briefly described, these sequences are: +.Bl -tag -width indent -compact +.It Cm @cwd Ar directory +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 @src Ar directory +Set the internal directory pointer for _creation only_ to +.Ar directory . +That is to say that it overrides +.Cm @cwd +for package creation but not extraction. +.It Cm @exec Ar command +Execute +.Ar command +as part of the unpacking process. +If +.Ar command +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 +.Pa /usr/local +and the last extracted file was +.Pa bin/emacs . +.Bl -tag -width indent -compact +.It Cm "%F" +Expands to the last filename extracted (as specified), in the example case +.Pa bin/emacs +.It Cm "%D" +Expand to the current directory prefix, as set with +.Cm @cwd , +in the example case +.Pa /usr/local . +.It Cm "%B" +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" +Expand to the ``filename'' part of the fully qualified name, or +the converse of +.Cm %B , +being in the example case, +.Pa emacs . +.El +.It Cm @unexec Ar command +Execute +.Ar command +as part of the deinstallation process. +Expansion of special +.Cm % +sequences is the same as for +.Cm @exec . +This command is not executed during the package add, as +.Cm @exec +is, but rather when the package is deleted. +This is useful for deleting links and other ancillary files that were created +as a result of adding the package, but not directly known to the package's +table of contents (and hence not automatically removable). +The advantage of using +.Cm @unexec +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 ) . +.It Cm @mode Ar mode +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 +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 +Set default group ownership for all subsequently extracted files to +.Ar group . +Use without an arg to set back to default (extraction) +group ownership. +.It Cm @comment Ar string +Imbed a comment in the packing list. +Useful in trying to document some particularly hairy sequence that +may trip someone up later. +.It Cm @ignore +Used internally to tell extraction to ignore the next file (don't +copy it anywhere), as it's used for some special purpose. +.It Cm @ignore_inst +Similar to +.Cm @ignore , +but the ignoring of the next file is delayed one evaluation cycle. +This makes it possible to use this directive in the +.Ar packinglist +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 +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 +.Nm +will derive this field from the package name and add it automatically +if none is given. +.It Cm @dirrm Ar name +Declare directory +.Pa name +to be deleted at deinstall time. +By default, directories created by a package installation are not deleted +when the package is deinstalled; this provides an explicit directory cleanup +method. +This directive should appear at the end of the package list. +If more than one +.Cm @dirrm +directives are used, the directories are removed in the order specified. +The +.Pa name +directory will not be removed unless it is empty. +.It Cm @mtree Ar name +Declare +.Pa name +as an +.Xr mtree 8 +input file to be used at install time (see +.Fl m +above). +Only the first +.Cm @mtree +directive is honored. +.It Cm @display Ar name +Declare +.Pa name +as the file to be displayed at install time (see +.Fl D +above). +.It Cm @pkgdep Ar pkgname +Declare a dependency on the +.Ar pkgname +package. +The +.Ar pkgname +package must be installed before this package may be +installed, and this package must be deinstalled before the +.Ar pkgname +package is deinstalled. +Multiple +.Cm @pkgdep +directives may be used if the package depends on multiple other packages. +.It Cm @blddep Ar pkgname +Declare that this package was built with the exact version +of +.Ar pkgname +(since the +.Cm @pkgdep +directive may contain wildcards or relational +package version information). +.It Cm @pkgcfl Ar pkgcflname +Declare a conflict with the +.Ar pkgcflname +package, as the two packages contain references to the same files, +and so cannot co-exist on the same system. +.El +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr sysconf 3 , +.Xr packages 7 +.Sh HISTORY +The +.Nm +command first appeared in +.Fx . +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for +.Nx +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, pkg size recording etc. +.El +.Sh BUGS +Hard links between files in a distribution must be bracketed by +.Cm @cwd +directives in order to be preserved as hard links when the package is +extracted. +They additionally must not end up being split between +.Cm tar +invocations due to exec argument-space limitations (this depends on the +value returned by +.Fn sysconf _SC_ARG_MAX ) . diff --git a/pkgtools/pkg_install/files/create/pkg_create.cat1 b/pkgtools/pkg_install/files/create/pkg_create.cat1 new file mode 100644 index 00000000000..7ba95b827a2 --- /dev/null +++ b/pkgtools/pkg_install/files/create/pkg_create.cat1 @@ -0,0 +1,298 @@ +PKG_CREATE(1) NetBSD Reference Manual PKG_CREATE(1) + +NNAAMMEE + ppkkgg__ccrreeaattee - a utility for creating software package distributions + +SSYYNNOOPPSSIISS + ppkkgg__ccrreeaattee [--hhllOORRUUVVvv] [--BB _b_u_i_l_d_-_i_n_f_o_-_f_i_l_e] [--CC _c_p_k_g_s] [--DD _d_i_s_p_l_a_y_f_i_l_e] + [--PP _d_p_k_g_s] [--XX _e_x_c_l_u_d_e_f_i_l_e] [--bb _b_u_i_l_d_-_v_e_r_s_i_o_n_-_f_i_l_e] [--ff _c_o_n_t_e_n_t_s] + [--ii _i_s_c_r_i_p_t] [--II _r_e_a_l_p_r_e_f_i_x] [--kk _d_s_c_r_i_p_t] [--LL _S_r_c_D_i_r] [--mm _m_t_r_e_e_f_i_l_e] + [--pp _p_r_e_f_i_x] [--rr _r_s_c_r_i_p_t] [--ss _s_i_z_e_-_p_k_g_-_f_i_l_e] [--SS _s_i_z_e_-_a_l_l_-_f_i_l_e] + [--tt _t_e_m_p_l_a_t_e] --cc _c_o_m_m_e_n_t --dd _d_e_s_c_r_i_p_t_i_o_n --ff _p_a_c_k_l_i_s_t _p_k_g_-_n_a_m_e + +DDEESSCCRRIIPPTTIIOONN + The ppkkgg__ccrreeaattee command is used to create packages that will subsequently + be fed to one of the package extraction/info utilities. The input de- + scription and command line arguments for the creation of a package are + not really meant to be human-generated, though it is easy enough to 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 descrip- + tion of the input syntax is included in this document. + +OOPPTTIIOONNSS + The following command line options are supported: + + --BB _b_u_i_l_d_-_i_n_f_o_-_f_i_l_e + Install the file _b_u_i_l_d_-_i_n_f_o_-_f_i_l_e so that users of binary packages + can see what make(1) definitions were used to control the build + when creating the binary package. This allows various build def- + initions to be retained in a binary package and viewed wherever + it is installed, using pkg_info(1). + + --bb _b_u_i_l_d_-_v_e_r_s_i_o_n_-_f_i_l_e + Install the file _b_u_i_l_d_-_v_e_r_s_i_o_n_-_f_i_l_e so that users of binary pack- + ages can see what versions of the files used to control the build + were used when creating the binary package. This allows some + fine-grained version control information to be retained in a bi- + nary package and viewed wherever it is installed, using + pkg_info(1). + + --CC _c_p_k_g_s + Set the initial package conflict list to _c_p_k_g_s. This is assumed + to be a whitespace separated list of package names and is meant + as a convenient shorthand for specifying multiple @@ppkkggccffll direc- + tives in the packing list (see PACKING LIST DETAILS section be- + low). + + --cc _[_-_]_d_e_s_c + Fetch package ``one line description'' from file _d_e_s_c or, if pre- + ceded by --, the argument itself. This string should also give + some idea of which version of the product (if any) the package + represents. + + --DD _d_i_s_p_l_a_y_f_i_l_e + Display the file after installing the package. Useful for things + like legal notices on almost-free software, etc. + + --dd _[_-_]_d_e_s_c + Fetch long description for package from file _d_e_s_c or, if preceded + by --, the argument itself. + + --ff _p_a_c_k_i_n_g_l_i_s_t + Fetch ``packing list'' for package from the file _p_a_c_k_i_n_g_l_i_s_t or + ssttddiinn if _p_a_c_k_i_n_g_l_i_s_t is a -- (dash). + + --hh Force tar to follow symbolic links, so that the files they point + to are dumped, rather than the links themselves. + + --II _r_e_a_l_p_r_e_f_i_x + Provide the real prefix, as opposed to the staging prefix, for + use in staged installations of packages. + + --ii _i_s_c_r_i_p_t + Set _i_s_c_r_i_p_t to be the install procedure for the package. This + can be any executable program (or shell script). It will be in- + voked automatically when the package is later installed. + + --kk _d_s_c_r_i_p_t + Set _d_s_c_r_i_p_t to be the de-install procedure for the package. This + can be any executable program (or shell script). It will be in- + voked automatically when the package is later (if ever) de-in- + stalled. + + --LL _S_r_c_D_i_r + This sets the package's @src directive; see below for a descrip- + tion of what this does. + + --ll Check that any symbolic links which are to be placed in the pack- + age are relative to the current prefix. This means using + unlink(2) and symlink(2) to remove and re-link any symbolic links + which are targeted at full path names. + + --mm _m_t_r_e_e_f_i_l_e + Run mtree(8) with input from mtreefile before the package is in- + stalled. Mtree is invoked as mmttrreeee --uu --ff _m_t_r_e_e_f_i_l_e --dd --ee --pp + _p_r_e_f_i_x, where _p_r_e_f_i_x is the name of the first directory named by + a @@ccwwdd directive. + + --OO Go into a `packing list Only' mode. This is used to do `fake + pkg_add' operations when a package is installed. In such cases, + it is necessary to know what the final, adjusted packing list + will look like. + + --PP _d_p_k_g_s + Set the initial package dependency list to _d_p_k_g_s. This is as- + sumed to be a whitespace separated list of package names and is + meant as a convenient shorthand for specifying multiple @@ppkkggddeepp + directives in the packing list (see PACKING LIST DETAILS section + below). In addition, the exact versions of the packages referred + to in the _d_p_k_g_s list will be added to the packing list in the + form of @@bbllddddeepp directives. + + --pp _p_r_e_f_i_x + Set _p_r_e_f_i_x as the initial directory ``base'' to start from in se- + lecting files for the package. + + --RR Re-order any directories in the pkg/PLIST file into reverse al- + phabetic order, so that child directories will automatically be + removed before parent directories. + + --rr _r_s_c_r_i_p_t + Set _r_s_c_r_i_p_t 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 de- + termine whether or not installation/deinstallation should pro- + ceed. + + --SS _s_i_z_e_-_a_l_l_-_f_i_l_e + Store the given file for later querying with the pkg_info(1) _-_S + flag. The file is expected to contain the size (in bytes) of all + files of this package plus any required packages added up and + stored as a ASCII string, terminated by a newline. + + --ss _s_i_z_e_-_p_k_g_-_f_i_l_e + Store the given file for later querying with the pkg_info(1) _-_s + flag. The file is expected to contain the the size (in bytes) of + all files of this package added up and stored as a ASCII string, + terminated by a newline. + + --tt _t_e_m_p_l_a_t_e + Use _t_e_m_p_l_a_t_e as the input to mktemp(3). By default, this is the + string _/_t_m_p_/_i_n_s_t_m_p_._X_X_X_X_X_X, but it may be necessary to override it + in the situation where space in your _/_t_m_p directory is limited. + Be sure to leave some number of `X' characters for mktemp(3) to + fill in with a unique ID. + + --UU Do not update the package file database with any file informa- + tion. + + --VV Print version number and exit. + + --vv Turn on verbose output. + + --XX _e_x_c_l_u_d_e_f_i_l_e + Pass _e_x_c_l_u_d_e_f_i_l_e as a ----eexxcclluuddee--ffrroomm argument to ttaarr when creat- + ing final package. See ttaarr man page (or run ttaarr with ----hheellpp + flag) for further information on using this flag. + +PPAACCKKIINNGG LLIISSTT DDEETTAAIILLSS + The ``packing list'' format (see --ff) is fairly simple, being nothing more + than a single column of filenames to include in the package. However, + since absolute pathnames are generally a bad idea for a package that + could be installed potentially anywhere, there is another method of spec- + ifying where things are supposed to go and, optionally, what ownership + and mode information they should be installed with. This is done by em- + bedding specialized command sequences in the packing list. Briefly de- + scribed, these sequences are: + @@ccwwdd _d_i_r_e_c_t_o_r_y + Set the internal directory pointer to point to _d_i_r_e_c_t_o_r_y. All + subsequent filenames will be assumed relative to this directory. + Note: @@ccdd is also an alias for this command. + @@ssrrcc _d_i_r_e_c_t_o_r_y + Set the internal directory pointer for _creation only_ to + _d_i_r_e_c_t_o_r_y. That is to say that it overrides @@ccwwdd for package + creation but not extraction. + @@eexxeecc _c_o_m_m_a_n_d + Execute _c_o_m_m_a_n_d as part of the unpacking process. If _c_o_m_m_a_n_d + contains any of the following sequences somewhere in it, they + will be expanded inline. For the following examples, assume that + @@ccwwdd is set to _/_u_s_r_/_l_o_c_a_l and the last extracted file was + _b_i_n_/_e_m_a_c_s. + %%FF Expands to the last filename extracted (as specified), in + the example case _b_i_n_/_e_m_a_c_s + %%DD Expand to the current directory prefix, as set with @@ccwwdd, + in the example case _/_u_s_r_/_l_o_c_a_l. + %%BB Expand to the ``basename'' of the fully qualified file- + name, that is the current directory prefix, plus the last + filespec, minus the trailing filename. In the example + case, that would be _/_u_s_r_/_l_o_c_a_l_/_b_i_n. + %%ff Expand to the ``filename'' part of the fully qualified + name, or the converse of %%BB, being in the example case, + _e_m_a_c_s. + @@uunneexxeecc _c_o_m_m_a_n_d + Execute _c_o_m_m_a_n_d as part of the deinstallation process. Expansion + of special %% sequences is the same as for @@eexxeecc. This command is + not executed during the package add, as @@eexxeecc is, but rather when + the package is deleted. This is useful for deleting links and + other ancillary files that were created as a result of adding the + package, but not directly known to the package's table of con- + tents (and hence not automatically removable). The advantage of + using @@uunneexxeecc 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 --pp). + @@mmooddee _m_o_d_e + Set default permission for all subsequently extracted files to + _m_o_d_e. Format is the same as that used by the cchhmmoodd command + (well, considering that it's later handed off to it, that's no + surprise). Use without an arg to set back to default (extrac- + tion) permissions. + @@ooppttiioonn _o_p_t_i_o_n + Set internal package options, the only two currently supported + ones being _e_x_t_r_a_c_t_-_i_n_-_p_l_a_c_e, 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 + _p_r_e_s_e_r_v_e, which tells pkg_add to move any existing files out of + the way, preserving the previous contents (which are also resur- + rected on pkg_delete, so caveat emptor). + @@oowwnneerr _u_s_e_r + Set default ownership for all subsequently extracted files to + _u_s_e_r. Use without an arg to set back to default (extraction) + ownership. + @@ggrroouupp _g_r_o_u_p + Set default group ownership for all subsequently extracted files + to _g_r_o_u_p. Use without an arg to set back to default (extraction) + group ownership. + @@ccoommmmeenntt _s_t_r_i_n_g + Imbed a comment in the packing list. Useful in trying to docu- + ment some particularly hairy sequence that may trip someone up + later. + @@iiggnnoorree + Used internally to tell extraction to ignore the next file (don't + copy it anywhere), as it's used for some special purpose. + @@iiggnnoorree__iinnsstt + Similar to @@iiggnnoorree, but the ignoring of the next file is delayed + one evaluation cycle. This makes it possible to use this direc- + tive in the _p_a_c_k_i_n_g_l_i_s_t file, so you can pack a specialized + datafile in with a distribution for your install script (or some- + thing) yet have the installer ignore it. + @@nnaammee _n_a_m_e + 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 ppkkgg__ccrreeaattee will de- + rive this field from the package name and add it automatically if + none is given. + @@ddiirrrrmm _n_a_m_e + Declare directory _n_a_m_e to be deleted at deinstall time. By de- + fault, directories created by a package installation are not + deleted when the package is deinstalled; this provides an explic- + it directory cleanup method. This directive should appear at the + end of the package list. If more than one @@ddiirrrrmm directives are + used, the directories are removed in the order specified. The + _n_a_m_e directory will not be removed unless it is empty. + @@mmttrreeee _n_a_m_e + Declare _n_a_m_e as an mtree(8) input file to be used at install time + (see --mm above). Only the first @@mmttrreeee directive is honored. + @@ddiissppllaayy _n_a_m_e + Declare _n_a_m_e as the file to be displayed at install time (see --DD + above). + @@ppkkggddeepp _p_k_g_n_a_m_e + Declare a dependency on the _p_k_g_n_a_m_e package. The _p_k_g_n_a_m_e package + must be installed before this package may be installed, and this + package must be deinstalled before the _p_k_g_n_a_m_e package is dein- + stalled. Multiple @@ppkkggddeepp directives may be used if the package + depends on multiple other packages. + @@bbllddddeepp _p_k_g_n_a_m_e + Declare that this package was built with the exact version of + _p_k_g_n_a_m_e (since the @@ppkkggddeepp directive may contain wildcards or re- + lational package version information). + @@ppkkggccffll _p_k_g_c_f_l_n_a_m_e + Declare a conflict with the _p_k_g_c_f_l_n_a_m_e package, as the two pack- + ages contain references to the same files, and so cannot co-exist + on the same system. + +SSEEEE AALLSSOO + pkg_add(1), pkg_admin(1), pkg_delete(1), pkg_info(1), sysconf(3), + packages(7) + +HHIISSTTOORRYY + The ppkkgg__ccrreeaattee command first appeared in FreeBSD. + +AAUUTTHHOORRSS + Jordan Hubbard + most of the work + John Kohl + refined it for NetBSD + Hubert Feyrer + NetBSD wildcard dependency processing, pkgdb, pkg size recording + etc. + +BBUUGGSS + Hard links between files in a distribution must be bracketed by @@ccwwdd di- + rectives in order to be preserved as hard links when the package is ex- + tracted. They additionally must not end up being split between ttaarr invo- + cations due to exec argument-space limitations (this depends on the value + returned by ssyyssccoonnff(___S_C___A_R_G___M_A_X)). + +NetBSD 1.6 April 21, 1995 5 diff --git a/pkgtools/pkg_install/files/create/pl.c b/pkgtools/pkg_install/files/create/pl.c new file mode 100644 index 00000000000..54b763d3337 --- /dev/null +++ b/pkgtools/pkg_install/files/create/pl.c @@ -0,0 +1,238 @@ +/* $NetBSD: pl.c,v 1.1.1.1 2002/12/20 18:14:11 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: pl.c,v 1.11 1997/10/08 07:46:35 charnier Exp"; +#else +__RCSID("$NetBSD: pl.c,v 1.1.1.1 2002/12/20 18:14:11 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Routines for dealing with the packing list. + * + */ + +#include "lib.h" +#include "create.h" + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_MD5GLOBAL_H +#include <md5global.h> +#endif + +#ifdef HAVE_MD5_H +#include <md5.h> +#endif + +/* + * Check that any symbolic link is relative to the prefix + */ +static void +CheckSymlink(char *name, char *prefix, size_t prefixcc) +{ + char newtgt[MAXPATHLEN]; + char oldtgt[MAXPATHLEN]; + char *slash; + int slashc; + int cc; + int i; + + if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) { + oldtgt[cc] = 0; + if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') { + for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) { + } + for (cc = i = 0; i < slashc; i++) { + strnncpy(&newtgt[cc], sizeof(newtgt) - cc, "../", 3); + cc += 3; + } + strnncpy(&newtgt[cc], sizeof(newtgt) - cc, &oldtgt[prefixcc + 1], strlen(&oldtgt[prefixcc + 1])); + (void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt); + if (unlink(name) != 0) { + warn("can't unlink `%s'", name); + } else if (symlink(newtgt, name) != 0) { + warn("can't symlink `%s' called `%s'", newtgt, name); + } + } + } +} + +/* + * (Reversed) comparison routine for directory name sorting + */ +static int +dircmp(const void *vp1, const void *vp2) +{ + return strcmp((const char *) vp2, (const char *) vp1); +} + +/* + * Re-order the PLIST_DIR_RM entries into reverse alphabetic order + */ +static void +reorder(package_t *pkg, int dirc) +{ + plist_t *p; + char **dirv; + int i; + + if ((dirv = (char **) calloc(dirc, sizeof(char *))) == (char **) NULL) { + warn("No directory re-ordering will be done"); + } else { + for (p = pkg->head, i = 0; p; p = p->next) { + if (p->type == PLIST_DIR_RM) { + dirv[i++] = p->name; + } + } + qsort(dirv, dirc, sizeof(char *), dircmp); + for (p = pkg->head, i = 0; p; p = p->next) { + if (p->type == PLIST_DIR_RM) { + p->name = dirv[i++]; + } + } + (void) free(dirv); + } +} + +/* + * Check a list for files that require preconversion + */ +void +check_list(char *home, package_t *pkg, const char *PkgName) +{ + struct stat st; + plist_t *tmp; + plist_t *p; + char name[FILENAME_MAX]; + char buf[ChecksumHeaderLen + LegibleChecksumLen]; + char *cwd = home; + char *srcdir = NULL; + int dirc; + + /* Open Package Database for writing */ + if (update_pkgdb && pkgdb_open(0) == -1) { + cleanup(0); + err(1, "can't open pkgdb"); + } + + for (dirc = 0, p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_CWD: + cwd = p->name; + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_SRC: + srcdir = p->name; + break; + case PLIST_DIR_RM: + dirc++; + break; + case PLIST_FILE: + /* + * pkgdb handling - usually, we enter files + * into the pkgdb as soon as they hit the disk, + * but as they are present before pkg_create + * starts, it's ok to do this somewhere here + */ + if (update_pkgdb) { + char *s, t[FILENAME_MAX]; + + (void) snprintf(t, sizeof(t), "%s/%s", cwd, p->name); + + s = pkgdb_retrieve(t); +#ifdef PKGDB_DEBUG + fprintf(stderr, "pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ +#endif + if (s && PlistOnly) + warnx("Overwriting %s - " + "pkg %s bogus/conflicting?", t, s); + else { + pkgdb_store(t, PkgName); +#ifdef PKGDB_DEBUG + fprintf(stderr, "pkgdb_store(\"%s\", \"%s\")\n", t, PkgName); /* pkgdb-debug - HF */ +#endif + } + } + + if (cwd == home) { + /* no @cwd yet */ + (void) snprintf(name, sizeof(name), "%s/%s", srcdir ? srcdir : cwd, p->name); + } else { + /* after @cwd */ + /* prepend DESTDIR if set? - HF */ + (void) snprintf(name, sizeof(name), "%s/%s", cwd, p->name); + } + if (lstat(name, &st) < 0) { + warnx("can't stat `%s'", name); + continue; + } + switch (st.st_mode & S_IFMT) { + case S_IFDIR: + p->type = PLIST_DIR_RM; + dirc++; + continue; + case S_IFLNK: + if (RelativeLinks) { + CheckSymlink(name, cwd, strlen(cwd)); + } + break; + case S_IFCHR: + warnx("Warning - char special device `%s' in PLIST", name); + break; + case S_IFBLK: + warnx("Warning - block special device `%s' in PLIST", name); + break; + default: + (void) strcpy(buf, CHECKSUM_HEADER); + if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) { + tmp = new_plist_entry(); + tmp->name = strdup(buf); + tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */ + tmp->next = p->next; + tmp->prev = p; + if (p == pkg->tail) { + pkg->tail = tmp; + } + p->next = tmp; + p = tmp; + } + break; + } + break; + default: + break; + } + } + + if (update_pkgdb) { + pkgdb_close(); + } + + if (ReorderDirs && dirc > 0) { + reorder(pkg, dirc); + } +} diff --git a/pkgtools/pkg_install/files/delete/Makefile.in b/pkgtools/pkg_install/files/delete/Makefile.in new file mode 100644 index 00000000000..37acb9ac73d --- /dev/null +++ b/pkgtools/pkg_install/files/delete/Makefile.in @@ -0,0 +1,40 @@ +# From NetBSD: Makefile,v 1.4 1997/10/17 14:53:59 lukem Exp $ +# Original from FreeBSD, no rcs id. + +PREFIX= @prefix@ +INSTALL= @INSTALL@ + +mandir= ${PREFIX}/man +mandircat1= ${mandir}/cat1 + +CC= @CC@ +CCLD= $(CC) +LIBS= @LIBS@ -linstall +CPPFLAGS= @CPPFLAGS@ +DEFS= @DEFS@ -I. -I@srcdir@ -I../lib +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ -L../lib + +LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ +COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) + +PROG= pkg_delete + +SRCS= main.c perform.c +OBJS= main.o perform.o + +all: ${PROG} + +${PROG}: ${OBJS} + ${LINK} ${OBJS} ${LIBS} + +.c.o: + $(COMPILE) -c $< -o $@ + +clean: + rm -f ${OBJS} ${PROG} + +install: + ${INSTALL} ${PROG} ${PREFIX}/sbin + ${INSTALL} -m 755 -d ${mandircat1} + ${INSTALL} -m 444 ${PROG}.cat1 ${mandircat1}/${PROG}.1 diff --git a/pkgtools/pkg_install/files/delete/delete.h b/pkgtools/pkg_install/files/delete/delete.h new file mode 100644 index 00000000000..62823872942 --- /dev/null +++ b/pkgtools/pkg_install/files/delete/delete.h @@ -0,0 +1,37 @@ +/* $NetBSD: delete.h,v 1.1.1.1 2002/12/20 18:14:07 schmonz Exp $ */ + +/* from FreeBSD Id: delete.h,v 1.4 1997/02/22 16:09:35 peter Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the delete command. + * + */ + +#ifndef _INST_DELETE_H_INCLUDE +#define _INST_DELETE_H_INCLUDE + +extern char *Prefix; +extern char *ProgramPath; +extern Boolean NoDeInstall; +extern Boolean CleanDirs; +extern Boolean Force; +extern Boolean Recurse_up; +extern Boolean Recurse_down; +extern lpkg_head_t pkgs; + +#endif /* _INST_DELETE_H_INCLUDE */ diff --git a/pkgtools/pkg_install/files/delete/main.c b/pkgtools/pkg_install/files/delete/main.c new file mode 100644 index 00000000000..32dacc7e3e4 --- /dev/null +++ b/pkgtools/pkg_install/files/delete/main.c @@ -0,0 +1,225 @@ +/* $NetBSD: main.c,v 1.1.1.1 2002/12/20 18:14:09 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char *rcsid = "from FreeBSD Id: main.c,v 1.11 1997/10/08 07:46:48 charnier Exp"; +#else +__RCSID("$NetBSD: main.c,v 1.1.1.1 2002/12/20 18:14:09 schmonz Exp $"); +#endif +#endif +#endif + +/* + * + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the delete module. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <errno.h> +#include "lib.h" +#include "delete.h" + +static char Options[] = "hVvDdnfFp:OrR"; + +char *Prefix = NULL; +char *ProgramPath = NULL; +Boolean NoDeInstall = FALSE; +Boolean CleanDirs = FALSE; +Boolean File2Pkg = FALSE; +Boolean Recurse_up = FALSE; +Boolean Recurse_down = FALSE; +Boolean OnlyDeleteFromPkgDB = FALSE; +lpkg_head_t pkgs; + +static void +usage(void) +{ + fprintf(stderr, "usage: pkg_delete [-vVDdnFfOrR] [-p prefix] pkg-name ...\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, error; + lpkg_t *lpp; + + setprogname(argv[0]); + + ProgramPath = argv[0]; + + while ((ch = getopt(argc, argv, Options)) != -1) + switch (ch) { + case 'v': + Verbose = TRUE; + break; + + case 'f': + Force = TRUE; + break; + + case 'F': + File2Pkg = TRUE; + break; + + case 'p': + Prefix = optarg; + break; + + case 'D': + NoDeInstall = TRUE; + break; + + case 'd': + CleanDirs = TRUE; + break; + + case 'n': + Fake = TRUE; + Verbose = TRUE; + break; + + case 'r': + Recurse_up = TRUE; + break; + + case 'R': + Recurse_down = TRUE; + break; + + case 'O': + OnlyDeleteFromPkgDB = TRUE; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case 'h': + case '?': + default: + usage(); + break; + } + + argc -= optind; + argv += optind; + + TAILQ_INIT(&pkgs); + + /* Get all the remaining package names, if any */ + if (File2Pkg) + if (pkgdb_open(1) == -1) { + err(1, "cannot open pkgdb"); + } + /* Get all the remaining package names, if any */ + while (*argv) { + /* pkgdb: if -F flag given, don't add pkgnames to pkgs but + * rather resolve the given filenames to pkgnames using + * pkgdb_retrieve, then add these. */ + if (File2Pkg) { + char *s; + + s = pkgdb_retrieve(*argv); + + if (s) { + lpp = alloc_lpkg(s); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } else + errx(1, "No matching pkg for %s in pkgdb.", *argv); + } else { + if (ispkgpattern(*argv)) { + int rc; + rc = findmatchingname(_pkgdb_getPKGDB_DIR(), *argv, add_to_list_fn, &pkgs); + if (rc == 0) + errx(1, "No matching pkg for %s.", *argv); + else if (rc == -1) + errx(1, "error expanding '%s' ('%s' nonexistant?)", *argv, _pkgdb_getPKGDB_DIR()); + } else { + lpp = alloc_lpkg(*argv); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } + } + argv++; + } + + if (File2Pkg) + pkgdb_close(); + + /* If no packages, yelp */ + if (TAILQ_FIRST(&pkgs) == NULL) + warnx("missing package name(s)"), usage(); + if (!Fake && getuid() != 0) + errx(1, "you must be root to delete packages"); + if (OnlyDeleteFromPkgDB) { + /* Only delete the given packages' files from pkgdb, do not + * touch the pkg itself. Used by "make reinstall" in + * bsd.pkg.mk */ + char *key, *val; + + if (pkgdb_open(0) == -1) { + err(1, "cannot open %s", _pkgdb_getPKGDB_FILE()); + } + + error = 0; + while ((key = pkgdb_iter())) { + val = pkgdb_retrieve(key); + if (val == NULL || *val == '\0') + continue; + + lpp = TAILQ_FIRST(&pkgs); + if (lpp != NULL) { + do { + if (strcmp(val, lpp->lp_name) == 0) { + if (Verbose) + printf("Removing file %s from pkgdb\n", key); + + errno = 0; + if (pkgdb_remove(key)) { + if (errno) + printf("Error removing %s from pkgdb: %s\n", key, strerror(errno)); + else + printf("Key %s not present in pkgdb?!\n", key); + error = 1; + } + } + + lpp = TAILQ_NEXT(lpp, lp_link); + } while (lpp != NULL); + } + } + pkgdb_close(); + + return error; + + } else if ((error = pkg_perform(&pkgs)) != 0) { + if (Verbose) + warnx("%d package deletion(s) failed", error); + return error; + } else + return 0; +} diff --git a/pkgtools/pkg_install/files/delete/perform.c b/pkgtools/pkg_install/files/delete/perform.c new file mode 100644 index 00000000000..cb7bfa04d70 --- /dev/null +++ b/pkgtools/pkg_install/files/delete/perform.c @@ -0,0 +1,697 @@ +/* $NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:14:08 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: perform.c,v 1.15 1997/10/13 15:03:52 jkh Exp"; +#else +__RCSID("$NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:14:08 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the delete module. + * + */ +/* + * Copyright (c) 1999 Christian E. Hopps + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Added the require find and require delete code + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include "lib.h" +#include "delete.h" + + +/* In which direction to search in require_find() */ +typedef enum { + FIND_UP, FIND_DOWN +} rec_find_t; + +static int require_find_recursive_up(lpkg_t *); +static int require_find_recursive_down(lpkg_t *, package_t *); +static int require_find(char *, rec_find_t); +static int require_delete(char *, int); +static void require_print(void); +static int undepend(const char *, void *); + +static char LogDir[FILENAME_MAX]; +static char linebuf[FILENAME_MAX]; +static char pkgdir[FILENAME_MAX]; + +static package_t Plist; + +static lpkg_head_t lpfindq; +static lpkg_head_t lpdelq; + +static void +sanity_check(char *pkg) +{ + if (!fexists(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); +} + +/* + * deppkgname is the pkg from which's +REQUIRED_BY file we are + * about to remove pkg2delname. This function is called from + * findmatchingname(), deppkgname is expanded from a (possible) pattern. + */ +static int +undepend(const char *deppkgname, void *vp) +{ + char *pkg2delname = vp; + char fname[FILENAME_MAX], ftmp[FILENAME_MAX]; + char fbuf[FILENAME_MAX]; + FILE *fp, *fpwr; + char *tmp; + int s; + + (void) snprintf(fname, sizeof(fname), "%s/%s/%s", + (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + deppkgname, REQUIRED_BY_FNAME); + fp = fopen(fname, "r"); + if (fp == NULL) { + warnx("couldn't open dependency file `%s'", fname); + return 0; + } + (void) snprintf(ftmp, sizeof(ftmp), "%s.XXXXXX", fname); + s = mkstemp(ftmp); + if (s == -1) { + fclose(fp); + warnx("couldn't open temp file `%s'", ftmp); + return 0; + } + fpwr = fdopen(s, "w"); + if (fpwr == NULL) { + close(s); + fclose(fp); + warnx("couldn't fdopen temp file `%s'", ftmp); + remove(ftmp); + return 0; + } + while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { + if (fbuf[strlen(fbuf) - 1] == '\n') + fbuf[strlen(fbuf) - 1] = '\0'; + if (strcmp(fbuf, pkg2delname)) /* no match */ + fputs(fbuf, fpwr), putc('\n', fpwr); + } + (void) fclose(fp); + if (fchmod(s, 0644) == FAIL) { + warnx("error changing permission of temp file `%s'", ftmp); + fclose(fpwr); + remove(ftmp); + return 0; + } + if (fclose(fpwr) == EOF) { + warnx("error closing temp file `%s'", ftmp); + remove(ftmp); + return 0; + } + if (rename(ftmp, fname) == -1) + warnx("error renaming `%s' to `%s'", ftmp, fname); + remove(ftmp); /* just in case */ + + return 0; +} + +/* + * Delete from directory 'home' all packages on lpkg_list. + * If tryall is set, ignore errors from pkg_delete(1). + */ +int +require_delete(char *home, int tryall) +{ + lpkg_t *lpp; + int rv, fail; + char *tmp; + int oldcwd; + + /* save cwd */ + oldcwd = open(".", O_RDONLY, 0); + if (oldcwd == -1) + err(1, "cannot open \".\""); + + (void) snprintf(pkgdir, sizeof(pkgdir), "%s", + (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR); + + /* walk list of things to delete */ + fail = 0; + lpp = TAILQ_FIRST(&lpdelq); + for (; lpp; lpp = TAILQ_NEXT(lpp, lp_link)) { + int rm_installed; /* delete expanded pkg, not @pkgdep value */ + char installed[FILENAME_MAX]; + + /* go to the db dir */ + if (chdir(pkgdir) == FAIL) { + warnx("unable to change directory to %s, deinstall failed (1)", + pkgdir); + fail = 1; + break; + } + + /* look to see if package was already deleted */ + rm_installed = 0; + if (ispkgpattern(lpp->lp_name)) { + if (findmatchingname(".", lpp->lp_name, note_whats_installed, installed) != 1) { + warnx("%s appears to have been deleted", lpp->lp_name); + continue; + } + rm_installed = 1; + } else { + if (!fexists(lpp->lp_name)) { + warnx("%s appears to have been deleted", lpp->lp_name); + continue; + } + } + + /* return home for execution of command */ + if (chdir(home) == FAIL) { + warnx("unable to change directory to %s, deinstall failed (2)", home); + fail = 1; + break; + } + + if (Verbose) + printf("deinstalling %s\n", rm_installed?installed:lpp->lp_name); + + /* delete the package */ + if (Fake) + rv = 0; + else + rv = vsystem("%s %s %s %s %s %s %s %s %s", ProgramPath, + Prefix ? "-p" : "", + Prefix ? Prefix : "", + Verbose ? "-v" : "", + Force ? "-f" : "", + NoDeInstall ? "-D" : "", + CleanDirs ? "-d" : "", + Fake ? "-n" : "", + rm_installed?installed:lpp->lp_name); + + /* check for delete failure */ + if (rv && !tryall) { + fail = 1; + warnx("had problem removing %s%s", rm_installed?installed:lpp->lp_name, + Force ? ", continuing" : ""); + if (!Force) + break; + } + } + + /* cleanup list */ + while ((lpp = TAILQ_FIRST(&lpdelq))) { + TAILQ_REMOVE(&lpdelq, lpp, lp_link); + free_lpkg(lpp); + } + + /* return to the log dir */ + if (fchdir(oldcwd) == FAIL) { + warnx("unable to change to previous directory, deinstall failed"); + fail = 1; + } + close(oldcwd); + + return (fail); +} + +/* + * Recursively find all packages "up" the tree (follow +REQUIRED_BY). + * Return 1 on errors + */ +int +require_find_recursive_up(lpkg_t *thislpp) +{ + lpkg_head_t reqq; + lpkg_t *lpp = NULL; + FILE *cfile; + char *nl, *tmp; + + /* see if we are on the find queue -- circular dependency */ + if ((lpp = find_on_queue(&lpfindq, thislpp->lp_name))) { + warnx("circular dependency found for pkg %s", lpp->lp_name); + return (1); + } + + TAILQ_INIT(&reqq); + + (void) snprintf(pkgdir, sizeof(pkgdir), "%s/%s", + (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, thislpp->lp_name); + + /* change to package's dir */ + if (chdir(pkgdir) == FAIL) { + warnx("unable to change directory to %s! deinstall failed", pkgdir); + return (1); + } + + /* terminate recursion if no required by's */ + if (isemptyfile(REQUIRED_BY_FNAME)) + return (0); + + /* get packages that directly require us */ + cfile = fopen(REQUIRED_BY_FNAME, "r"); + if (!cfile) { + warnx("cannot open requirements file `%s'", REQUIRED_BY_FNAME); + return (1); + } + while (fgets(linebuf, sizeof(linebuf), cfile)) { + if ((nl = strrchr(linebuf, '\n'))) + *nl = 0; + lpp = alloc_lpkg(linebuf); + TAILQ_INSERT_TAIL(&reqq, lpp, lp_link); + } + fclose(cfile); + + /* put ourselves on the top of the find queue */ + TAILQ_INSERT_HEAD(&lpfindq, thislpp, lp_link); + + while ((lpp = TAILQ_FIRST(&reqq))) { + /* remove a direct req from our queue */ + TAILQ_REMOVE(&reqq, lpp, lp_link); + + /* find direct required requires */ + if (require_find_recursive_up(lpp)) + goto fail; + + /* all requires taken care of, add to tail of delete queue + * if not already there */ + if (find_on_queue(&lpdelq, lpp->lp_name)) + free_lpkg(lpp); + else + TAILQ_INSERT_TAIL(&lpdelq, lpp, lp_link); + } + + /* take ourselves off the find queue */ + TAILQ_REMOVE(&lpfindq, thislpp, lp_link); + + return (0); + +fail: + while ((lpp = TAILQ_FIRST(&reqq))) { + TAILQ_REMOVE(&reqq, lpp, lp_link); + free_lpkg(lpp); + } + return (1); +} + +/* + * Recursively find all packages "down" the tree (follow @pkgdep). + * Return 1 on errors + */ +int +require_find_recursive_down(lpkg_t *thislpp, package_t *plist) +{ + plist_t *p; + lpkg_t *lpp, *lpp2; + lpkg_head_t reqq; + int rc, fail = 0; + + /* see if we are on the find queue -- circular dependency */ + if ((lpp = find_on_queue(&lpfindq, thislpp->lp_name))) { + warnx("circular dependency found for pkg %s", lpp->lp_name); + return (1); + } + + TAILQ_INIT(&reqq); + + /* width-first scan */ + /* first enqueue all @pkgdep's to lpdelq, then (further below) + * go in recursively */ + for (p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_PKGDEP: + lpp = alloc_lpkg(p->name); + TAILQ_INSERT_TAIL(&reqq, lpp, lp_link); + + lpp2 = find_on_queue(&lpdelq, p->name); + if (lpp2) { + TAILQ_REMOVE(&lpdelq, lpp2, lp_link); + free_lpkg(lpp2); + } + lpp = alloc_lpkg(p->name); + TAILQ_INSERT_TAIL(&lpdelq, lpp, lp_link); + + break; + default: + break; + } + } + + while ((lpp = TAILQ_FIRST(&reqq))) { + FILE *cfile; + package_t rPlist; + char *tmp; + + /* remove a direct req from our queue */ + TAILQ_REMOVE(&reqq, lpp, lp_link); + + /* Reset some state */ + rPlist.head = NULL; + rPlist.tail = NULL; + + /* prepare for recursion */ + chdir ((tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR); + if (ispkgpattern(lpp->lp_name)) { + char installed[FILENAME_MAX]; + if (findmatchingname(".", lpp->lp_name, note_whats_installed, installed) != 1) { + warnx("cannot remove dependency for pkg-pattern %s", lpp->lp_name); + fail = 1; + goto fail; + } + if (chdir(installed) == -1) { + warnx("can't chdir to %s", installed); + fail = 1; + goto fail; + } + sanity_check(installed); + } else { + if (chdir(lpp->lp_name) == -1) { + warnx("cannot remove dependency from %s", lpp->lp_name); + fail = 1; + goto fail; + } + sanity_check(lpp->lp_name); + } + + cfile = fopen(CONTENTS_FNAME, "r"); + if (!cfile) { + warn("unable to open '%s' file", CONTENTS_FNAME); + fail = 1; + goto fail; + } + /* If we have a prefix, add it now */ + if (Prefix) + add_plist(&rPlist, PLIST_CWD, Prefix); + read_plist(&rPlist, cfile); + fclose(cfile); + p = find_plist(&rPlist, PLIST_CWD); + if (!p) { + warnx("package '%s' doesn't have a prefix", lpp->lp_name); + free_plist(&rPlist); + fail = 1; + goto fail; + } + + /* put ourselves on the top of the find queue */ + TAILQ_INSERT_HEAD(&lpfindq, thislpp, lp_link); + + rc = require_find_recursive_down(lpp, &rPlist); + free_plist(&rPlist); + if (rc) { + fail = 1; + goto fail; + } + + /* take ourselves off the find queue */ + TAILQ_REMOVE(&lpfindq, thislpp, lp_link); + free_lpkg(lpp); + } + +fail: + /* Clean out reqq */ + while ((lpp = TAILQ_FIRST(&reqq))) { + TAILQ_REMOVE(&reqq, lpp, lp_link); + free_lpkg(lpp); + } + + return fail; +} + +/* + * Start recursion in the one or other direction. + */ +int +require_find(char *pkg, rec_find_t updown) +{ + lpkg_t *lpp; + int rv = 0; + + TAILQ_INIT(&lpfindq); + TAILQ_INIT(&lpdelq); + + lpp = alloc_lpkg(pkg); + switch (updown) { + case FIND_UP: + rv = require_find_recursive_up(lpp); + break; + case FIND_DOWN: + rv = require_find_recursive_down(lpp, &Plist); + break; + } + free_lpkg(lpp); + + return (rv); +} + +void +require_print(void) +{ + lpkg_t *lpp; + + /* print all but last -- deleting if requested */ + while ((lpp = TAILQ_FIRST(&lpdelq))) { + TAILQ_REMOVE(&lpdelq, lpp, lp_link); + fprintf(stderr, "\t%s\n", lpp->lp_name); + free_lpkg(lpp); + } +} + +/* + * This is seriously ugly code following. Written very fast! + */ +static int +pkg_do(char *pkg) +{ + FILE *cfile; + char home[FILENAME_MAX]; + plist_t *p; + char *tmp; + + /* Reset some state */ + if (Plist.head) + free_plist(&Plist); + + (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + pkg); + if (!fexists(LogDir) || !isdir(LogDir)) { + { + /* Check if the given package name matches something + * with 'pkg-[0-9]*' */ + char try[FILENAME_MAX]; + snprintf(try, FILENAME_MAX, "%s-[0-9]*", pkg); + if (findmatchingname(_pkgdb_getPKGDB_DIR(), try, + add_to_list_fn, &pkgs) != 0) { + return 0; /* we've just appended some names to the pkgs list, + * they will be processed after this package. */ + } + } + + /* No match */ + warnx("package '%s' not installed", pkg); + return 1; + } + if (!getcwd(home, FILENAME_MAX)) { + cleanup(0); + errx(2, "unable to get current working directory!"); + } + if (chdir(LogDir) == FAIL) { + warnx("unable to change directory to %s! deinstall failed", LogDir); + return 1; + } + if (!isemptyfile(REQUIRED_BY_FNAME)) { + /* This package is required by others. Either nuke + * them (-r), or stop. */ + if (!Recurse_up) + warnx("package `%s' is required by other packages:", pkg); + else if (Verbose) + printf("Building list of packages that require `%s'" + " to deinstall\n", pkg); + if (require_find(pkg, FIND_UP)) { + if (!Force || Recurse_up) + return (1); + } + chdir(LogDir); /* CWD was changed by require_find() */ + if (!Recurse_up) { + require_print(); + if (!Force) + return 1; + } else + require_delete(home, 0); + } + sanity_check(LogDir); + cfile = fopen(CONTENTS_FNAME, "r"); + if (!cfile) { + warnx("unable to open '%s' file", CONTENTS_FNAME); + return 1; + } + /* If we have a prefix, add it now */ + if (Prefix) + add_plist(&Plist, PLIST_CWD, Prefix); + read_plist(&Plist, cfile); + fclose(cfile); + p = find_plist(&Plist, PLIST_CWD); + 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("%s +x %s", CHMOD_CMD, REQUIRE_FNAME); /* be sure */ + if (vsystem("./%s %s DEINSTALL", REQUIRE_FNAME, pkg)) { + warnx("package %s fails requirements %s", pkg, + Force ? "" : "- not deleted"); + if (!Force) + return 1; + } + } + if (!NoDeInstall && fexists(DEINSTALL_FNAME)) { + if (Fake) + printf("Would execute de-install script at this point (arg: DEINSTALL).\n"); + else { + vsystem("%s +x %s", CHMOD_CMD, DEINSTALL_FNAME); /* make sure */ + if (vsystem("./%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) { + warnx("deinstall script returned error status"); + if (!Force) + return 1; + } + } + } + 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) + warnx( + "couldn't entirely delete package `%s'\n" + "(perhaps the packing list is incorrectly specified?)", pkg); + } + /* Remove this package from the +REQUIRED_BY list of the packages this depends on */ + for (p = Plist.head; p; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Attempting to remove dependency on package `%s'\n", p->name); + if (!Fake) + findmatchingname((tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + p->name, undepend, pkg); + } + if (Recurse_down) { + /* Also remove the packages further down, now that there's + * (most likely) nothing left which requires them. */ + if (Verbose) + printf("Building list of packages that `%s' required\n", pkg); + if (require_find(pkg, FIND_DOWN)) + return (1); + + require_delete(home, 1); + } + if (!NoDeInstall && fexists(DEINSTALL_FNAME)) { + if (Fake) + printf("Would execute post-de-install script at this point (arg: POST-DEINSTALL).\n"); + else { + vsystem("chmod +x %s", DEINSTALL_FNAME); /* make sure */ + if (vsystem("./%s %s POST-DEINSTALL", DEINSTALL_FNAME, pkg)) { + warnx("post-deinstall script returned error status"); + if (!Force) + return 1; + } + } + } + /* Change out of LogDir before we remove it. + * Do not fail here, as the package is not yet completely deleted! */ + if (chdir(home) == FAIL) + warnx("Oops - removed current working directory. Oh, well."); + if (!Fake) { + /* Finally nuke the +-files and the pkgdb-dir (/var/db/pkg/foo) */ + if (vsystem("%s -r %s", RM, LogDir)) { + warnx("couldn't remove log entry in %s, deinstall failed", LogDir); + if (!Force) + return 1; + } + } + return 0; +} + +int +pkg_perform(lpkg_head_t *pkghead) +{ + int err_cnt = 0; + int oldcwd; + lpkg_t *lpp; + + /* save cwd */ + oldcwd = open(".", O_RDONLY, 0); + if (oldcwd == -1) + err(1, "cannot open \".\""); + + while ((lpp = TAILQ_FIRST(pkghead))) { + err_cnt += pkg_do(lpp->lp_name); + TAILQ_REMOVE(pkghead, lpp, lp_link); + free_lpkg(lpp); + if (fchdir(oldcwd) == FAIL) + err(1, "unable to change to previous directory"); + } + close(oldcwd); + return err_cnt; +} diff --git a/pkgtools/pkg_install/files/delete/pkg_delete.1 b/pkgtools/pkg_install/files/delete/pkg_delete.1 new file mode 100644 index 00000000000..39569ff3c7d --- /dev/null +++ b/pkgtools/pkg_install/files/delete/pkg_delete.1 @@ -0,0 +1,241 @@ +.\" $NetBSD: pkg_delete.1,v 1.1.1.1 2002/12/20 18:14:08 schmonz Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintainance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" from FreeBSD: @(#)pkg_delete.1 +.\" +.Dd March 8, 1999 +.Dt PKG_DELETE 1 +.Os +.Sh NAME +.Nm pkg_delete +.Nd a utility for deleting previously installed software package distributions +.Sh SYNOPSIS +.Nm +.Op Fl DdFfnORrVv +.Bk -words +.Op Fl p Ar prefix +.Ek +.Ar pkg-name ... +.Sh DESCRIPTION +The +.Nm +command is used to delete packages that have been previously installed +with the +.Xr pkg_add 1 +command. +.Sh WARNING +.Bf -emphasis +Since the +.Nm +command may execute scripts or programs provided by a package file, +your system may be susceptible to ``Trojan horses'' or other subtle +attacks from miscreants who create dangerous package files. +.Pp +You are advised to verify the competence and identity of those who +provide installable package files. +For extra protection, examine all the package control files in the +package record directory +.Pa ( /var/db/pkg/\*[Lt]pkg-name\*[Gt]/ ) . +Pay particular +attention to any +INSTALL, +DEINSTALL, +REQUIRE or +MTREE_DIRS files, +and inspect the +CONTENTS file for +.Cm @cwd , +.Cm @mode +(check for setuid), +.Cm @dirrm , +.Cm @exec , +and +.Cm @unexec +directives, and/or use the +.Xr pkg_info 1 +command to examine the installed package control files. +.Ef +.Sh OPTIONS +The following command line options are supported: +.Bl -tag -width indent +.It Ar pkg-name ... +The named packages are deinstalled, wildcards can be used, see +.Xr pkg_info 1 . +If no version is given, the one currently installed +will be removed. +If the +.Fl F +flag is given, one or more (absolute) filenames may be specified and +the Package Database will be consulted for the package to which the +given file belongs. +These packages are then deinstalled. +.It Fl D +If a deinstallation script exists for a given package, do not execute it. +.It Fl d +Remove empty directories created by file cleanup. +By default, only files/directories explicitly listed in a package's +contents (either as normal files/directories or with the +.Cm @dirrm +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. +.It Fl F +Any pkg-name given will be interpreted as pathname which is +subsequently transformed in a (real) package name via the Package +Database. +That way, packages can be deleted by giving a filename +instead of the package-name. +.It Fl f +Force removal of the package, even if a dependency is recorded or the +deinstall or require script fails. +.It Fl n +Don't actually deinstall a package, just report the steps that +would be taken if it were. +.It Fl O +Only delete the package's entries from the package database, do not +touch the package or its files itself. +.It Fl p Ar prefix +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 . +.It Fl R +Like the +.Fl r +option, this does a recursive delete. +The +.Fl R +option deletes the given package and any packages required by +it, unless some other package still needs them. +This can be used to delete a package and all the packages it needs. +.It Fl r +.Nm +first builds a list of all packages that require (directly and indirectly) +the one being deleted. +It then deletes these packages using +.Nm +with the given options before deleting the user specified package. +.It Fl V +Print version number and exit. +.It Fl v +Turn on verbose output. +.El +.Sh TECHNICAL DETAILS +.Nm +does pretty much what it says. +It examines installed package records in +.Pa /var/db/pkg/\*[Lt]pkg-name\*[Gt] , +deletes the package contents, and finally removes the package records. +.Pp +If a package is required by other installed packages, +.Nm +will list those dependent packages and refuse to delete the package +(unless the +.Fl f +option is given). +.Pp +If a filename is given instead of a package name, the package of which +the given file belongs to can be deleted if the +.Fl F +Flag is given. +The filename needs to be absolute, see the output produced by the pkg_info +.Fl aF +command. +.Pp +If the package contains a +.Ar require +file (see +.Xr pkg_create 1 ) , +then this is executed first as +.Bd -filled -offset indent -compact +.Cm require +.Ar \*[Lt]pkg-name\*[Gt] +.Ar DEINSTALL +.Ed +(where +.Ar pkg-name +is the name of the package in question and +.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 +.Fl f +option is specified. +.Pp +If a +.Cm deinstall +script exists for the package, it is executed before and after +any files are removed. +It is this script's responsibility to clean up any additional messy details +around the package's installation, since all +.Nm +knows how to do is delete the files created in the original distribution. +The +.Ic deinstall +script is called as: +.Bd -filled -offset indent -compact +.Cm deinstall +.Ar \*[Lt]pkg-name\*[Gt] +.Ar DEINSTALL +.Ed +before deleting all files and as: +.Bd -filled -offset indent -compact +.Cm deinstall +.Ar \*[Lt]pkg-name\*[Gt] +.Ar POST-DEINSTALL +.Ed +after deleting them. +Passing the keywords +.Ar DEINSTALL +and +.Ar POST-DEINSTALL +lets you potentially write only one program/script that handles all +aspects of installation and deletion. +.Pp +All scripts are called with the environment variable +.Ev PKG_PREFIX +set to the installation prefix (see the +.Fl p +option above). +This allows a package author to write a script +that reliably performs some action on the directory where the package +is installed, even if the user might have changed it by specifying the +.Fl p +option when running +.Nm +or +.Xr pkg_add 1 . +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_info 1 , +.Xr mktemp 3 , +.Xr packages 7 , +.Xr mtree 8 +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for +.Nx +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, recursive "down" +delete, etc. +.El diff --git a/pkgtools/pkg_install/files/delete/pkg_delete.cat1 b/pkgtools/pkg_install/files/delete/pkg_delete.cat1 new file mode 100644 index 00000000000..1f08bf8ae84 --- /dev/null +++ b/pkgtools/pkg_install/files/delete/pkg_delete.cat1 @@ -0,0 +1,135 @@ +PKG_DELETE(1) NetBSD Reference Manual PKG_DELETE(1) + +NNAAMMEE + ppkkgg__ddeelleettee - a utility for deleting previously installed software package + distributions + +SSYYNNOOPPSSIISS + ppkkgg__ddeelleettee [--DDddFFffnnOORRrrVVvv] [--pp _p_r_e_f_i_x] _p_k_g_-_n_a_m_e _._._. + +DDEESSCCRRIIPPTTIIOONN + The ppkkgg__ddeelleettee command is used to delete packages that have been previ- + ously installed with the pkg_add(1) command. + +WWAARRNNIINNGG + _S_i_n_c_e _t_h_e ppkkgg__ddeelleettee _c_o_m_m_a_n_d _m_a_y _e_x_e_c_u_t_e _s_c_r_i_p_t_s _o_r _p_r_o_g_r_a_m_s _p_r_o_v_i_d_e_d _b_y + _a _p_a_c_k_a_g_e _f_i_l_e_, _y_o_u_r _s_y_s_t_e_m _m_a_y _b_e _s_u_s_c_e_p_t_i_b_l_e _t_o _`_`_T_r_o_j_a_n _h_o_r_s_e_s_'_' _o_r + _o_t_h_e_r _s_u_b_t_l_e _a_t_t_a_c_k_s _f_r_o_m _m_i_s_c_r_e_a_n_t_s _w_h_o _c_r_e_a_t_e _d_a_n_g_e_r_o_u_s _p_a_c_k_a_g_e _f_i_l_e_s_. + + _Y_o_u _a_r_e _a_d_v_i_s_e_d _t_o _v_e_r_i_f_y _t_h_e _c_o_m_p_e_t_e_n_c_e _a_n_d _i_d_e_n_t_i_t_y _o_f _t_h_o_s_e _w_h_o _p_r_o_- + _v_i_d_e _i_n_s_t_a_l_l_a_b_l_e _p_a_c_k_a_g_e _f_i_l_e_s_. _F_o_r _e_x_t_r_a _p_r_o_t_e_c_t_i_o_n_, _e_x_a_m_i_n_e _a_l_l _t_h_e + _p_a_c_k_a_g_e _c_o_n_t_r_o_l _f_i_l_e_s _i_n _t_h_e _p_a_c_k_a_g_e _r_e_c_o_r_d _d_i_r_e_c_t_o_r_y _(_/_v_a_r_/_d_b_/_p_k_g_/_<_p_k_g_- + _n_a_m_e_>_/_)_. _P_a_y _p_a_r_t_i_c_u_l_a_r _a_t_t_e_n_t_i_o_n _t_o _a_n_y _+_I_N_S_T_A_L_L_, _+_D_E_I_N_S_T_A_L_L_, _+_R_E_Q_U_I_R_E + _o_r _+_M_T_R_E_E___D_I_R_S _f_i_l_e_s_, _a_n_d _i_n_s_p_e_c_t _t_h_e _+_C_O_N_T_E_N_T_S _f_i_l_e _f_o_r @@ccwwdd_, @@mmooddee + _(_c_h_e_c_k _f_o_r _s_e_t_u_i_d_)_, @@ddiirrrrmm_, @@eexxeecc_, _a_n_d @@uunneexxeecc _d_i_r_e_c_t_i_v_e_s_, _a_n_d_/_o_r _u_s_e _t_h_e + pkg_info(_1) _c_o_m_m_a_n_d _t_o _e_x_a_m_i_n_e _t_h_e _i_n_s_t_a_l_l_e_d _p_a_c_k_a_g_e _c_o_n_t_r_o_l _f_i_l_e_s_. + +OOPPTTIIOONNSS + The following command line options are supported: + + _p_k_g_-_n_a_m_e _._._. + The named packages are deinstalled, wildcards can be used, see + pkg_info(1). If no version is given, the one currently installed + will be removed. If the --FF flag is given, one or more (absolute) + filenames may be specified and the Package Database will be con- + sulted for the package to which the given file belongs. These + packages are then deinstalled. + + --DD If a deinstallation script exists for a given package, do not ex- + ecute it. + + --dd Remove empty directories created by file cleanup. By default, + only files/directories explicitly listed in a package's contents + (either as normal files/directories or with the @@ddiirrrrmm directive) + will be removed at deinstallation time. This option tells + ppkkgg__ddeelleettee to also remove any directories that were emptied as a + result of removing the package. + + --FF Any pkg-name given will be interpreted as pathname which is sub- + sequently transformed in a (real) package name via the Package + Database. That way, packages can be deleted by giving a filename + instead of the package-name. + + --ff Force removal of the package, even if a dependency is recorded or + the deinstall or require script fails. + + --nn Don't actually deinstall a package, just report the steps that + would be taken if it were. + + --OO Only delete the package's entries from the package database, do + not touch the package or its files itself. + + --pp _p_r_e_f_i_x + Set _p_r_e_f_i_x as the directory in which to delete files from any in- + stalled packages which do not explicitly set theirs. For most + packages, the prefix will be set automatically to the installed + location by pkg_add(1). + + --RR Like the --rr option, this does a recursive delete. The --RR option + deletes the given package and any packages required by it, unless + some other package still needs them. This can be used to delete + a package and all the packages it needs. + + --rr ppkkgg__ddeelleettee first builds a list of all packages that require (di- + rectly and indirectly) the one being deleted. It then deletes + these packages using ppkkgg__ddeelleettee with the given options before + deleting the user specified package. + + --VV Print version number and exit. + + --vv Turn on verbose output. + +TTEECCHHNNIICCAALL DDEETTAAIILLSS + ppkkgg__ddeelleettee does pretty much what it says. It examines installed package + records in _/_v_a_r_/_d_b_/_p_k_g_/_<_p_k_g_-_n_a_m_e_>, deletes the package contents, and fi- + nally removes the package records. + + If a package is required by other installed packages, ppkkgg__ddeelleettee will + list those dependent packages and refuse to delete the package (unless + the --ff option is given). + + If a filename is given instead of a package name, the package of which + the given file belongs to can be deleted if the --FF Flag is given. The + filename needs to be absolute, see the output produced by the pkg_info + --aaFF command. + + If the package contains a _r_e_q_u_i_r_e file (see pkg_create(1)), then this is + executed first as + rreeqquuiirree _<_p_k_g_-_n_a_m_e_> _D_E_I_N_S_T_A_L_L + (where _p_k_g_-_n_a_m_e is the name of the package in question and _D_E_I_N_S_T_A_L_L is a + keyword denoting that this is a deinstallation) to see whether or not de- + installation should continue. A non-zero exit status means no, unless + the --ff option is specified. + + If a ddeeiinnssttaallll script exists for the package, it is executed before and + after any files are removed. It is this script's responsibility to clean + up any additional messy details around the package's installation, since + all ppkkgg__ddeelleettee knows how to do is delete the files created in the origi- + nal distribution. The ddeeiinnssttaallll script is called as: + ddeeiinnssttaallll _<_p_k_g_-_n_a_m_e_> _D_E_I_N_S_T_A_L_L + before deleting all files and as: + ddeeiinnssttaallll _<_p_k_g_-_n_a_m_e_> _P_O_S_T_-_D_E_I_N_S_T_A_L_L + after deleting them. Passing the keywords _D_E_I_N_S_T_A_L_L and _P_O_S_T_-_D_E_I_N_S_T_A_L_L + lets you potentially write only one program/script that handles all as- + pects of installation and deletion. + + All scripts are called with the environment variable PKG_PREFIX set to + the installation prefix (see the --pp option above). This allows a package + author to write a script that reliably performs some action on the direc- + tory where the package is installed, even if the user might have changed + it by specifying the --pp option when running ppkkgg__ddeelleettee or pkg_add(1). + +SSEEEE AALLSSOO + pkg_add(1), pkg_admin(1), pkg_create(1), pkg_info(1), mktemp(3), + packages(7), mtree(8) + +AAUUTTHHOORRSS + Jordan Hubbard + most of the work + John Kohl + refined it for NetBSD + Hubert Feyrer + NetBSD wildcard dependency processing, pkgdb, recursive "down" + delete, etc. + +NetBSD 1.6 March 8, 1999 3 diff --git a/pkgtools/pkg_install/files/info/Makefile.in b/pkgtools/pkg_install/files/info/Makefile.in new file mode 100644 index 00000000000..5d7460dd40f --- /dev/null +++ b/pkgtools/pkg_install/files/info/Makefile.in @@ -0,0 +1,39 @@ +# From NetBSD: Makefile,v 1.1 1999/01/19 17:01:58 hubertf Exp + +PREFIX= @prefix@ +INSTALL= @INSTALL@ + +mandir= ${PREFIX}/man +mandircat1= ${mandir}/cat1 + +CC= @CC@ +CCLD= $(CC) +LIBS= @LIBS@ -linstall +CPPFLAGS= @CPPFLAGS@ +DEFS= @DEFS@ -I. -I@srcdir@ -I../lib +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ -L../lib + +LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ +COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) + +PROG= pkg_info + +SRCS= main.c perform.c show.c +OBJS= main.o perform.o show.o + +all: ${PROG} + +${PROG}: ${OBJS} + ${LINK} ${OBJS} ${LIBS} + +.c.o: + $(COMPILE) -c $< -o $@ + +clean: + rm -f ${OBJS} ${PROG} + +install: + ${INSTALL} ${PROG} ${PREFIX}/sbin + ${INSTALL} -m 755 -d ${mandircat1} + ${INSTALL} -m 444 ${PROG}.cat1 ${mandircat1}/${PROG}.1 diff --git a/pkgtools/pkg_install/files/info/info.h b/pkgtools/pkg_install/files/info/info.h new file mode 100644 index 00000000000..a18d450e195 --- /dev/null +++ b/pkgtools/pkg_install/files/info/info.h @@ -0,0 +1,71 @@ +/* $NetBSD: info.h,v 1.1.1.1 2002/12/20 18:14:12 schmonz Exp $ */ + +/* from FreeBSD Id: info.h,v 1.10 1997/02/22 16:09:40 peter Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 23 August 1993 + * + * Include and define various things wanted by the info command. + * + */ + +#ifndef _INST_INFO_H_INCLUDE +#define _INST_INFO_H_INCLUDE + +#ifndef MAXINDEXSIZE +#define MAXINDEXSIZE 60 +#endif + +#ifndef MAXNAMESIZE +#define MAXNAMESIZE 20 +#endif + +#define SHOW_COMMENT 0x00001 +#define SHOW_DESC 0x00002 +#define SHOW_PLIST 0x00004 +#define SHOW_INSTALL 0x00008 +#define SHOW_DEINSTALL 0x00010 +#define SHOW_REQUIRE 0x00020 +#define SHOW_PREFIX 0x00040 +#define SHOW_INDEX 0x00080 +#define SHOW_FILES 0x00100 +#define SHOW_DISPLAY 0x00200 +#define SHOW_REQBY 0x00400 +#define SHOW_MTREE 0x00800 +#define SHOW_BUILD_VERSION 0x01000 +#define SHOW_BUILD_INFO 0x02000 +#define SHOW_DEPENDS 0x04000 +#define SHOW_PKG_SIZE 0x08000 +#define SHOW_ALL_SIZE 0x10000 + +extern int Flags; +extern Boolean AllInstalled; +extern Boolean File2Pkg; +extern Boolean Quiet; +extern char *InfoPrefix; +extern char PlayPen[]; +extern size_t PlayPenSize; +extern char *CheckPkg; +extern size_t termwidth; +extern lpkg_head_t pkgs; + +extern void show_file(char *, char *); +extern void show_plist(char *, package_t *, pl_ent_t); +extern void show_files(char *, package_t *); +extern void show_depends(char *, package_t *); +extern void show_index(char *, char *); + +#endif /* _INST_INFO_H_INCLUDE */ diff --git a/pkgtools/pkg_install/files/info/main.c b/pkgtools/pkg_install/files/info/main.c new file mode 100644 index 00000000000..27e17085533 --- /dev/null +++ b/pkgtools/pkg_install/files/info/main.c @@ -0,0 +1,287 @@ +/* $NetBSD: main.c,v 1.1.1.1 2002/12/20 18:14:12 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char *rcsid = "from FreeBSD Id: main.c,v 1.14 1997/10/08 07:47:26 charnier Exp"; +#else +__RCSID("$NetBSD: main.c,v 1.1.1.1 2002/12/20 18:14:12 schmonz Exp $"); +#endif +#endif +#endif + +/* + * + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the add module. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" +#include "info.h" + +static const char Options[] = "aBbcDde:fFhIikLl:mnpqRrsSvV"; + +int Flags = 0; +Boolean AllInstalled = FALSE; +Boolean File2Pkg = FALSE; +Boolean Quiet = FALSE; +char *InfoPrefix = ""; +char PlayPen[FILENAME_MAX]; +size_t PlayPenSize = sizeof(PlayPen); +char *CheckPkg = NULL; +size_t termwidth = 0; +lpkg_head_t pkgs; + +static void +usage(void) +{ + fprintf(stderr, "%s\n%s\n%s\n", + "usage: pkg_info [-BbcDdFfIikLmnpqRrSsVvh] [-e package] [-l prefix]", + " pkg-name [pkg-name ...]", + " pkg_info -a [flags]"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, rc; + lpkg_t *lpp; + + setprogname(argv[0]); + + while ((ch = getopt(argc, argv, Options)) != -1) + switch (ch) { + case 'a': + AllInstalled = TRUE; + break; + + case 'B': + Flags |= SHOW_BUILD_INFO; + break; + + case 'b': + Flags |= SHOW_BUILD_VERSION; + break; + + case 'c': + Flags |= SHOW_COMMENT; + break; + + case 'D': + Flags |= SHOW_DISPLAY; + break; + + case 'd': + Flags |= SHOW_DESC; + break; + + case 'e': + CheckPkg = optarg; + break; + + case 'f': + Flags |= SHOW_PLIST; + break; + + case 'F': + File2Pkg = 1; + break; + + case 'I': + Flags |= SHOW_INDEX; + break; + + case 'i': + Flags |= SHOW_INSTALL; + break; + + case 'k': + Flags |= SHOW_DEINSTALL; + break; + + case 'L': + Flags |= SHOW_FILES; + break; + + case 'l': + InfoPrefix = optarg; + break; + + case 'm': + Flags |= SHOW_MTREE; + break; + + case 'n': + Flags |= SHOW_DEPENDS; + break; + + case 'p': + Flags |= SHOW_PREFIX; + break; + + case 'q': + Quiet = TRUE; + break; + + case 'R': + Flags |= SHOW_REQBY; + break; + + case 'r': + Flags |= SHOW_REQUIRE; + break; + + case 's': + Flags |= SHOW_PKG_SIZE; + break; + + case 'S': + Flags |= SHOW_ALL_SIZE; + 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 | + SHOW_REQBY | SHOW_DEPENDS | SHOW_PKG_SIZE | SHOW_ALL_SIZE; + break; + + case 'V': + show_version(); + /* NOTREACHED */ + + case 'h': + case '?': + default: + usage(); + /* NOTREACHED */ + } + + argc -= optind; + argv += optind; + + if (argc == 0 && !Flags && !CheckPkg) { + /* No argument or flags specified - assume -Ia */ + Flags = SHOW_INDEX; + AllInstalled = TRUE; + } + + /* Don't do FTP stuff when operating on all pkgs */ + if (AllInstalled && getenv("PKG_PATH") != 0) { + warnx("disabling PKG_PATH when operating on all packages."); + unsetenv("PKG_PATH"); + } + + path_create(getenv("PKG_PATH")); + + /* Set some reasonable defaults */ + if (!Flags) + Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY | SHOW_DEPENDS; + + /* -Fe /filename -> change CheckPkg to real packagename */ + if (CheckPkg && File2Pkg) { + char *s; + + if (pkgdb_open(1) == -1) + err(1, "cannot open pkgdb"); + + s = pkgdb_retrieve(CheckPkg); + + if (s) { + CheckPkg = strdup(s); + } else { + errx(1, "No matching pkg for %s.", CheckPkg); + } + + pkgdb_close(); + } + + TAILQ_INIT(&pkgs); + + /* Get all the remaining package names, if any */ + if (File2Pkg && !AllInstalled) + if (pkgdb_open(1) == -1) { + err(1, "cannot open pkgdb"); + } + while (*argv) { + /* pkgdb: if -F flag given, don't add pkgnames to the "pkgs" + * queue but rather resolve the given filenames to pkgnames + * using pkgdb_retrieve, then add them. */ + if (File2Pkg) { + char *s; + + s = pkgdb_retrieve(*argv); + + if (s) { + lpp = alloc_lpkg(s); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } else + errx(1, "No matching pkg for %s.", *argv); + } else { + if (ispkgpattern(*argv)) { + if (findmatchingname(_pkgdb_getPKGDB_DIR(), *argv, add_to_list_fn, &pkgs) == 0) + errx(1, "No matching pkg for %s.", *argv); + } else { + lpp = alloc_lpkg(*argv); + TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); + } + } + argv++; + } + + if (File2Pkg) + pkgdb_close(); + + /* If no packages, yelp */ + if (TAILQ_FIRST(&pkgs) == NULL && !AllInstalled && !CheckPkg) + warnx("missing package name(s)"), usage(); + + if (isatty(STDOUT_FILENO)) { + const char *p; + struct winsize win; + + if ((p = getenv("COLUMNS")) != NULL) + termwidth = atoi(p); + else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && + win.ws_col > 0) + termwidth = win.ws_col; + } + + rc = pkg_perform(&pkgs); + exit(rc); + /* NOTREACHED */ +} diff --git a/pkgtools/pkg_install/files/info/perform.c b/pkgtools/pkg_install/files/info/perform.c new file mode 100644 index 00000000000..c8dddc7b3b2 --- /dev/null +++ b/pkgtools/pkg_install/files/info/perform.c @@ -0,0 +1,381 @@ +/* $NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:14:13 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: perform.c,v 1.23 1997/10/13 15:03:53 jkh Exp"; +#else +__RCSID("$NetBSD: perform.c,v 1.1.1.1 2002/12/20 18:14:13 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 23 Aug 1993 + * + * This is the main body of the info module. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "lib.h" +#include "info.h" + +#include <sys/types.h> + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <signal.h> + +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif + +#include <ctype.h> + +static char *Home; + +static int +pkg_do(char *pkg) +{ + Boolean installed = FALSE, isTMP = FALSE; + char log_dir[FILENAME_MAX]; + char fname[FILENAME_MAX]; + struct stat sb; + char *cp = NULL; + int code = 0; + + if (IS_URL(pkg)) { + if ((cp = fileGetURL(pkg)) != NULL) { + strcpy(fname, cp); + isTMP = TRUE; + } + } else if (fexists(pkg) && isfile(pkg)) { + int len; + + if (*pkg != '/') { + if (!getcwd(fname, FILENAME_MAX)) { + cleanup(0); + err(1, "fatal error during execution: getcwd"); + } + len = strlen(fname); + (void) snprintf(&fname[len], sizeof(fname) - len, "/%s", pkg); + } else { + strcpy(fname, pkg); + } + cp = fname; + } else { + if ((cp = fileFindByPath(pkg)) != NULL) { + strncpy(fname, cp, FILENAME_MAX); + } + } + + if (cp) { + if (IS_URL(pkg)) { + /* file is already unpacked by fileGetURL() */ + strcpy(PlayPen, cp); + } else { + if (IS_URL(cp)) { + /* only a package name was given, and it was expanded to a + * full URL by fileFindByPath. Now extract... + */ + char *cp2; + + if ((cp2 = fileGetURL(cp)) != NULL) { + strcpy(fname, cp2); + isTMP = TRUE; + } + strcpy(PlayPen, cp2); + } 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, PlayPenSize, sb.st_size / 2); + if (unpack(fname, "+*")) { + warnx("error during unpacking, no info for '%s' available", pkg); + code = 1; + goto bail; + } + } + } + } else { + /* + * It's not an uninstalled package, try and find it among the + * installed + */ + char *tmp; + + (void) snprintf(log_dir, sizeof(log_dir), "%s/%s", + (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + pkg); + if (!fexists(log_dir) || !isdir(log_dir)) { + { + /* Check if the given package name matches + * something with 'pkg-[0-9]*' */ + char try[FILENAME_MAX]; + snprintf(try, FILENAME_MAX, "%s-[0-9]*", pkg); + if (findmatchingname(_pkgdb_getPKGDB_DIR(), try, + add_to_list_fn, &pkgs) != 0) { + return 0; /* we've just appended some names to the pkgs list, + * they will be processed after this package. */ + } + } + + /* No match */ + 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; + } + + /* + * Index is special info type that has to override all others to make + * any sense. + */ + if (Flags & SHOW_INDEX) { + char tmp[FILENAME_MAX]; + + (void) snprintf(tmp, sizeof(tmp), "%-19s ", pkg); + show_index(tmp, COMMENT_FNAME); + } else { + FILE *fp; + package_t plist; + + /* Read 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); + + /* 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_DEPENDS) { + show_depends("Requires:\n", &plist); + } + 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_SHOW_ALL); + } + 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_REQUIRE) && fexists(REQUIRE_FNAME)) { + show_file("Require script:\n", REQUIRE_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 ((Flags & SHOW_BUILD_VERSION) && fexists(BUILD_VERSION_FNAME)) { + show_file("Build version:\n", BUILD_VERSION_FNAME); + } + if ((Flags & SHOW_BUILD_INFO) && fexists(BUILD_INFO_FNAME)) { + show_file("Build information:\n", BUILD_INFO_FNAME); + } + if ((Flags & SHOW_PKG_SIZE) && fexists(SIZE_PKG_FNAME)) { + show_file("Size of this package in bytes: ", SIZE_PKG_FNAME); + } + if ((Flags & SHOW_ALL_SIZE) && fexists(SIZE_ALL_FNAME)) { + show_file("Size in bytes including required pkgs: ", SIZE_ALL_FNAME); + } + if (!Quiet) { + puts(InfoPrefix); + } + free_plist(&plist); + } +bail: + leave_playpen(Home); + if (isTMP) + unlink(fname); + return code; +} + +/* + * Function to be called for pkgs found + */ +static int +foundpkg(const char *found, void *vp) +{ + char *data = vp; + char buf[FILENAME_MAX+1]; + + /* we only want to display this if it really is a directory */ + snprintf(buf, sizeof(buf), "%s/%s", data, found); + if (!isdir(buf)) { + /* return value seems to be ignored for now */ + return -1; + } + + if (!Quiet) { + printf("%s\n", found); + } + + return 0; +} + +/* + * Check if a package "pkgspec" (which can be a pattern) is installed. + * dbdir contains the return value of _pkgdb_getPKGDB_DIR(), for reading only. + * Return 0 if found, 1 otherwise (indicating an error). + */ +static int +CheckForPkg(char *pkgspec, char *dbdir) +{ + char buf[FILENAME_MAX]; + int error; + + if (strpbrk(pkgspec, "<>[]?*{")) { + /* expensive (pattern) match */ + return !findmatchingname(dbdir, pkgspec, foundpkg, dbdir); + } + /* simple match */ + (void) snprintf(buf, sizeof(buf), "%s/%s", dbdir, pkgspec); + error = !isdir(buf); + if (!error && !Quiet) { + printf("%s\n", pkgspec); + } + if (error) { + /* found nothing - try 'pkg-[0-9]*' */ + + char try[FILENAME_MAX]; + snprintf(try, FILENAME_MAX, "%s-[0-9]*", pkgspec); + if (findmatchingname(dbdir, try, foundpkg, dbdir) != 0) { + error = 0; + } + } + return error; +} + +void +cleanup(int sig) +{ + leave_playpen(Home); + exit(1); +} + +int +pkg_perform(lpkg_head_t *pkghead) +{ + struct dirent *dp; + char *tmp; + DIR *dirp; + int err_cnt = 0; + + signal(SIGINT, cleanup); + + tmp = _pkgdb_getPKGDB_DIR(); + + /* Overriding action? */ + if (CheckPkg) { + err_cnt += CheckForPkg(CheckPkg, tmp); + } else if (AllInstalled) { + if (!(isdir(tmp) || islinktodir(tmp))) + return 1; + + if (File2Pkg) { + /* Show all files with the package they belong to */ + char *file, *pkg; + + /* pkg_info -Fa => Dump pkgdb */ + if (pkgdb_open(1) == -1) { + err(1, "cannot open pkgdb"); + } + while ((file = pkgdb_iter())) { + pkg = pkgdb_retrieve(file); + printf("%-50s %s\n", file, pkg); + } + pkgdb_close(); + } else { + /* Show all packges with description */ + if ((dirp = opendir(tmp)) != (DIR *) NULL) { + while ((dp = readdir(dirp)) != (struct dirent *) NULL) { + char tmp2[FILENAME_MAX]; + + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + + (void) snprintf(tmp2, sizeof(tmp2), "%s/%s", + tmp, dp->d_name); + if (isfile(tmp2)) + continue; + + err_cnt += pkg_do(dp->d_name); + } + (void) closedir(dirp); + } + } + } else { + /* Show info on individual pkg(s) */ + lpkg_t *lpp; + + while ((lpp = TAILQ_FIRST(pkghead))) { + TAILQ_REMOVE(pkghead, lpp, lp_link); + err_cnt += pkg_do(lpp->lp_name); + free_lpkg(lpp); + } + } + ftp_stop(); + return err_cnt; +} diff --git a/pkgtools/pkg_install/files/info/pkg_info.1 b/pkgtools/pkg_install/files/info/pkg_info.1 new file mode 100644 index 00000000000..70494bceab6 --- /dev/null +++ b/pkgtools/pkg_install/files/info/pkg_info.1 @@ -0,0 +1,262 @@ +.\" $NetBSD: pkg_info.1,v 1.1.1.1 2002/12/20 18:14:13 schmonz Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintainance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_info.1 +.\" +.Dd March 4, 1999 +.Dt PKG_INFO 1 +.Os +.Sh NAME +.Nm pkg_info +.Nd a utility for displaying information on software packages +.Sh SYNOPSIS +.Nm +.Op Fl BbcDdFfhIikLmnpqRrSsVv +.Bk -words +.Op Fl e Ar package +.Ek +.Bk -words +.Op Fl l Ar prefix +.Ek +.Ar pkg-name ... +.Nm +.Bk -words +.Op Fl a Ar flags +.Ek +.Sh DESCRIPTION +The +.Nm +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. +.Pp +The +.Ar pkg-name +may be the name of an installed package (with our without version), a +pattern matching several installed packages (see the +.Fl e +switch for a description of possible patterns), +the pathname to a +package distribution file, a filename belonging to an installed +package (if +.Fl F +is also given), or a URL to an ftp-available package. +.Pp +The following command-line options are supported: +.Bl -tag -width indent +.It Fl a +Show information for all currently installed packages. +.It Fl B +Show some of the important definitions used when building +the binary package (the "Build information") for each package. +.It Fl b +Show the +.Nx +RCS Id strings from the files used in the construction +of the binary package (the "Build version") for each package. +These files are the package Makefile, any patch files, any checksum +files, and the packing list file. +.It Fl c +Show the one-line comment field for each package. +.It Fl D +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 +This option +allows you to test for the presence of another (perhaps +prerequisite) package from a script. +If the package identified by +.Ar pkg-name +is currently installed, return 0, otherwise return 1. +In addition, the names of any package(s) found installed are printed to +stdout unless turned off using the +.Fl q +option. +.Pp +If the given +.Ar pkg-name +contains a +shell meta character, it will be matched against all installed +packages using +.Xr fnmatch 3 . +.Xr csh 1 +style {,} alternates have also been implemented in addition to this. +Package version numbers can also be matched in a relational manner +using the +.Pa \*[Ge], \*[Le], \*[Gt] +and +.Pa \*[Lt] +operators. +For example, +.Pa pkg_info -e 'name\*[Ge]1.3' +will match versions 1.3 and later of the +.Pa name +package. +The collating sequence of the various package version numbers is +unusual, but strives to be consistent. +The magic string ``rc'' equates to +.Pa release candidate +and sorts before a release. +For example, +.Pa name-1.3rc3 +will sort before +.Pa name-1.3 +and after +.Pa name-1.2.9 +In addition, alphabetic characters sort in the same place as +their numeric counterparts, so that +.Pa name-1.2e +has the same sorting value as +.Pa name-1.2.5 +The magic string ``pl'' equates to a +.Pa patch level +and has the same value as a dot in the dewey-decimal ordering schemes. +.It Fl F +Interpret any pkg-name given as filename, and translate it to a +package name using the Package Database. +This can be used to query information on a per-file basis, e.g. in +conjunction with the +.Fl e +flag to find out which package a file belongs to. +.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 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 l Ar str +Prefix each information category header (see +.Fl q ) +shown with +.Ar str . +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 m +Show the mtree file (if any) for each package. +.It Fl n +Show which packages each package needs (depends upon), if any. +.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 S +Show the size of this package and all the packages it requires, +in bytes. +.It Fl s +Show the size of this package in bytes. +The size is calculated by adding up the size of each file of the package. +.It Fl V +Print version number and exit. +.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 semicolon-separated list of paths and URLs to search for +package files. +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 +in +.Pa /var/db/pkg/\*[Lt]pkg-name\*[Gt] . +.Pp +A filename can be given instead of a (installed) package name to query +information on the package this file belongs to. +This filename is then resolved to a package name using the Package Database. +For this translation to take place, the +.Fl F +flag must be given. +The filename must be absolute, compare the output of pkg_info +.Fl aF . +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 , +.Xr pkg_create 1 , +.Xr pkg_delete 1 , +.Xr mktemp 3 , +.Xr packages 7 , +.Xr mtree 8 +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for +.Nx +.It "Hubert Feyrer" +.Nx +wildcard dependency processing, pkgdb, depends displaying, +pkg size display etc. +.El diff --git a/pkgtools/pkg_install/files/info/pkg_info.cat1 b/pkgtools/pkg_install/files/info/pkg_info.cat1 new file mode 100644 index 00000000000..3dba143ceca --- /dev/null +++ b/pkgtools/pkg_install/files/info/pkg_info.cat1 @@ -0,0 +1,157 @@ +PKG_INFO(1) NetBSD Reference Manual PKG_INFO(1) + +NNAAMMEE + ppkkgg__iinnffoo - a utility for displaying information on software packages + +SSYYNNOOPPSSIISS + ppkkgg__iinnffoo [--BBbbccDDddFFffhhIIiikkLLmmnnppqqRRrrSSssVVvv] [--ee _p_a_c_k_a_g_e] [--ll _p_r_e_f_i_x] _p_k_g_-_n_a_m_e _._._. + ppkkgg__iinnffoo [--aa _f_l_a_g_s] + +DDEESSCCRRIIPPTTIIOONN + The ppkkgg__iinnffoo 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 pkg_create(1) command. + + The _p_k_g_-_n_a_m_e may be the name of an installed package (with our without + version), a pattern matching several installed packages (see the --ee + switch for a description of possible patterns), the pathname to a package + distribution file, a filename belonging to an installed package (if --FF is + also given), or a URL to an ftp-available package. + + The following command-line options are supported: + + --aa Show information for all currently installed packages. + + --BB Show some of the important definitions used when building the bi- + nary package (the "Build information") for each package. + + --bb Show the NetBSD RCS Id strings from the files used in the con- + struction of the binary package (the "Build version") for each + package. These files are the package Makefile, any patch files, + any checksum files, and the packing list file. + + --cc Show the one-line comment field for each package. + + --DD Show the install-message file (if any) for each package. + + --dd Show the long-description field for each package. + + --ee _p_k_g_-_n_a_m_e + This option allows you to test for the presence of another (per- + haps prerequisite) package from a script. If the package identi- + fied by _p_k_g_-_n_a_m_e is currently installed, return 0, otherwise re- + turn 1. In addition, the names of any package(s) found installed + are printed to stdout unless turned off using the --qq option. + + If the given _p_k_g_-_n_a_m_e contains a shell meta character, it will be + matched against all installed packages using fnmatch(3). csh(1) + style {,} alternates have also been implemented in addition to + this. Package version numbers can also be matched in a relation- + al manner using the _>_=_, _<_=_, _> and _< operators. For example, + _p_k_g___i_n_f_o _-_e _'_n_a_m_e_>_=_1_._3_' will match versions 1.3 and later of the + _n_a_m_e package. The collating sequence of the various package ver- + sion numbers is unusual, but strives to be consistent. The magic + string ``rc'' equates to _r_e_l_e_a_s_e _c_a_n_d_i_d_a_t_e and sorts before a re- + lease. For example, _n_a_m_e_-_1_._3_r_c_3 will sort before _n_a_m_e_-_1_._3 and + after _n_a_m_e_-_1_._2_._9 In addition, alphabetic characters sort in the + same place as their numeric counterparts, so that _n_a_m_e_-_1_._2_e has + the same sorting value as _n_a_m_e_-_1_._2_._5 The magic string ``pl'' + equates to a _p_a_t_c_h _l_e_v_e_l and has the same value as a dot in the + dewey-decimal ordering schemes. + + --FF Interpret any pkg-name given as filename, and translate it to a + package name using the Package Database. This can be used to + query information on a per-file basis, e.g. in conjunction with + the --ee flag to find out which package a file belongs to. + + --ff Show the packing list instructions for each package. + + --II Show the index entry for each package. + + --ii Show the install script (if any) for each package. + + --kk Show the de-install script (if any) for each package. + + --LL Show the files within each package. This is different from just + viewing the packing list, since full pathnames for everything are + generated. + + --ll _s_t_r Prefix each information category header (see --qq) shown with _s_t_r. + This is primarily of use to front-end programs that want to re- + quest a lot of different information fields at once for a pack- + age, but don't necessary want the output intermingled in such a + way that they can't organize it. This lets you add a special to- + ken to the start of each field. + + --mm Show the mtree file (if any) for each package. + + --nn Show which packages each package needs (depends upon), if any. + + --pp Show the installation prefix for each package. + + --qq Be ``quiet'' in emitting report headers and such, just dump the + raw info (basically, assume a non-human reading). + + --RR Show which packages are required by each package. + + --rr Show the requirements script (if any) for each package. + + --SS Show the size of this package and all the packages it requires, + in bytes. + + --ss Show the size of this package in bytes. The size is calculated + by adding up the size of each file of the package. + + --VV Print version number and exit. + + --vv Turn on verbose output. + +EENNVVIIRROONNMMEENNTT + PKG_DBDIR The standard package database directory, _/_v_a_r_/_d_b_/_p_k_g, can be + overridden by specifying an alternative directory in the + PKG_DBDIR environment variable. + + PKG_PATH This can be used to specify a semicolon-separated list of + paths and URLs to search for package files. If PKG_PATH is + used, the suffix _._t_g_z is automatically appended to the _p_k_g_- + _n_a_m_e, whereas searching in the current directory uses _p_k_g_-_n_a_m_e + literally. + + PKG_TMPDIR, TMPDIR + These are tried in turn (if set) as candidate directories in + which to create a ``staging area'' for any files extracted by + ppkkgg__iinnffoo from package files. If neither PKG_TMPDIR nor TMPDIR + yields a suitable scratch directory, _/_v_a_r_/_t_m_p, _/_t_m_p, and + _/_u_s_r_/_t_m_p are tried in turn. Note that _/_u_s_r_/_t_m_p may be creat- + ed, if it doesn't already exist. + + Since ppkkgg__iinnffoo requires very little information to be extract- + ed 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. + +TTEECCHHNNIICCAALL DDEETTAAIILLSS + Package info is either extracted from package files named on the command + line, or from already installed package information in _/_v_a_r_/_d_b_/_p_k_g_/_<_p_k_g_- + _n_a_m_e_>. + + A filename can be given instead of a (installed) package name to query + information on the package this file belongs to. This filename is then + resolved to a package name using the Package Database. For this transla- + tion to take place, the --FF flag must be given. The filename must be ab- + solute, compare the output of pkg_info --aaFF. + +SSEEEE AALLSSOO + pkg_add(1), pkg_admin(1), pkg_create(1), pkg_delete(1), mktemp(3), + packages(7), mtree(8) + +AAUUTTHHOORRSS + Jordan Hubbard + most of the work + John Kohl + refined it for NetBSD + Hubert Feyrer + NetBSD wildcard dependency processing, pkgdb, depends displaying, + pkg size display etc. + +NetBSD 1.6 March 4, 1999 3 diff --git a/pkgtools/pkg_install/files/info/show.c b/pkgtools/pkg_install/files/info/show.c new file mode 100644 index 00000000000..29c4b5a56cd --- /dev/null +++ b/pkgtools/pkg_install/files/info/show.c @@ -0,0 +1,290 @@ +/* $NetBSD: show.c,v 1.1.1.1 2002/12/20 18:14:14 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: show.c,v 1.11 1997/10/08 07:47:38 charnier Exp"; +#else +__RCSID("$NetBSD: show.c,v 1.1.1.1 2002/12/20 18:14:14 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 23 Aug 1993 + * + * Various display routines for the info module. + * + */ +/* + * Copyright (c) 1999 Hubert Feyrer. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Hubert Feyrer for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" +#include "info.h" + +/* Structure to define entries for the "show table" */ +typedef struct show_t { + pl_ent_t sh_type; /* type of entry */ + char *sh_quiet; /* message when quiet */ + char *sh_verbose; /* message when verbose */ +} show_t; + +/* + * The entries in this table must be ordered the same as + * pl_ent_t constants + */ +static const show_t showv[] = { + {PLIST_FILE, "%s", "\tFile: %s"}, + {PLIST_CWD, "@cwd %s", "\tCWD to: %s"}, + {PLIST_CMD, "@exec %s", "\tEXEC '%s'"}, + {PLIST_CHMOD, "@chmod %s", "\tCHMOD to %s"}, + {PLIST_CHOWN, "@chown %s", "\tCHOWN to %s"}, + {PLIST_CHGRP, "@chgrp %s", "\tCHGRP to %s"}, + {PLIST_COMMENT, "@comment %s", "\tComment: %s"}, + {PLIST_IGNORE, "@ignore", "Ignore next file:"}, + {PLIST_NAME, "@name %s", "\tPackage name: %s"}, + {PLIST_UNEXEC, "@unexec %s", "\tUNEXEC '%s'"}, + {PLIST_SRC, "@src: %s", "\tSRC to: %s"}, + {PLIST_DISPLAY, "@display %s", "\tInstall message file: %s"}, + {PLIST_PKGDEP, "@pkgdep %s", "\tPackage depends on: %s"}, + {PLIST_MTREE, "@mtree %s", "\tPackage mtree file: %s"}, + {PLIST_DIR_RM, "@dirrm %s", "\tDeinstall directory remove: %s"}, + {PLIST_IGNORE_INST, "@ignore_inst ??? doesn't belong here", + "\tIgnore next file installation directive (doesn't belong)"}, + {PLIST_OPTION, "@option %s", "\tPackage has option: %s"}, + {PLIST_PKGCFL, "@pkgcfl %s", "\tPackage conflicts with: %s"}, + {PLIST_BLDDEP, "@blddep %s", "\tPackage depends exactly on: %s"}, + {-1, NULL, NULL} +}; + +void +show_file(char *title, char *fname) +{ + FILE *fp; + char line[1024]; + int n; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + if ((fp = fopen(fname, "r")) == (FILE *) NULL) { + printf("ERROR: show_file: Can't open '%s' for reading!\n", fname); + } else { + int append_nl = 0; + while ((n = fread(line, 1, sizeof(line), fp)) != 0) { + fwrite(line, 1, n, stdout); + append_nl = (line[n - 1] != '\n'); + } + (void) fclose(fp); + if (append_nl) + printf("\n"); + } + printf("\n"); /* just in case */ +} + +void +show_index(char *title, char *fname) +{ + FILE *fp; + char *line; + size_t linelen; + size_t maxline = termwidth; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + maxline -= MAXNAMESIZE; + } + if ((fp = fopen(fname, "r")) == (FILE *) NULL) { + warnx("show_file: can't open '%s' for reading", fname); + return; + } + if ((line = fgetln(fp, &linelen))) { + line[linelen - 1] = '\0'; /* tromp newline & terminate string */ + if (termwidth && (linelen > maxline)) { + /* XXX -1 if term does NOT have xn (or xenl) quirk */ + line[maxline] = '\0'; + } + (void) printf("%s\n", line); + } + (void) fclose(fp); +} + +/* + * Show a packing list item type. If type is PLIST_SHOW_ALL, show all + */ +void +show_plist(char *title, package_t *plist, pl_ent_t type) +{ + plist_t *p; + Boolean ign; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (ign = FALSE, p = plist->head; p; p = p->next) { + if (p->type == type || type == PLIST_SHOW_ALL) { + switch (p->type) { + case PLIST_FILE: + printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose, p->name); + if (ign) { + if (!Quiet) { + printf(" (ignored)"); + } + ign = FALSE; + } + break; + case PLIST_CHMOD: + case PLIST_CHOWN: + case PLIST_CHGRP: + printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose, + p->name ? p->name : "(clear default)"); + break; + case PLIST_IGNORE: + printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose); + ign = TRUE; + break; + case PLIST_IGNORE_INST: + printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose, p->name); + ign = TRUE; + break; + case PLIST_CWD: + case PLIST_CMD: + case PLIST_SRC: + case PLIST_UNEXEC: + case PLIST_COMMENT: + case PLIST_NAME: + case PLIST_DISPLAY: + case PLIST_PKGDEP: + case PLIST_MTREE: + case PLIST_DIR_RM: + case PLIST_OPTION: + case PLIST_PKGCFL: + case PLIST_BLDDEP: + printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose, p->name); + break; + default: + warnx("unknown command type %d (%s)", p->type, p->name); + } + (void) fputc('\n', stdout); + } + } +} + +/* + * Show all files in the packing list (except ignored ones) + */ +void +show_files(char *title, package_t *plist) +{ + plist_t *p; + Boolean ign; + char *dir = "."; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (ign = FALSE, p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_FILE: + if (!ign) { + printf("%s/%s\n", dir, p->name); + } + ign = FALSE; + break; + case PLIST_CWD: + dir = p->name; + break; + case PLIST_IGNORE: + ign = TRUE; + break; + default: + break; + } + } +} + +/* + * Show dependencies (packages this pkg requires) + */ +void +show_depends(char *title, package_t *plist) +{ + plist_t *p; + int nodepends; + + nodepends = 1; + for (p = plist->head; p && nodepends; p = p->next) { + switch (p->type) { + case PLIST_PKGDEP: + nodepends = 0; + break; + default: + break; + } + } + if (nodepends) + return; + + if (!Quiet) { + printf("%s%s", InfoPrefix, title); + } + for (p = plist->head; p; p = p->next) { + switch (p->type) { + case PLIST_PKGDEP: + printf("%s\n", p->name); + break; + default: + break; + } + } + + printf("\n"); +} diff --git a/pkgtools/pkg_install/files/install-sh b/pkgtools/pkg_install/files/install-sh new file mode 100755 index 00000000000..89fc9b098b8 --- /dev/null +++ b/pkgtools/pkg_install/files/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/pkgtools/pkg_install/files/lib/Makefile.in b/pkgtools/pkg_install/files/lib/Makefile.in new file mode 100644 index 00000000000..102f099345e --- /dev/null +++ b/pkgtools/pkg_install/files/lib/Makefile.in @@ -0,0 +1,38 @@ +# Based on NetBSD: Makefile,v 1.17 2001/12/12 01:48:54 tv Exp +# Original from FreeBSD, no rcs id. + +RANLIB= @RANLIB@ +AR= @AR@ +CC= @CC@ +CCLD= $(CC) +LIBS= @LIBS@ -linstall +CPPFLAGS= @CPPFLAGS@ +DEFS= @DEFS@ -I. -I@srcdir@ +CFLAGS= @CFLAGS@ +LDFLAGS= @LDFLAGS@ -L../lib + +LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ +COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) + +LIBINSTALL= libinstall.a + +SRCS= digest.c exec.c file.c fgetln.c ftpio.c global.c lpkg.c \ + pen.c pkgdb.c plist.c str.c version.c path.c \ + err.c setprogname.c setenv.c unsetenv.c +OBJS= digest.o exec.o file.o fgetln.o ftpio.o global.o lpkg.o \ + pen.o pkgdb.o plist.o str.o version.o path.o \ + err.o setprogname.o setenv.o unsetenv.o + +libinstall.a: ${OBJS} + ${AR} crv ${LIBINSTALL} ${OBJS} + ${RANLIB} ${LIBINSTALL} + +version.o: version.h version.c + +.c.o: + $(COMPILE) -c $< -o $@ + +clean: + rm -f ${OBJS} ${LIBINSTALL} + +install: diff --git a/pkgtools/pkg_install/files/lib/config.h.in b/pkgtools/pkg_install/files/lib/config.h.in new file mode 100644 index 00000000000..1d52c9fa8b5 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/config.h.in @@ -0,0 +1,169 @@ +/* lib/config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +#undef size_t + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you have the MD5File function. */ +#undef HAVE_MD5FILE + +/* Define if you have the chflags function. */ +#undef HAVE_CHFLAGS + +/* Define if you have the dbopen function. */ +#undef HAVE_DBOPEN + +/* Define if you have the err function. */ +#undef HAVE_ERR + +/* Define if you have the errx function. */ +#undef HAVE_ERRX + +/* Define if you have the fgetln function. */ +#undef HAVE_FGETLN + +/* Define if you have the getprogname function. */ +#undef HAVE_GETPROGNAME + +/* Define if you have the mkdtemp function. */ +#undef HAVE_MKDTEMP + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setprogname function. */ +#undef HAVE_SETPROGNAME + +/* Define if you have the statfs function. */ +#undef HAVE_STATFS + +/* Define if you have the statvfs function. */ +#undef HAVE_STATVFS + +/* Define if you have the strlcpy function. */ +#undef HAVE_STRLCPY + +/* Define if you have the strsep function. */ +#undef HAVE_STRSEP + +/* Define if you have the unsetenv function. */ +#undef HAVE_UNSETENV + +/* Define if you have the warn function. */ +#undef HAVE_WARN + +/* Define if you have the warnx function. */ +#undef HAVE_WARNX + +/* Define if you have the <assert.h> header file. */ +#undef HAVE_ASSERT_H + +/* Define if you have the <db.h> header file. */ +#undef HAVE_DB_H + +/* Define if you have the <db1/db.h> header file. */ +#undef HAVE_DB1_DB_H + +/* Define if you have the <dirent.h> header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the <err.h> header file. */ +#undef HAVE_ERR_H + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <fnmatch.h> header file. */ +#undef HAVE_FNMATCH_H + +/* Define if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the <md5.h> header file. */ +#undef HAVE_MD5_H + +/* Define if you have the <md5global.h> header file. */ +#undef HAVE_MD5GLOBAL_H + +/* Define if you have the <netdb.h> header file. */ +#undef HAVE_NETDB_H + +/* Define if you have the <pwd.h> header file. */ +#undef HAVE_PWD_H + +/* Define if you have the <regex.h> header file. */ +#undef HAVE_REGEX_H + +/* Define if you have the <signal.h> header file. */ +#undef HAVE_SIGNAL_H + +/* Define if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define if you have the <sys/file.h> header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the <sys/ioctl.h> header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define if you have the <sys/mount.h> header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define if you have the <sys/param.h> header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the <sys/queue.h> header file. */ +#undef HAVE_SYS_QUEUE_H + +/* Define if you have the <sys/resource.h> header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if you have the <sys/vfs.h> header file. */ +#undef HAVE_SYS_VFS_H + +/* Define if you have the <sys/wait.h> header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have the <termios.h> header file. */ +#undef HAVE_TERMIOS_H + +/* Define if you have the <time.h> header file. */ +#undef HAVE_TIME_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the <vis.h> header file. */ +#undef HAVE_VIS_H + +/* Define if you have the db1 library (-ldb1). */ +#undef HAVE_LIBDB1 + +/* Define if you have the md library (-lmd). */ +#undef HAVE_LIBMD + +#ifndef HAVE___ATTRIBUTE__ +# define __attribute__(x) +#endif + +#ifndef HAVE_GETPROGNAME +const char *getprogname(void); +#endif + diff --git a/pkgtools/pkg_install/files/lib/defs.h b/pkgtools/pkg_install/files/lib/defs.h new file mode 100644 index 00000000000..0a076049242 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/defs.h @@ -0,0 +1,92 @@ +/* $NetBSD: defs.h,v 1.1.1.1 2002/12/20 18:13:59 schmonz Exp $ */ + +/* + * Copyright (c) 1999-2000 Alistair G. Crooks. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Alistair G. Crooks. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef DEFS_H_ +#define DEFS_H_ + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#define NEWARRAY(type,ptr,size,where,action) do { \ + if ((ptr = (type *) calloc(sizeof(type), (unsigned)(size))) == NULL) { \ + warn("%s: can't allocate %lu bytes", where, \ + (unsigned long)(size * sizeof(type))); \ + action; \ + } \ +} while( /* CONSTCOND */ 0) + +#define RENEW(type,ptr,size,where,action) do { \ + type *newptr; \ + if ((newptr = (type *) realloc(ptr, sizeof(type) * (size))) == NULL) { \ + warn("%s: can't realloc %lu bytes", where, \ + (unsigned long)(size * sizeof(type))); \ + action; \ + } \ + ptr = newptr; \ +} while( /* CONSTCOND */ 0) + +#define NEW(type, ptr, where, action) NEWARRAY(type, ptr, 1, where, action) + +#define FREE(ptr) (void) free(ptr) + +#define ALLOC(type, v, size, c, init, where, action) do { \ + if (size == 0) { \ + size = init; \ + NEWARRAY(type, v, size, where ": new", action); \ + } else if (c == size) { \ + size *= 2; \ + RENEW(type, v, size, where ": renew", action); \ + } \ +} while( /* CONSTCOND */ 0) + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef ABS +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#endif + +#define STRNCPY(to, from, size) do { \ + (void) strncpy(to, from, size); \ + to[(size) - 1] = 0; \ +} while( /* CONSTCOND */ 0) + +#endif /* !DEFS_H_ */ diff --git a/pkgtools/pkg_install/files/lib/digest.c b/pkgtools/pkg_install/files/lib/digest.c new file mode 100644 index 00000000000..53a623796fc --- /dev/null +++ b/pkgtools/pkg_install/files/lib/digest.c @@ -0,0 +1,90 @@ +/* $NetBSD: digest.c,v 1.1.1.1 2002/12/20 18:13:59 schmonz Exp $ */ + +/* + * Copyright (c) 2002 Alistair G. Crooks. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Alistair G. Crooks. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if 0 +#include <sys/cdefs.h> + +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 2002 \ + The NetBSD Foundation, Inc. All rights reserved."); +__RCSID("$NetBSD: digest.c,v 1.1.1.1 2002/12/20 18:13:59 schmonz Exp $"); +#endif +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include <unistd.h> + +#include "lib.h" + +#ifndef HAVE_MD5FILE + +#define _MD5_ASCII_BUF_SIZE 33 + +char * +MD5File(char *filename, char *buf) +{ + char cmd[1024]; + char in[1024]; + FILE *pp; + char *cp; + + (void) snprintf(cmd, sizeof(cmd), "%s md5 %s", DIGEST, filename); + if ((pp = popen(cmd, "r")) == NULL) { + warn("MD5File: can't popen `%s'", cmd); + return NULL; + } + if (fgets(in, sizeof(in), pp) == NULL) { + warn("MD5File: can't read from `%s'", cmd); + (void) pclose(pp); + return NULL; + } + (void) pclose(pp); + cp = strrchr(in, ' '); + (void) strcpy(buf, cp + 1); + buf[_MD5_ASCII_BUF_SIZE - 1] = 0; + return buf; +} +#endif diff --git a/pkgtools/pkg_install/files/lib/err.c b/pkgtools/pkg_install/files/lib/err.c new file mode 100644 index 00000000000..fc3a007097a --- /dev/null +++ b/pkgtools/pkg_install/files/lib/err.c @@ -0,0 +1,108 @@ +/* $Id: err.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ + +/* + * Copyright 1997-2000 Luke Mewburn <lukem@netbsd.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_ERR +void +err(int eval, const char *fmt, ...) +{ + va_list ap; + int sverrno; + + sverrno = errno; + (void)fprintf(stderr, "%s: ", getprogname()); + va_start(ap, fmt); + if (fmt != NULL) { + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, ": "); + } + va_end(ap); + (void)fprintf(stderr, "%s\n", strerror(sverrno)); + exit(eval); +} +#endif + +#ifndef HAVE_ERRX +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + + (void)fprintf(stderr, "%s: ", getprogname()); + va_start(ap, fmt); + if (fmt != NULL) + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(eval); +} +#endif + +#ifndef HAVE_WARN +void +warn(const char *fmt, ...) +{ + va_list ap; + int sverrno; + + sverrno = errno; + (void)fprintf(stderr, "%s: ", getprogname()); + va_start(ap, fmt); + if (fmt != NULL) { + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, ": "); + } + va_end(ap); + (void)fprintf(stderr, "%s\n", strerror(sverrno)); +} +#endif + +#ifndef HAVE_WARNX +void +warnx(const char *fmt, ...) +{ + va_list ap; + + (void)fprintf(stderr, "%s: ", getprogname()); + va_start(ap, fmt); + if (fmt != NULL) + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); +} +#endif diff --git a/pkgtools/pkg_install/files/lib/exec.c b/pkgtools/pkg_install/files/lib/exec.c new file mode 100644 index 00000000000..a7a3af172f8 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/exec.c @@ -0,0 +1,75 @@ +/* $NetBSD: exec.c,v 1.1.1.1 2002/12/20 18:13:59 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: exec.c,v 1.6 1997/10/08 07:47:50 charnier Exp"; +#else +__RCSID("$NetBSD: exec.c,v 1.1.1.1 2002/12/20 18:13:59 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous system routines. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" + +/* + * Unusual system() substitute. Accepts format string and args, + * builds and executes command. Returns exit code. + */ +int +vsystem(const char *fmt,...) +{ + va_list args; + char *cmd; + size_t maxargs; + int ret; + + maxargs = (size_t) sysconf(_SC_ARG_MAX); + maxargs -= 32; /* some slop for the sh -c */ + if ((cmd = (char *) malloc(maxargs)) == (char *) NULL) { + warnx("vsystem can't alloc arg space"); + return 1; + } + + va_start(args, fmt); + if (vsnprintf(cmd, maxargs, fmt, args) >= maxargs) { + warnx("vsystem args are too long"); + va_end(args); + return 1; + } +#ifdef VSYSTEM_DEBUG + printf("vsystem(\"%s\")\n", cmd); +#endif + ret = system(cmd); + va_end(args); + free(cmd); + return ret; +} diff --git a/pkgtools/pkg_install/files/lib/fgetln.c b/pkgtools/pkg_install/files/lib/fgetln.c new file mode 100644 index 00000000000..fb8f6cbffc5 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/fgetln.c @@ -0,0 +1,88 @@ +/* $Id: fgetln.c,v 1.1.1.1 2002/12/20 18:13:59 schmonz Exp $ */ + +/* + * Copyright 1999 Luke Mewburn <lukem@netbsd.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_FGETLN + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include <unistd.h> + +#define BUFCHUNKS BUFSIZ + +char * +fgetln(FILE *fp, size_t *len) +{ + static char *buf; + static size_t bufsize; + size_t buflen; + char curbuf[BUFCHUNKS]; + char *p; + + if (buf == NULL) { + bufsize = BUFCHUNKS; + buf = (char *)malloc(bufsize); + if (buf == NULL) + err(1, "Unable to allocate buffer for fgetln()"); + } + + *buf = '\0'; + buflen = 0; + while ((p = fgets(curbuf, sizeof(curbuf), fp)) != NULL) { + size_t l; + + l = strlen(p); + if (bufsize < buflen + l) { + bufsize += BUFCHUNKS; + if ((buf = (char *)realloc(buf, bufsize)) == NULL) + err(1, "Unable to allocate %ld bytes of memory", + (long)bufsize); + } + strcpy(buf + buflen, p); + buflen += l; + if (p[l - 1] == '\n') + break; + } + if (p == NULL && *buf == '\0') + return (NULL); + *len = strlen(buf); + return (buf); +} +#endif diff --git a/pkgtools/pkg_install/files/lib/file.c b/pkgtools/pkg_install/files/lib/file.c new file mode 100644 index 00000000000..96a71b4b376 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/file.c @@ -0,0 +1,634 @@ +/* $NetBSD: file.c,v 1.1.1.1 2002/12/20 18:14:00 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: file.c,v 1.29 1997/10/08 07:47:54 charnier Exp"; +#else +__RCSID("$NetBSD: file.c,v 1.1.1.1 2002/12/20 18:14:00 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous file access utilities. + * + */ + +#include "lib.h" + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_ASSERT_H +#include <assert.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifdef HAVE_TIME_H +#include <time.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + + +/* + * Quick check to see if a file (or dir ...) exists + */ +Boolean +fexists(const char *fname) +{ + struct stat dummy; + if (!lstat(fname, &dummy)) + return TRUE; + return FALSE; +} + +/* + * Quick check to see if something is a directory + */ +Boolean +isdir(const char *fname) +{ + struct stat sb; + + 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(const 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(const char *fname) +{ + if (isdir(fname) || islinktodir(fname)) { + DIR *dirp; + struct dirent *dp; + + dirp = opendir(fname); + if (!dirp) + return FALSE; /* no perms, leave it alone */ + for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { + closedir(dirp); + return FALSE; + } + } + (void) closedir(dirp); + return TRUE; + } + return FALSE; +} + +/* + * Check if something is a regular file + */ +Boolean +isfile(const char *fname) +{ + struct stat sb; + if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) + return TRUE; + return FALSE; +} + +/* + * Check to see if file is a file and is empty. If nonexistent or not + * a file, say "it's empty", otherwise return TRUE if zero sized. + */ +Boolean +isemptyfile(const char *fname) +{ + struct stat sb; + if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) { + if (sb.st_size != 0) + return FALSE; + } + return TRUE; +} + +/* This struct defines the leading part of a valid URL name */ +typedef struct url_t { + char *u_s; /* the leading part of the URL */ + int u_len; /* its length */ +} url_t; + +/* A table of valid leading strings for URLs */ +static const url_t urls[] = { + {"ftp://", 6}, + {"http://", 7}, + {NULL} +}; + +/* + * Returns length of leading part of any URL from urls table, or -1 + */ +int +URLlength(const char *fname) +{ + const url_t *up; + int i; + + if (fname != (char *) NULL) { + for (i = 0; isspace((unsigned char) *fname); i++) { + fname++; + } + for (up = urls; up->u_s; up++) { + if (strncmp(fname, up->u_s, up->u_len) == 0) { + return i + up->u_len; /* ... + sizeof(up->u_s); - HF */ + } + } + } + return -1; +} + +/* + * Returns the host part of a URL + */ +const char * +fileURLHost(const char *fname, char *where, int max) +{ + const char *ret; + int i; + + assert(where != NULL); + assert(max > 0); + + if ((i = URLlength(fname)) < 0) { /* invalid URL? */ + errx(1, "fileURLhost called with a bad URL: `%s'", fname); + } + fname += i; + /* Do we have a place to stick our work? */ + ret = where; + while (*fname && *fname != '/' && --max) + *where++ = *fname++; + *where = '\0'; + + return ret; +} + +/* + * Returns the filename part of a URL + */ +const char * +fileURLFilename(const char *fname, char *where, int max) +{ + const char *ret; + int i; + + assert(where != NULL); + assert(max > 0); + + if ((i = URLlength(fname)) < 0) { /* invalid URL? */ + errx(1, "fileURLFilename called with a bad URL: `%s'", fname); + } + fname += i; + /* Do we have a place to stick our work? */ + ret = where; + while (*fname && *fname != '/') + ++fname; + if (*fname == '/') { + while (*fname && --max) + *where++ = *fname++; + } + *where = '\0'; + + return ret; +} + +/* + * Try and fetch a file by URL, returning the directory name for where + * it's unpacked, if successful. To be handed to leave_playpen() later. + */ +char * +fileGetURL(const char *spec) +{ + char host[MAXHOSTNAMELEN], file[FILENAME_MAX]; + const char *cp; + char *rp; + char pen[FILENAME_MAX]; + int rc; + + rp = NULL; + if (!IS_URL(spec)) { + errx(1, "fileGetURL was called with non-url arg '%s'", spec); + } + + /* Some sanity checks on the URL */ + cp = fileURLHost(spec, host, MAXHOSTNAMELEN); + if (!*cp) { + warnx("URL `%s' has bad host part!", spec); + return NULL; + } + cp = fileURLFilename(spec, file, FILENAME_MAX); + if (!*cp) { + warnx("URL `%s' has bad filename part!", spec); + return NULL; + } + + if (Verbose) + printf("Trying to fetch %s.\n", spec); + + pen[0] = '\0'; + rp = make_playpen(pen, sizeof(pen), 0); + if (rp == NULL) { + printf("Error: Unable to construct a new playpen for FTP!\n"); + return NULL; + } + + rp = strdup(pen); + rc = unpackURL(spec, pen); + if (rc < 0) { + leave_playpen(rp); /* Don't leave dir hang around! */ + + printf("Error on unpackURL('%s', '%s')\n", spec, pen); + return NULL; + } + return rp; +} + +static char * +resolvepattern1(const char *name) +{ + static char tmp[FILENAME_MAX]; + char *cp; + + if (IS_URL(name)) { + /* some package depends on a wildcard pkg */ + int rc; + + rc = expandURL(tmp, name); + if (rc < 0) { + return NULL; + } + if (Verbose) + printf("'%s' expanded to '%s'\n", name, tmp); + return tmp; /* return expanded URL w/ corrent pkg */ + } + else if (ispkgpattern(name)) { + cp = findbestmatchingname( + dirname_of(name), basename_of(name)); + if (cp) { + snprintf(tmp, sizeof(tmp), "%s/%s", dirname_of(name), cp); + free(cp); + return tmp; + } + } else { + if (isfile(name)) { + strlcpy(tmp, name, sizeof(tmp)); + return tmp; + } + } + + return NULL; +} + +static char * +resolvepattern(const char *name) +{ + char tmp[FILENAME_MAX]; + char *cp; + const char *suf; + + cp = resolvepattern1(name); + if (cp != NULL) + return cp; + + if (ispkgpattern(name)) + return NULL; + + suf = suffix_of(name); + if (!strcmp(suf, "tbz") || !strcmp(suf, "tgz")) + return NULL; + + /* add suffix and try */ + snprintf(tmp, sizeof(tmp), "%s.tbz", name); + cp = resolvepattern1(tmp); + if (cp != NULL) + return cp; + snprintf(tmp, sizeof(tmp), "%s.tgz", name); + cp = resolvepattern1(tmp); + if (cp != NULL) + return cp; + + /* add version number wildcard and try */ + snprintf(tmp, sizeof(tmp), "%s-[0-9]*.t[bg]z", name); + return resolvepattern1(tmp); +} + +/* + * Look for filename/pattern "fname" in + * Returns a full path/URL where the pkg can be found + */ +char * +fileFindByPath(const char *fname) +{ + char tmp[FILENAME_MAX]; + struct path *path; + + /* + * 1. if fname is an absolute pathname or a url, + * just use it. + */ + if (IS_FULLPATH(fname) || IS_URL(fname)) + return resolvepattern(fname); + + /* + * 2. otherwise, use PKG_PATH. + */ + TAILQ_FOREACH(path, &PkgPath, pl_entry) { + char *cp; + const char *cp2 = path->pl_path; + + if (Verbose) + printf("trying PKG_PATH %s\n", cp2); + + if (IS_FULLPATH(cp2) || IS_URL(cp2)) { + snprintf(tmp, sizeof(tmp), "%s/%s", cp2, fname); + } + else { + char cwdtmp[MAXPATHLEN]; + if (getcwd(cwdtmp, sizeof(cwdtmp)) == NULL) + errx(1, "getcwd"); + snprintf(tmp, sizeof(tmp), "%s/%s/%s", cwdtmp, cp2, fname); + } + cp = resolvepattern(tmp); + if (cp) + return cp; + } + +#if 0 + /* + * 3. finally, search current directory. + */ + snprintf(tmp, sizeof(tmp), "./%s", fname); + return resolvepattern(tmp); +#else + return NULL; +#endif +} + +/* + * Expect "fname" to point at a file, and read it into + * the buffer returned. + */ +char * +fileGetContents(char *fname) +{ + char *contents; + struct stat sb; + int fd; + + if (stat(fname, &sb) == FAIL) { + cleanup(0); + errx(2, "can't stat '%s'", fname); + } + + contents = (char *) malloc((size_t) (sb.st_size) + 1); + fd = open(fname, O_RDONLY, 0); + if (fd == FAIL) { + cleanup(0); + errx(2, "unable to open '%s' for reading", fname); + } + if (read(fd, contents, (size_t) sb.st_size) != (size_t) sb.st_size) { + cleanup(0); + errx(2, "short read on '%s' - did not get %lld bytes", + fname, (long long) sb.st_size); + } + close(fd); + contents[(size_t) 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, size_t 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) +{ + size_t len; + FILE *fp; + + if ((fp = fopen(name, "w")) == (FILE *) NULL) { + cleanup(0); + errx(2, "cannot fopen '%s' for writing", name); + } + len = strlen(str); + if (fwrite(str, 1, len, fp) != len) { + cleanup(0); + errx(2, "short fwrite on '%s', tried to write %ld bytes", + name, (long) len); + } + if (fclose(fp)) { + cleanup(0); + errx(2, "failure to fclose '%s'", name); + } +} + +void +copy_file(char *dir, char *fname, char *to) +{ + char cmd[FILENAME_MAX]; + + if (fname[0] == '/') + (void) snprintf(cmd, sizeof(cmd), "cp -r %s %s", fname, to); + else + (void) snprintf(cmd, sizeof(cmd), "cp -r %s/%s %s", dir, fname, to); + if (vsystem("%s", cmd)) { + cleanup(0); + errx(2, "could not perform '%s'", cmd); + } +} + +void +move_file(char *dir, char *fname, char *to) +{ + char cmd[FILENAME_MAX]; + + if (fname[0] == '/') + (void) snprintf(cmd, sizeof(cmd), "mv %s %s", fname, to); + else + (void) snprintf(cmd, sizeof(cmd), "mv %s/%s %s", dir, fname, to); + if (vsystem("%s", cmd)) { + cleanup(0); + errx(2, "could not perform '%s'", cmd); + } +} + +/* + * Unpack a tar file + */ +int +unpack(const char *pkg, const char *flist) +{ + char args[10] = "-"; + char *cp; + + /* + * Figure out by a crude heuristic whether this or not this is probably + * compressed. + */ + if (!IS_STDIN(pkg)) { + cp = strrchr(pkg, '.'); + if (cp) { + cp++; + if (strchr(cp, 'z') || strchr(cp, 'Z')) + strcat(args, "z"); + } + } else + strcat(args, "z"); + strcat(args, "xpf"); + if (vsystem("%s %s %s %s", TAR_FULLPATHNAME, args, pkg, flist ? flist : "")) { + warnx("%s extract of %s failed!", TAR_FULLPATHNAME, pkg); + return 1; + } + return 0; +} + +/* + * Using fmt, replace all instances of: + * + * %F With the parameter "name" + * %D With the parameter "dir" + * %B Return the directory part ("base") of %D/%F + * %f Return the filename part of %D/%F + * + * Check that no overflows can occur. + */ +void +format_cmd(char *buf, size_t size, char *fmt, char *dir, char *name) +{ + char scratch[FILENAME_MAX * 2]; + char *bufp; + char *cp; + + for (bufp = buf; (int) (bufp - buf) < size && *fmt;) { + if (*fmt == '%') { + switch (*++fmt) { + case 'F': + strnncpy(bufp, size - (int) (bufp - buf), name, strlen(name)); + bufp += strlen(bufp); + break; + + case 'D': + strnncpy(bufp, size - (int) (bufp - buf), dir, strlen(dir)); + bufp += strlen(bufp); + break; + + case 'B': + (void) snprintf(scratch, sizeof(scratch), "%s/%s", dir, name); + if ((cp = strrchr(scratch, '/')) == (char *) NULL) { + cp = scratch; + } + strnncpy(bufp, size - (int) (bufp - buf), scratch, (size_t) (cp - scratch)); + bufp += strlen(bufp); + break; + + case 'f': + (void) snprintf(scratch, sizeof(scratch), "%s/%s", dir, name); + if ((cp = strrchr(scratch, '/')) == (char *) NULL) { + cp = scratch; + } else { + cp++; + } + strnncpy(bufp, size - (int) (bufp - buf), cp, strlen(cp)); + bufp += strlen(bufp); + break; + + default: + *bufp++ = '%'; + *bufp++ = *fmt; + break; + } + ++fmt; + } else { + *bufp++ = *fmt++; + } + } + *bufp = '\0'; +} diff --git a/pkgtools/pkg_install/files/lib/ftpio.c b/pkgtools/pkg_install/files/lib/ftpio.c new file mode 100644 index 00000000000..02e6339ee9f --- /dev/null +++ b/pkgtools/pkg_install/files/lib/ftpio.c @@ -0,0 +1,943 @@ +/* $NetBSD: ftpio.c,v 1.1.1.1 2002/12/20 18:14:01 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: ftpio.c,v 1.1.1.1 2002/12/20 18:14:01 schmonz Exp $"); +#endif +#endif + +/* + * Copyright (c) 1999 Hubert Feyrer. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Hubert Feyrer for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif + +#ifdef HAVE_ASSERT_H +#include <assert.h> +#endif + +#include <ctype.h> + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <errno.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_REGEX_H +#include <regex.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef EXPECT_DEBUG +#ifdef HAVE_VIS_H +#include <vis.h> +#endif +#endif + +#include "../lib/lib.h" + +/* + * Names of environment variables used to pass things to + * subprocesses, for connection caching. + */ +#define PKG_FTPIO_COMMAND "PKG_FTPIO_COMMAND" +#define PKG_FTPIO_ANSWER "PKG_FTPIO_ANSWER" +#define PKG_FTPIO_CNT "PKG_FTPIO_CNT" +#define PKG_FTPIO_CURRENTHOST "PKG_FTPIO_CURRENTHOST" +#define PKG_FTPIO_CURRENTDIR "PKG_FTPIO_CURRENTDIR" + +#undef STANDALONE /* define for standalone debugging */ + +/* File descriptors */ +typedef struct { + int command; + int answer; +} fds; + + +#if EXPECT_DEBUG +static int expect_debug = 1; +#endif /* EXPECT_DEBUG */ +#ifdef STANDALONE +int Verbose=1; +#endif +static int needclose=0; +static int ftp_started=0; +static fds ftpio; +static int ftp_pid; +static char term[1024]; +static char bold_on[1024]; +static char bold_off[1024]; + +/* + * expect "str" (a regular expression) on file descriptor "fd", storing + * the FTP return code of the command in the integer "ftprc". The "str" + * string is expected to match some FTP return codes after a '\n', e.g. + * "\n(550|226).*\n" + */ +static int +expect(int fd, const char *str, int *ftprc) +{ + int rc; + char buf[90]; +#if EXPECT_DEBUG + char *vstr; +#endif /* EXPECT_DEBUG */ + regex_t rstr; + int done; + struct timeval timeout; + int retval; + regmatch_t match; + int verbose_expect=0; + +#if EXPECT_DEBUG + vstr=malloc(2*sizeof(buf)); + if (vstr == NULL) + err(1, "expect: malloc() failed"); + strvis(vstr, str, VIS_NL|VIS_SAFE|VIS_CSTYLE); +#endif /* EXPECT_DEBUG */ + + if (regcomp(&rstr, str, REG_EXTENDED) != 0) + err(1, "expect: regcomp() failed"); + +#if EXPECT_DEBUG + if (expect_debug) + printf("expecting \"%s\" on fd %d ...\n", vstr, fd); +#endif /* EXPECT_DEBUG */ + + if(0) setbuf(stdout, NULL); + + memset(buf, '\n', sizeof(buf)); + + timeout.tv_sec=10*60; /* seconds until next message from tar */ + timeout.tv_usec=0; + done=0; + retval=0; + while(!done) { + fd_set fdset; + + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + rc = select(FD_SETSIZE, &fdset, NULL, NULL, &timeout); + switch (rc) { + case -1: + if (errno == EINTR) + break; + warn("expect: select() failed (probably ftp died because of bad args)"); + done = 1; + retval = -1; + break; + case 0: + warnx("expect: select() timeout"); + /* need to send ftp coprocess SIGINT to make it stop + * downloading into dir that we'll blow away in a second */ + kill(ftp_pid, SIGINT); + + /* Wait until ftp coprocess is responsive again + * XXX Entering recursion here! + */ + rc = ftp_cmd("cd .\n", "\n(550|250).*\n"); + if (rc != 250) { + /* now we have a really good reason to bail out ;) */ + } + /* ftp is at command prompt again, and will wait for our + * next command. If we were downloading, we can now safely + * continue and remove the dir that the tar command was + * expanding to */ + + done = 1; /* hope that's ok */ + retval = -1; + break; + default: + rc=read(fd,&buf[sizeof(buf)-1],1); + + if (verbose_expect) + putchar(buf[sizeof(buf)-1]); + +#if EXPECT_DEBUG + { + char *v=malloc(2*sizeof(buf)); + strvis(v, buf, VIS_NL|VIS_SAFE|VIS_CSTYLE); + if (expect_debug) + printf("expect=<%s>, buf=<%*s>\n", vstr, strlen(v), v); + free(v); + } +#endif /* EXPECT_DEBUG */ + + if (regexec(&rstr, buf, 1, &match, 0) == 0) { +#if EXPECT_DEBUG + if (expect_debug) + printf("Gotcha -> %s!\n", buf+match.rm_so+1); + fflush(stdout); +#endif /* EXPECT_DEBUG */ + + if (ftprc && isdigit(buf[match.rm_so+1])) + *ftprc = atoi(buf+match.rm_so+1); + + done=1; + retval=0; + } + + memmove(buf, buf+1, sizeof(buf)-1); /* yes, this is non-performant */ + break; + } + } + +#if EXPECT_DEBUG + printf("done.\n"); + + if (str) + free(vstr); +#endif /* EXPECT_DEBUG */ + + return retval; +} + +/* + * send a certain ftp-command "cmd" to our FTP coprocess, and wait for + * "expectstr" to be returned. Return numeric FTP return code or -1 + * in case of an error (usually expect() timeout) + */ +int +ftp_cmd(const char *cmd, const char *expectstr) +{ + int rc=0, verbose_ftp=0; + int len; + + if (Verbose) + verbose_ftp=1; + + if (verbose_ftp) + fprintf(stderr, "\n%sftp> %s%s", bold_on, cmd, bold_off); + + fflush(stdout); + len = write(ftpio.command, cmd, strlen(cmd)); + if (len == strlen(cmd)) { + if (expectstr) { + /* set "rc" to the FTP error code: */ + if (expect(ftpio.answer, expectstr, &rc) == -1) + rc = -1; /* some error occurred */ + } + } else { + if (Verbose) + warn("short write"); + } + + return rc; +} + + +/* + * Really fire up FTP coprocess + */ +static int +setupCoproc(const char *base) +{ + int command_pipe[2]; + int answer_pipe[2]; + int rc1, rc2; + char buf[20]; + char *argv0 = strrchr(FTP_CMD, '/'); + if (argv0 == NULL) + argv0 = FTP_CMD; + else + argv0++; + + rc1 = pipe(command_pipe); + rc2 = pipe(answer_pipe); + + if(rc1==-1 || rc2==-1) { + warn("setupCoproc: pipe() failed"); + return -1; + } + + if (command_pipe[0] == -1 || command_pipe[1] == -1 || + answer_pipe[0] == -1 || answer_pipe[1] == -1 ) { + warn("setupCoproc: pipe() returned bogus descriptor"); + return -1; + } + + rc1 = fork(); + switch (rc1) { + case -1: + /* Error */ + + warn("setupCoproc: fork() failed"); + return -1; + break; + + case 0: + /* Child */ + + (void) close(command_pipe[1]); + rc1 = dup2(command_pipe[0], 0); + if (rc1 == -1) { + err(1, "setupCoproc: dup2 failed (command_pipe[0])"); + } + (void) close(command_pipe[0]); + + (void) close(answer_pipe[0]); + rc1 = dup2(answer_pipe[1], 1); + if (rc1 == -1) { + err(1, "setupCoproc: dup2 failed (answer_pipe[1])"); + } + (void) close(answer_pipe[1]); + + setbuf(stdout, NULL); + + if (Verbose) + fprintf(stderr, "%sftp -detv %s%s\n", bold_on, base, bold_off); + rc1 = execlp(FTP_CMD, argv0, "-detv", base, NULL); + warn("setupCoproc: execlp() failed"); + exit(1); + break; + default: + /* Parent */ + (void) close(command_pipe[0]); + (void) close(answer_pipe[1]); + + (void) snprintf(buf, sizeof(buf), "%d", command_pipe[1]); + setenv(PKG_FTPIO_COMMAND, buf, 1); + (void) snprintf(buf, sizeof(buf), "%d", answer_pipe[0]); + setenv(PKG_FTPIO_ANSWER, buf, 1); + + ftpio.command = command_pipe[1]; + ftpio.answer = answer_pipe[0]; + ftp_pid = rc1; /* to ^C transfers */ + + fcntl(ftpio.command, F_SETFL, O_NONBLOCK); + fcntl(ftpio.answer , F_SETFL, O_NONBLOCK); + + break; + } + + return 0; +} + + +/* + * Dummy signal handler to detect if the ftp(1) coprocess or + * and of the processes of the tar/gzip pipeline dies. + */ +static void +sigchld_handler (int n) +{ + /* Make select(2) return EINTR */ +} + + +/* + * SIGPIPE only happens when there's something wrong with the FTP + * coprocess. In that case, set mark to not try to close shut down + * the coprocess. + */ +static void +sigpipe_handler(int n) +{ + /* aparently our ftp companion died */ + if (Verbose) + fprintf(stderr, "SIGPIPE!\n"); + needclose = 0; +} + + +/* + * Close the FTP coprocess' current connection, but + * keep the process itself alive. + */ +void +ftp_stop(void) +{ +#if defined(__svr4__) && defined(__sun__) + char env[BUFSIZ]; +#endif + const char *tmp1, *tmp2; + + if (!ftp_started) + return; + + tmp1=getenv(PKG_FTPIO_COMMAND); + tmp2=getenv(PKG_FTPIO_ANSWER); + + /* (Only) the last one closes the link */ + if (tmp1 != NULL && tmp2 != NULL) { + if (needclose) + ftp_cmd("close\n", "\n(221 .*|Not connected.)\n"); + + (void) close(ftpio.command); + (void) close(ftpio.answer); + } + +#if defined(__svr4__) && defined(__sun__) + (void) snprintf(env, sizeof(env), "%s=", PKG_FTPIO_COMMAND); + putenv(env); + (void) snprintf(env, sizeof(env), "%s=", PKG_FTPIO_ANSWER); + putenv(env); +#else + unsetenv(PKG_FTPIO_COMMAND); + unsetenv(PKG_FTPIO_ANSWER); +#endif +} + + +/* + * (Start and re-)Connect the FTP coprocess to some host/dir. + * If the requested host/dir is different than the one that the + * coprocess is currently at, close first. + */ +int +ftp_start(char *base) +{ + const char *tmp1, *tmp2; + char *p; + int rc; + char newHost[MAXHOSTNAMELEN]; + const char *newDir; + const char *currentHost=getenv(PKG_FTPIO_CURRENTHOST); + const char *currentDir=getenv(PKG_FTPIO_CURRENTDIR); + int urllen; + + /* talk to termcap for bold on/off escape sequences */ +#if 0 + if (tgetent(term, getenv("TERM")) < 0) { + bold_on[0] = '\0'; + bold_off[0] = '\0'; + } else { + p = bold_on; tgetstr("md", &p); + p = bold_off; tgetstr("me", &p); + } +#else + bold_on[0] = '\0'; + bold_off[0] = '\0'; +#endif + + fileURLHost(base, newHost, sizeof(newHost)); + urllen = URLlength(base); + if (urllen < 0 || !(newDir = strchr(base + URLlength(base), '/'))) + errx(1, "ftp_start: bad URL '%s'", base); + newDir++; + if (currentHost + && currentDir + && ( strcmp(newHost, currentHost) != 0 + || strcmp(newDir, currentDir) != 0)) { /* could handle new dir case better here, w/o reconnect */ + if (Verbose) { + printf("ftp_start: new host or dir, stopping previous connect...\n"); + printf("currentHost='%s', newHost='%s'\n", currentHost, newHost); + printf("currentDir='%s', newDir='%s'\n", currentDir, newDir); + } + + ftp_stop(); + + if (Verbose) + printf("ftp stopped\n"); + } + setenv(PKG_FTPIO_CURRENTHOST, newHost, 1); /* need to update this in the environment */ + setenv(PKG_FTPIO_CURRENTDIR, newDir, 1); /* for subprocesses to have this available */ + + tmp1=getenv(PKG_FTPIO_COMMAND); + tmp2=getenv(PKG_FTPIO_ANSWER); + if(tmp1==NULL || tmp2==NULL || *tmp1=='\0' || *tmp2=='\0') { + /* no FTP coprocess running yet */ + + if (Verbose) + printf("Spawning FTP coprocess\n"); + + rc = setupCoproc(base); + if (rc == -1) { + warnx("setupCoproc() failed"); + return -1; + } + + needclose=1; + signal(SIGPIPE, sigpipe_handler); + signal(SIGCHLD, sigchld_handler); + + if ((expect(ftpio.answer, "\n(221|250|221|550).*\n", &rc) != 0) + || rc != 250) { + warnx("expect1 failed, rc=%d", rc); + return -1; + } + + /* lukemftp now issues a CWD for each part of the path + * and will return a code for each of them. No idea how to + * deal with that other than to issue a 'prompt off' to + * get something that we can wait for and that does NOT + * look like a CWD command's output */ + rc = ftp_cmd("prompt off\n", "\n(Interactive mode off|221).*\n"); + if ((rc == 221) || (rc == -1)) { + /* something is wrong */ + ftp_started=1; /* not really, but for ftp_stop() */ + ftp_stop(); + warnx("prompt failed - wrong dir?"); + return -1; + } + + ftp_started=1; + } else { + /* get FDs of our coprocess */ + + ftpio.command = dup(atoi(tmp1)); + if (ftpio.command == -1 ) { + warnx("command dup() failed, increase 'descriptors' limit"); + return -1; + } + ftpio.answer = dup(atoi(tmp2)); + if (ftpio.answer == -1 ) { + warnx("answer dup() failed, increase 'descriptors' limit"); + return -1; + } + + if (Verbose) + printf("Reusing FDs %s/%s for communication to FTP coprocess\n", tmp1, tmp2); + + fcntl(ftpio.command, F_SETFL, O_NONBLOCK); + fcntl(ftpio.answer , F_SETFL, O_NONBLOCK); + } + + return 0; +} + + +/* + * Expand the given wildcard URL "wildcardurl" if possible, and store the + * expanded value into "expandedurl". return 0 if successful, -1 else. + */ +int +expandURL(char *expandedurl, const char *wildcardurl) +{ + char *pkg; + int rc; + char base[FILENAME_MAX]; + + pkg=strrchr(wildcardurl, '/'); + if (pkg == NULL){ + warnx("expandURL: no '/' in url %s?!", wildcardurl); + return -1; + } + (void) snprintf(base, sizeof(base), "%*.*s/", (int)(pkg-wildcardurl), + (int)(pkg-wildcardurl), wildcardurl); + pkg++; + + rc = ftp_start(base); + if (rc == -1) { + warnx("ftp_start() failed"); + return -1; /* error */ + } + + /* for a given wildcard URL, find the best matching pkg */ + { + char *s, buf[FILENAME_MAX]; + char tmpname[FILENAME_MAX]; + char best[FILENAME_MAX]; + int tfd; + + strcpy(tmpname, "/var/tmp/pkg.XXXXXX"); + tfd=mkstemp(tmpname); + if (tfd == -1) { + warnx("Cannot generate temp file for ftp(1)'s nlist output"); + return -1; /* error */ + } + close(tfd); /* We don't need the file descriptor, but will use + the file in a second */ + + s=strpbrk(pkg, "<>[]?*{"); /* Could leave out "[]?*" here; + * ftp(1) is not that stupid */ + if (!s) { + /* This should only happen when getting here with (only) a package + * name specified to pkg_add, and PKG_PATH containing some URL. + */ + (void) snprintf(buf, sizeof(buf), "nlist %s %s\n", pkg, tmpname); + } else { + /* replace possible version(wildcard) given with "-*". + * we can't use the pkg wildcards here as dewey compare + * and alternates won't be handled by ftp(1); sort + * out later, using pmatch() */ + (void) snprintf(buf, sizeof(buf), "nlist %*.*s*.t[bg]z %s\n", + (int)(s-pkg), (int)(s-pkg), pkg, tmpname); + } + + rc = ftp_cmd(buf, "\n(550|226).*\n"); /* catch errors */ + if (rc != 226) { + if (Verbose) + warnx("nlist failed!"); + unlink(tmpname); /* remove clutter */ + return -1; + } + + /* Sync - don't remove */ + rc = ftp_cmd("cd .\n", "\n(550|250).*\n"); + if (rc != 250) { + warnx("chdir failed!"); + unlink(tmpname); /* remove clutter */ + return -1; + } + + best[0]='\0'; + if (access(tmpname, R_OK)==0) { + int matches; + FILE *f; + char filename[FILENAME_MAX]; + + f=fopen(tmpname, "r"); + if (f == NULL) { + warn("fopen"); + unlink(tmpname); /* remove clutter */ + return -1; + } + matches=0; + /* The following loop is basically the same as the readdir() loop + * in findmatchingname() */ + while (fgets(filename, sizeof(filename), f)) { + + /* + * We need to stripp of any .t[bg]z etc. + * suffix here + */ + + char s_filename[FILENAME_MAX]; + char s_pkg[FILENAME_MAX]; + + filename[strlen(filename)-1] = '\0'; + + strip_txz(s_filename, NULL, filename); + strip_txz(s_pkg, NULL, pkg); + + if (pmatch(s_pkg, s_filename)) { + matches++; + + /* compare findbestmatchingname() */ + findbestmatchingname_fn(filename, best); + } + } + (void) fclose(f); + + if (matches == 0 && Verbose) + warnx("nothing appropriate found"); + } + + unlink(tmpname); + + if (best[0] != '\0') { + if (Verbose) + printf("best match: '%s%s'\n", base, best); + snprintf(expandedurl, FILENAME_MAX, "%s%s", base, best); + } + else + return -1; + } + + return 0; +} + + +/* + * extract the given (expanded) URL "url" to the given directory "dir" + * return -1 on error, 0 else; + */ +int +unpackURL(const char *url, const char *dir) +{ + char *pkg; + int rc; + char base[FILENAME_MAX]; + char pkg_path[FILENAME_MAX]; + + { + /* Verify if the url is really ok */ + char expnd[FILENAME_MAX]; + + rc=expandURL(expnd, url); + if (rc == -1) { + warnx("unpackURL: verification expandURL failed"); + return -1; + } + if (strcmp(expnd, url) != 0) { + warnx("unpackURL: verification expandURL failed, '%s'!='%s'", + expnd, url); + return -1; + } + } + + pkg=strrchr(url, '/'); + if (pkg == NULL){ + warnx("unpackURL: no '/' in url %s?!", url); + return -1; + } + (void) snprintf(base, sizeof(base), "%*.*s/", (int)(pkg-url), + (int)(pkg-url), url); + (void) snprintf(pkg_path, sizeof(pkg_path), "%*.*s", (int)(pkg-url), + (int)(pkg-url), url); /* no trailing '/' */ + pkg++; + + /* Leave a hint for any depending pkgs that may need it */ + if (getenv("PKG_PATH") == NULL) { + setenv("PKG_PATH", pkg_path, 1); +#if 0 + path_create(pkg_path); /* XXX */ +#endif + printf("setenv PKG_PATH='%s'\n",pkg_path); + } + + rc = ftp_start(base); + if (rc == -1) { + warnx("ftp_start() failed"); + return -1; /* error */ + } + + { + char cmd[1024]; + + if (Verbose) + printf("unpackURL '%s' to '%s'\n", url, dir); + + /* yes, this is gross, but needed for borken ftp(1) */ + (void) snprintf(cmd, sizeof(cmd), "get %s \"| ( cd %s ; gunzip 2>/dev/null | " TAR_FULLPATHNAME " -%sx -f - | tee /dev/stderr )\"\n", pkg, dir, Verbose?"vv":""); + rc = ftp_cmd(cmd, "\n(226|550).*\n"); + if (rc != 226) { + warnx("Cannot fetch file (%d!=226)!", rc); + return -1; + } + } + + return 0; +} + + +#if 0 +/* + * Some misc stuff not needed yet, but maybe later + */ +int +miscstuff(const char *url) +{ + char *pkg; + int rc; + char base[FILENAME_MAX]; + + pkg=strrchr(url, '/'); + if (pkg == NULL){ + warnx("miscstuff: no '/' in url %s?!", url); + return -1; + } + (void) snprintf(base, sizeof(base), "%*.*s/", (int)(pkg-url), (int)(pkg-url), + url); + pkg++; + + rc = ftp_start(base); + if (rc == -1) { + warnx("ftp_start() failed"); + return -1; /* error */ + } + + /* basic operation */ + if (0) { + rc = ftp_cmd("cd ../All\n", "\n(550|250).*\n"); + if (rc != 250) { + warnx("chdir failed!"); + return -1; + } + } + + /* get and extract a file to tmpdir */ + if (0) { + char cmd[256]; + char tmpdir[256]; + + (void) snprintf(tmpdir, sizeof(tmpdir), "/var/tmp/dir%s", + (getenv(PKG_FTPIO_CNT))?getenv(PKG_FTPIO_CNT):""); + + mkdir(tmpdir, 0755); + + /* yes, this is gross, but needed for borken ftp(1) */ + (void) snprintf(cmd, sizeof(cmd), "get xpmroot-1.01.tgz \"| ( cd %s ; gunzip 2>/dev/null | tar -vvx -f - )\"\n", tmpdir); + rc = ftp_cmd(cmd, "\n(226|550).*\n"); + if (rc != 226) { + warnx("Cannot fetch file (%d != 226)!", rc); + return -1; + } + } + + /* check if one more file(s) exist */ + if (0) { + char buf[FILENAME_MAX]; + (void) snprintf(buf, sizeof(buf), "nlist %s /var/tmp/xxx\n", pkg); + rc = ftp_cmd(buf, "\n(226|550).*\n"); /* catch errors */ + if (rc != 226) { + if (Verbose) + warnx("nlist failed!"); + return -1; + } + + /* Sync - don't remove */ + rc = ftp_cmd("cd .\n", "\n(550|250).*\n"); + if (rc != 250) { + warnx("chdir failed!"); + return -1; + } + + if (access("/var/tmp/xxx", R_OK)==0) { + system("cat /var/tmp/xxx"); + + { + /* count lines - >0 -> fexists() == true */ + int len, count; + FILE *f; + + f=fopen("/var/tmp/xxx", "r"); + if (f == NULL) { + warn("fopen"); + return -1; + } + count=0; + while (fgetln(f, &len)) + count++; + (void) fclose(f); + + printf("#lines = %d\n", count); + } + } else + printf("NO MATCH\n"); + + unlink("/var/tmp/xxx"); + } + + /* for a given wildcard URL, find the best matching pkg */ + /* spawn child - like pkg_add'ing another package */ + /* Here's where the connection caching kicks in */ +#if 0 + if (0) { + char *s, buf[FILENAME_MAX]; + + if ((s=getenv(PKG_FTPIO_CNT)) && atoi(s)>0){ + (void) snprintf(buf, sizeof(buf),"%d", atoi(s)-1); + setenv(PKG_FTPIO_CNT, buf, 1); + + (void) snprintf(buf, sizeof(buf), "%s \"%s/%s\"", argv0, url, pkg); + printf("%s>>> %s\n", s, buf); + system(buf); + } + } +#endif + + return 0; + +} +#endif + + +#ifdef STANDALONE +static void +usage(void) +{ + errx(1, "Usage: foo [-v] ftp://-pattern"); +} + + +int +main(int argc, char *argv[]) +{ + int rc, ch; + char *argv0 = argv[0]; + + while ((ch = getopt(argc, argv, "v")) != -1) { + switch (ch) { + case 'v': + Verbose=1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc<1) + usage(); + + while(argv[0] != NULL) { + char newurl[FILENAME_MAX]; + + printf("Expand %s:\n", argv[0]); + rc = expandURL(newurl, argv[0]); + if (rc==-1) + warnx("Cannot expand %s", argv[0]); + else + printf("Expanded URL: %s\n", newurl); + + /* test out connection caching */ + if (1) { + char *s, buf[FILENAME_MAX]; + + if ((s=getenv(PKG_FTPIO_CNT)) && atoi(s)>0){ + (void) snprintf(buf, sizeof(buf),"%d", atoi(s)-1); + setenv(PKG_FTPIO_CNT, buf, 1); + + (void) snprintf(buf, sizeof(buf), "%s -v '%s'", argv0, argv[0]); + printf("%s>>> %s\n", s, buf); + system(buf); + } + } + + printf("\n\n\n"); + argv++; + } + + ftp_stop(); + + return 0; +} +#endif /* STANDALONE */ diff --git a/pkgtools/pkg_install/files/lib/global.c b/pkgtools/pkg_install/files/lib/global.c new file mode 100644 index 00000000000..0c8b14806a8 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/global.c @@ -0,0 +1,40 @@ +/* $NetBSD: global.c,v 1.1.1.1 2002/12/20 18:14:01 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: global.c,v 1.6 1997/10/08 07:47:58 charnier Exp"; +#else +__RCSID("$NetBSD: global.c,v 1.1.1.1 2002/12/20 18:14:01 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + + * 18 July 1993 + * + * Semi-convenient place to stick some needed globals. + * + */ + +#include "lib.h" + +/* These are global for all utils */ +Boolean Verbose = FALSE; +Boolean Fake = FALSE; +Boolean Force = FALSE; diff --git a/pkgtools/pkg_install/files/lib/lib.h.in b/pkgtools/pkg_install/files/lib/lib.h.in new file mode 100644 index 00000000000..69b9fd50579 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/lib.h.in @@ -0,0 +1,448 @@ +/* $NetBSD: lib.h.in,v 1.1.1.1 2002/12/20 18:14:02 schmonz Exp $ */ + +/* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the library routines. + * + */ + +#ifndef _INST_LIB_LIB_H_ +#define _INST_LIB_LIB_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> + +#if defined(HAVE_SYS_PARAM_H) +#include <sys/param.h> +#endif + +#if defined(HAVE_SYS_STAT_H) +#include <sys/stat.h> +#endif + +#if defined(HAVE_SYS_FILE_H) +#include <sys/file.h> +#endif + +#if defined(HAVE_SYS_QUEUE_H) +#include <sys/queue.h> +#endif + +#include <ctype.h> + +#if defined(HAVE_DIRENT_H) +#include <dirent.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#if defined(HAVE_STRING_H) +#include <string.h> +#endif + +#include <unistd.h> + +/* Macros */ +#define SUCCESS (0) +#define FAIL (-1) + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TAR_FULLPATHNAME +#define TAR_FULLPATHNAME "@TAR_FULLPATHNAME@" +#endif +/* Define ftp as a string, in case the ftp client is called something else */ +#ifndef FTP_CMD +#define FTP_CMD "ftp" +#endif +#ifndef ADD_CMD +#define ADD_CMD "@prefix@/sbin/pkg_add" +#endif +#ifndef CHMOD_CMD +#define CHMOD_CMD "@CHMOD@" +#endif +#ifndef CHOWN_CMD +#define CHOWN_CMD "@CHOWN@" +#endif +#ifndef CHGRP_CMD +#define CHGRP_CMD "@CHGRP@" +#endif +#ifndef DIGEST +#define DIGEST "@DIGEST@" +#endif +#ifndef MKDIR +#define MKDIR "@MKDIR@" +#endif +#ifndef MTREE +#define MTREE "@MTREE@" +#endif +#ifndef PREFIX +#define PREFIX "@prefix@" +#endif +#ifndef RM +#define RM "@RM@" +#endif +#ifndef RMDIR_CMD +#define RMDIR_CMD "@RMDIR@" +#endif + +#if defined(BSD4_4) +/* the BSD derivatives have added --fast-read to their tar(1) commands */ +#define HAVE_TAR__FAST_READ 1 +#endif + + +/* Where we put logging information by default, else ${PKG_DBDIR} if set */ +#ifndef DEF_LOG_DIR +#define DEF_LOG_DIR "@pkgdbdir@" +#endif +/* just in case we change the environment variable name */ +#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 REQUIRED_BY_FNAME "+REQUIRED_BY" +#define DISPLAY_FNAME "+DISPLAY" +#define MTREE_FNAME "+MTREE_DIRS" +#define BUILD_VERSION_FNAME "+BUILD_VERSION" +#define BUILD_INFO_FNAME "+BUILD_INFO" +#define SIZE_PKG_FNAME "+SIZE_PKG" +#define SIZE_ALL_FNAME "+SIZE_ALL" + +#define CMD_CHAR '@' /* prefix for extended PLIST cmd */ + +/* The name of the "prefix" environment variable given to scripts */ +#define PKG_PREFIX_VNAME "PKG_PREFIX" + +#define PKG_PATTERN_MAX FILENAME_MAX /* max length of pattern, including nul */ +#define PKG_SUFFIX_MAX 10 /* max length of suffix, including nul */ + + +/* This should only happen on 1.3 and 1.3.1, not 1.3.2 and up */ +#ifndef TAILQ_FIRST +#define TAILQ_FIRST(head) ((head)->tqh_first) +#endif + +#ifndef TAILQ_NEXT +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#endif + +/* + * Tail queue definitions. + */ +#ifndef QUEUEDEBUG_TAILQ_INSERT_HEAD +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) +#endif + +#ifndef QUEUEDEBUG_TAILQ_INSERT_TAIL +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) +#endif + +#ifndef QUEUEDEBUG_TAILQ_OP +#define QUEUEDEBUG_TAILQ_OP(elm, field) +#endif + +#ifndef QUEUEDEBUG_TAILQ_POSTREMOVE +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) +#endif + +#ifndef TAILQ_INIT +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) +#endif + +#ifndef TAILQ_HEAD +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} +#endif + +#ifndef TAILQ_HEAD_INITIALIZER +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } +#endif + +#ifndef TAILQ_ENTRY +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif + +#ifndef TAILQ_INSERT_HEAD +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) +#endif + +#ifndef TAILQ_INSERT_TAIL +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) +#endif /* !TAILQ_INSERT_TAIL */ + +#ifndef TAILQ_REMOVE +#define TAILQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((elm), field) \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ +} while (/*CONSTCOND*/0) +#endif + +#ifndef TAILQ_FOREACH +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var); \ + (var) = ((var)->field.tqe_next)) +#endif + +#ifndef TAILQ_FOREACH_REVERSE +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) +#endif + + +/* Enumerated constants for plist entry types */ +typedef enum pl_ent_t { + PLIST_SHOW_ALL = -1, + PLIST_FILE, /* 0 */ + PLIST_CWD, /* 1 */ + PLIST_CMD, /* 2 */ + PLIST_CHMOD, /* 3 */ + PLIST_CHOWN, /* 4 */ + PLIST_CHGRP, /* 5 */ + PLIST_COMMENT, /* 6 */ + PLIST_IGNORE, /* 7 */ + PLIST_NAME, /* 8 */ + PLIST_UNEXEC, /* 9 */ + PLIST_SRC, /* 10 */ + PLIST_DISPLAY, /* 11 */ + PLIST_PKGDEP, /* 12 */ + PLIST_MTREE, /* 13 */ + PLIST_DIR_RM, /* 14 */ + PLIST_IGNORE_INST, /* 15 */ + PLIST_OPTION, /* 16 */ + PLIST_PKGCFL, /* 17 */ + PLIST_BLDDEP /* 18 */ +} pl_ent_t; + +/* Types */ +typedef unsigned int Boolean; + +/* This structure describes a packing list entry */ +typedef struct plist_t { + struct plist_t *prev; /* previous entry */ + struct plist_t *next; /* next entry */ + char *name; /* name of entry */ + Boolean marked; /* whether entry has been marked */ + pl_ent_t type; /* type of entry */ +} plist_t; + +/* This structure describes a package's complete packing list */ +typedef struct package_t { + plist_t *head; /* head of list */ + plist_t *tail; /* tail of list */ +} package_t; + +#define CHECKSUM_HEADER "MD5:" + +enum { + ChecksumHeaderLen = 4, /* strlen(CHECKSUM_HEADER) */ + ChecksumLen = 16, + LegibleChecksumLen = 33 +}; + +/* List of packages */ +typedef struct _lpkg_t { + TAILQ_ENTRY(_lpkg_t) lp_link; + char *lp_name; +} lpkg_t; +TAILQ_HEAD(_lpkg_head_t, _lpkg_t); +typedef struct _lpkg_head_t lpkg_head_t; + +/* Type of function to be handed to findmatchingname; return value of this + * is currently ignored */ +typedef int (*matchfn) (const char *, void *); + +/* If URLlength()>0, then there is a ftp:// or http:// in the string, + * and this must be an URL. Hide this behind a more obvious name. */ +#define IS_URL(str) (URLlength(str) > 0) +#define IS_STDIN(str) ((str) != NULL && !strcmp((str), "-")) +#define IS_FULLPATH(str) ((str) != NULL && (str)[0] == '/') + +/* Prototypes */ +/* Misc */ +int vsystem(const char *,...) + __attribute__((__format__(__printf__, 1, 2))); +void cleanup(int); +char *make_playpen(char *, size_t, size_t); +char *where_playpen(void); +void leave_playpen(char *); +off_t min_free(char *); +void save_dirs(char **c, char **p); +void restore_dirs(char *c, char *p); +void show_version(void); + +#ifndef HAVE_MD5FILE +char *MD5File(char *, char *); +#endif + +#ifndef HAVE_FGETLN +char *fgetln(FILE *, size_t *); +#endif + +/* String */ +char *get_dash_string(char **); +void str_lowercase(char *); +const char *basename_of(const char *); +const char *dirname_of(const char *); +const char *suffix_of(const char *); +int pmatch(const char *, const char *); +int findmatchingname(const char *, const char *, matchfn, void *); /* doesn't really belong to "strings" */ +char *findbestmatchingname(const char *, const char *); /* neither */ +int ispkgpattern(const char *); +char *strnncpy(char *to, size_t tosize, char *from, size_t cc); +void strip_txz(char *buf, char *sfx, const char *fname); + +/* callback functions for findmatchingname */ +int findbestmatchingname_fn(const char *, void *); /* neither */ +int note_whats_installed(const char *, void *); +int add_to_list_fn(const char *, void *); + + +#ifndef HAVE_STRSEP +char *strsep(char **, const char *); +#endif + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *, const char *, size_t); +#endif + +/* File */ +Boolean fexists(const char *); +Boolean isdir(const char *); +Boolean islinktodir(const char *); +Boolean isemptydir(const char *fname); +Boolean isemptyfile(const char *fname); +Boolean isfile(const char *); +Boolean isempty(const char *); +int URLlength(const char *); +char *fileGetURL(const char *); +const char *fileURLFilename(const char *, char *, int); +char *fileFindByPath(const char *); +const char *fileURLHost(const char *, char *, int); +char *fileGetContents(char *); +Boolean make_preserve_name(char *, size_t, char *, char *); +void write_file(char *, char *); +void copy_file(char *, char *, char *); +void move_file(char *, char *, char *); +int delete_hierarchy(char *, Boolean, Boolean); +int unpack(const char *,const char *); +void format_cmd(char *, size_t, char *, char *, char *); + +/* ftpio.c: FTP handling */ +int expandURL(char *expandedurl, const char *wildcardurl); +int unpackURL(const char *url, const char *dir); +int ftp_cmd(const char *cmd, const char *expectstr); +int ftp_start(char *base); +void ftp_stop(void); + +/* Packing list */ +plist_t *new_plist_entry(void); +plist_t *last_plist(package_t *); +plist_t *find_plist(package_t *, pl_ent_t); +char *find_plist_option(package_t *, char *name); +void plist_delete(package_t *, Boolean, pl_ent_t, char *); +void free_plist(package_t *); +void mark_plist(package_t *); +void csum_plist_entry(char *, plist_t *); +void add_plist(package_t *, pl_ent_t, const char *); +void add_plist_top(package_t *, pl_ent_t, const char *); +void delete_plist(package_t *pkg, Boolean all, pl_ent_t type, char *name); +void write_plist(package_t *, FILE *, char *); +void read_plist(package_t *, FILE *); +int plist_cmd(char *, char **); +int delete_package(Boolean, Boolean, package_t *); + +/* Package Database */ +int pkgdb_open(int); +void pkgdb_close(void); +int pkgdb_store(const char *, const char *); +char *pkgdb_retrieve(const char *); +int pkgdb_remove(const char *); +char *pkgdb_iter(void); +char *_pkgdb_getPKGDB_FILE(void); +char *_pkgdb_getPKGDB_DIR(void); + +/* List of packages functions */ +lpkg_t *alloc_lpkg(const char *); +lpkg_t *find_on_queue(lpkg_head_t *, const char *); +void free_lpkg(lpkg_t *); + +/* For all */ +int pkg_perform(lpkg_head_t *); + +/* Externs */ +extern Boolean Verbose; +extern Boolean Fake; +extern Boolean Force; +extern int upgrade; + +/* We include it at the end, because it uses TAILQ_* */ +#include "path.h" +#endif /* _INST_LIB_LIB_H_ */ diff --git a/pkgtools/pkg_install/files/lib/lpkg.c b/pkgtools/pkg_install/files/lib/lpkg.c new file mode 100644 index 00000000000..ff759c24405 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/lpkg.c @@ -0,0 +1,72 @@ +/* $NetBSD: lpkg.c,v 1.1.1.1 2002/12/20 18:14:02 schmonz Exp $ */ + +/* + * Copyright (c) 1999 Christian E. Hopps + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Package-list auxiliary functions + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" + +/* + * Add a package to the (add/recursive delete) list + */ +lpkg_t * +alloc_lpkg(const char *pkgname) +{ + lpkg_t *lpp; + + if ((lpp = malloc(sizeof(*lpp))) == 0) + err(1, "cannot allocate recursion data"); + if ((lpp->lp_name = strdup(pkgname)) == 0) + err(1, "cannot allocate recursion data"); + return (lpp); +} + +void +free_lpkg(lpkg_t *lpp) +{ + free(lpp->lp_name); + free(lpp); +} + +lpkg_t * +find_on_queue(lpkg_head_t *qp, const char *name) +{ + lpkg_t *lpp; + + for (lpp = TAILQ_FIRST(qp); lpp; lpp = TAILQ_NEXT(lpp, lp_link)) + if (!strcmp(name, lpp->lp_name)) + return (lpp); + return (0); +} diff --git a/pkgtools/pkg_install/files/lib/path.c b/pkgtools/pkg_install/files/lib/path.c new file mode 100644 index 00000000000..abb84ae798b --- /dev/null +++ b/pkgtools/pkg_install/files/lib/path.c @@ -0,0 +1,208 @@ +/* $NetBSD: path.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ + +/*- + * Copyright (c)2002 YAMAMOTO Takashi, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: path.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $"); +#endif +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" + +struct pathhead PkgPath = TAILQ_HEAD_INITIALIZER(PkgPath); +static struct path *prepend = 0; + +static struct path *path_new_entry(const char *cp, size_t len); + +/* + * path_create: make PkgPath from a given string. + * + * => relative pathes are resolved to absolute ones. + * => if NULL is passed, use "." instead. XXX + */ +void +path_create(const char *path) +{ + const char *cp; + size_t len; + + path_free(); + + if (path == NULL) { + path = "."; /* XXX */ + } + + if (Verbose) + printf("parsing: %s\n", path); + + cp = path; + while (*cp) { + len = strcspn(cp, ";"); + if (len > 0) { + /* add a new path */ + struct path *new; + + new = path_new_entry(cp, len); + if (Verbose) + printf("path: %s\n", new->pl_path); + TAILQ_INSERT_TAIL(&PkgPath, new, pl_entry); + } + + cp += len; + if (*cp == '\0') + break; + cp++; + } +} + +/* + * path_free: free PkgPath. + */ +void +path_free() +{ + struct path *p; + + while ((p = TAILQ_FIRST(&PkgPath)) != NULL) { + TAILQ_REMOVE(&PkgPath, p, pl_entry); + free(p->pl_path); + free(p); + } +} + +/* + * path_new_entry: Generate a new 'struct path' entry to be included in + * 'PkgPath' using the first 'len' characters of 'cp'. + */ +static struct path * +path_new_entry(const char *cp, size_t len) +{ + struct path *new; + + new = malloc(sizeof(*new)); + if (new == NULL) + err(1, "path_create"); + + if (!IS_FULLPATH(cp) && !IS_URL(cp)) { + /* this is a relative path */ + size_t total; + char cwd[MAXPATHLEN]; + size_t cwdlen; + + if (getcwd(cwd, sizeof(cwd)) == NULL) + err(1, "getcwd"); + cwdlen = strlen(cwd); + total = cwdlen + 1 + len + 1; + new->pl_path = malloc(total); + if (new->pl_path == NULL) + err(1, "path_create"); + snprintf(new->pl_path, total, "%s/%*.*s", cwd, (int)len, (int)len, cp); + } + else { + new->pl_path = malloc(len + 1); + if (new->pl_path == NULL) + err(1, "path_create"); + memcpy(new->pl_path, cp, len); + new->pl_path[len] = '\0'; + } + return new; +} + +/* + * path_prepend_from_pkgname: prepend the path for a package onto 'PkgPath' + */ +void +path_prepend_from_pkgname(const char *pkgname) +{ + char *ptr; + if ((ptr = strrchr(pkgname , '/'))) { + prepend = path_new_entry(pkgname, ptr - pkgname); + TAILQ_INSERT_HEAD(&PkgPath, prepend, pl_entry); + } +} + +/* + * path_prepend_clear: Remove any prepended entry from 'PkgPath' + */ +void +path_prepend_clear() +{ + if (prepend) { + TAILQ_REMOVE(&PkgPath, prepend, pl_entry); + prepend = 0; + } +} + +/* + * path_setenv: construct string from PkgPath and set it to a environment. + * + * => the environment name is given by envname. + */ +void +path_setenv(const char *envname) +{ + struct path *p; + ssize_t len = 0; + char *env, *env0, *envend; + char *sep; + + TAILQ_FOREACH(p, &PkgPath, pl_entry) + len += strlen(p->pl_path) + 1; + + env = malloc(len); + if (env == NULL) + err(1, "path_setenv"); + + env0 = env; + envend = env + len; + sep = ""; + TAILQ_FOREACH(p, &PkgPath, pl_entry) { + int r; + + r = snprintf(env, envend - env, "%s%s", sep, p->pl_path); + if (r < 0 || r >= envend - env) + err(1, "snprintf"); + env += r; + sep = ";"; + } + + if (Verbose) + printf("%s = %s\n", envname, env0); + if (setenv(envname, env0, 1) != 0) + err(1, "setenv"); + free(env0); +} diff --git a/pkgtools/pkg_install/files/lib/path.h b/pkgtools/pkg_install/files/lib/path.h new file mode 100644 index 00000000000..1b7a301e251 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/path.h @@ -0,0 +1,40 @@ +/* $NetBSD: path.h,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ + +/*- + * Copyright (c)2002 YAMAMOTO Takashi, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct path { + TAILQ_ENTRY(path) pl_entry; + char *pl_path; +}; + +TAILQ_HEAD(pathhead, path); +extern struct pathhead PkgPath; +void path_create(const char *); +void path_free(void); +void path_prepend_from_pkgname(const char *); +void path_prepend_clear(void); +void path_setenv(const char *); diff --git a/pkgtools/pkg_install/files/lib/pen.c b/pkgtools/pkg_install/files/lib/pen.c new file mode 100644 index 00000000000..7373f5a1df6 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/pen.c @@ -0,0 +1,417 @@ +/* $NetBSD: pen.c,v 1.1.1.1 2002/12/20 18:14:03 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: pen.c,v 1.25 1997/10/08 07:48:12 charnier Exp"; +#else +__RCSID("$NetBSD: pen.c,v 1.1.1.1 2002/12/20 18:14:03 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Routines for managing the "play pen". + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include "lib.h" + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif + +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif + +/* For keeping track of where we are */ +static char Current[FILENAME_MAX]; +static char Previous[FILENAME_MAX]; +static int CurrentSet; /* rm -rf Current only if it's really set! */ + /* CurrentSet is set to 0 before strcpy()s + * to prevent rm'ing of a partial string + * when interrupted by ^C */ + +#if 0 +/* + * Backup Current and Previous into temp. strings that are later + * restored & freed by restore_dirs + * This is to make nested calls to make_playpen/leave_playpen work + */ +void +save_dirs(char **c, char **p) +{ + *c = strdup(Current); /* XXX */ + *p = strdup(Previous); +} + +/* + * Restore Current and Previous from temp strings that were created + * by safe_dirs. + * This is to make nested calls to make_playpen/leave_playpen work + */ +void +restore_dirs(char *c, char *p) +{ + CurrentSet = 0; /* prevent from deleting */ + strcpy(Current, c); + CurrentSet = 1; /* rm -fr Current is safe now */ + free(c); + + strcpy(Previous, p); + free(p); +} +#endif + +char * +where_playpen(void) +{ + return Current; +} + +/* + * Find a good place to play. + */ +static char * +find_play_pen(char *pen, size_t pensize, size_t sz) +{ + char *cp; + struct stat sb; + + if (pen && pen[0] && stat(pen, &sb) != FAIL && (min_free(pen) >= sz)) + return pen; + else if ((cp = getenv("PKG_TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz)) + (void) snprintf(pen, pensize, "%s/instmp.XXXXXX", cp); + else if ((cp = getenv("TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz)) + (void) snprintf(pen, pensize, "%s/instmp.XXXXXX", cp); + else if (stat("/var/tmp", &sb) != FAIL && min_free("/var/tmp") >= sz) + strcpy(pen, "/var/tmp/instmp.XXXXXX"); + else if (stat("/tmp", &sb) != FAIL && min_free("/tmp") >= sz) + strcpy(pen, "/tmp/instmp.XXXXXX"); + else if (stat("/usr/tmp", &sb) != FAIL && min_free("/usr/tmp") >= sz) + strcpy(pen, "/usr/tmp/instmp.XXXXXX"); + else { + 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; +} + +#if !defined(HAVE_MKDTEMP) +static char * +mkdtemp(char *template) +{ + /* mkdtemp(3) is not present on 1.3.3 and below */ + if (!mktemp(template)) { + cleanup(0); + errx(2, "can't mktemp '%s'", template); + } + if (mkdir(template, 0700) < 0) { + cleanup(0); + errx(2, "can't mkdir '%s'", template); + } + return template; +} +#endif + +/* + * Make a temporary directory to play in and chdir() to it, returning + * pathname of previous working directory. + */ +char * +make_playpen(char *pen, size_t pensize, size_t sz) +{ + if (!find_play_pen(pen, pensize, sz)) + return NULL; + + if (!mkdtemp(pen)) { + cleanup(0); + errx(2, "can't mkdtemp '%s'", pen); + } + if (Verbose) { + if (sz) + fprintf(stderr, + "Requested space: %lu bytes, free space: %lld bytes in %s\n", + (u_long) sz, (long long) min_free(pen), pen); + } + if (min_free(pen) < sz) { + rmdir(pen); + 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); + } + if (Current[0]) + strcpy(Previous, Current); + else if (!getcwd(Previous, FILENAME_MAX)) { + cleanup(0); + err(1, "fatal error during execution: getcwd"); + } + if (chdir(pen) == FAIL) { + cleanup(0); + errx(2, "can't chdir to '%s'", pen); + } + strcpy(Current, pen); CurrentSet = 1; + + return Previous; +} + +/* + * Convenience routine for getting out of playpen + */ +void +leave_playpen(char *save) +{ + void (*oldsig) (int); + + /* Make us interruptable while we're cleaning up - just in case... */ + oldsig = signal(SIGINT, SIG_DFL); + if (Previous[0] && chdir(Previous) == FAIL) { + cleanup(0); + errx(2, "can't chdir back to '%s'", Previous); + } else if (CurrentSet && Current[0] && strcmp(Current, Previous)) { + if (strcmp(Current, "/") == 0) { + fprintf(stderr, "PANIC: About to rm -rf / (not doing so, aborting)\n"); + abort(); + } + if (vsystem("%s -rf %s", RM, Current)) + warnx("couldn't remove temporary dir '%s'", Current); + strcpy(Current, Previous); + } + if (save) + strcpy(Previous, save); + else + Previous[0] = '\0'; + signal(SIGINT, oldsig); +} + +/* + * Solaris 2.7 and 2.8 have statfs(2), but it is deprecated, and has a + * different interface to NetBSD's statfs. + * We do this autoconf dance here to get around the old interface (it's + * in libc on 2.7 and 2.8, but not in 2.9) + */ +#if !defined(HAVE_STATFS) || (defined(HAVE_STATFS) && defined(HAVE_STATVFS)) +/* $NetBSD: pen.c,v 1.1.1.1 2002/12/20 18:14:03 schmonz Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/types.h> +#include <sys/mount.h> +#include <sys/statvfs.h> + +#define MFSNAMELEN 16 /* length of fs type name, including nul */ +#define MNAMELEN 90 /* length of buffer for returned name */ + +struct statfs { + short f_type; /* type of file system */ + u_short f_flags; /* copy of mount flags */ + long f_bsize; /* fundamental file system block size */ + long f_iosize; /* optimal transfer block size */ + long f_blocks; /* total data blocks in file system */ + long f_bfree; /* free blocks in fs */ + long f_bavail; /* free blocks avail to non-superuser */ + long f_files; /* total file nodes in file system */ + long f_ffree; /* free file nodes in fs */ + fsid_t f_fsid; /* file system id */ + uid_t f_owner; /* user that mounted the file system */ + long f_spare[4]; /* spare for later */ + char f_fstypename[MFSNAMELEN]; /* fs type name */ + char f_mntonname[MNAMELEN]; /* directory on which mounted */ + char f_mntfromname[MNAMELEN]; /* mounted file system */ +}; + +#ifndef MNT_RDONLY +#define MNT_RDONLY 0x00000001 /* read only filesystem */ +#endif + +#ifndef MNT_NOSUID +#define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */ +#endif + +static void vfs2fs(struct statfs *, const struct statvfs *); + +static void +vfs2fs(struct statfs *sfs, const struct statvfs *vfs) +{ + sfs->f_type = 0; /* ok */ + sfs->f_flags = 0; + if (vfs->f_flag & ST_RDONLY) + sfs->f_flags |= MNT_RDONLY; + if (vfs->f_flag & ST_NOSUID) + sfs->f_flags |= MNT_NOSUID; + + /* + * From a quick survey of f_bsize, f_iosize, and f_frsize on + * various NetBSD and Solaris systems, with varying fragment and + * block sizes: + * + * f_bsize f_iosize f_frsize + * netbsd 1k/8k 1024 8192 + * netbsd 2k/16k 2048 16384 + * solaris 1k/8k 8192 1024 + * solaris 2k/8k 8192 2048 + * solaris 512/4k 4096 512 + * + * It is apparent that: + * + * - netbsd's f_bsize is equivalent to the fragment size of the + * underlying filesystem + * - netbsd's f_iosize is equivalent to the block size of the + * underlying filesystem + * - solaris's f_bsize is equivalent to the block size of the + * underlying filesystem + * - solaris's f_frsize is equivalent to the fragment size of the + * underlying filesystem + * + * NetBSD's statfs(2) man page (and sys/mount.h header file) says: + * + * long f_bsize; /* fundamental file system block size * / + * long f_iosize; /* optimal transfer block size * / + * + * and Solaris's statvfs(2) man page says: + * + * u_long f_bsize; /* preferred file system block size * / + * u_long f_frsize; /* fundamental filesystem block + * (size if supported) * / + * + * so it makes sense that their f_frsize == our f_bsize. + * + * I see that Solaris's sys/statvfs.h says: + * + * unsigned long f_bsize; /* fundamental file system block size * / + * unsigned long f_frsize; /* fragment size * / + * + * but empiric testing (above) seems to indicate that the comments + * in their code are wrong. The following two assignments, even + * though they may look wrong, are actually correct. + */ + sfs->f_bsize = vfs->f_frsize; + sfs->f_iosize = vfs->f_bsize; + sfs->f_blocks = vfs->f_blocks; + sfs->f_bfree = vfs->f_bfree; + sfs->f_bavail = vfs->f_bavail; + sfs->f_files = vfs->f_files; + sfs->f_ffree = vfs->f_ffree; + (void) memcpy(&sfs->f_fsid.val[0], &vfs->f_fsid, sizeof(fsid_t)); + sfs->f_owner = 0; /* XXX: root always here */ + (void)strncpy(sfs->f_fstypename, + vfs->f_basetype, sizeof(sfs->f_fstypename)); + sfs->f_mntonname[0] = '\0'; /* XXX: */ + sfs->f_mntfromname[0] = '\0'; /* XXX: */ +} + +int +statfs(path, sfs) + const char *path; + struct statfs *sfs; +{ + struct statvfs vfs; + + if (statvfs(path, &vfs) == -1) + return -1; + vfs2fs(sfs, &vfs); + return 0; + +} + +int +fstatfs(fd, sfs) + int fd; + struct statfs *sfs; +{ + struct statvfs vfs; + + if (fstatvfs(fd, &vfs) == -1) + return -1; + + vfs2fs(sfs, &vfs); + return 0; +} +#endif + +/* + * Return free disk space (in bytes) on given file system + */ +off_t +min_free(char *tmpdir) +{ + struct statfs buf; + + if (statfs(tmpdir, &buf) != 0) { + warn("statfs"); + return -1; + } + return (off_t) buf.f_bavail * (off_t) buf.f_bsize; +} diff --git a/pkgtools/pkg_install/files/lib/pkgdb.c b/pkgtools/pkg_install/files/lib/pkgdb.c new file mode 100644 index 00000000000..1ae6d622307 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/pkgdb.c @@ -0,0 +1,275 @@ +/* $NetBSD: pkgdb.c,v 1.1.1.1 2002/12/20 18:14:03 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: pkgdb.c,v 1.1.1.1 2002/12/20 18:14:03 schmonz Exp $"); +#endif +#endif + +/* + * Copyright (c) 1999 Hubert Feyrer. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Hubert Feyrer for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_DB1_DB_H +#include <db1/db.h> +#elif defined(HAVE_DB_H) +#include <db.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#include <errno.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <stdarg.h> +#include <stdio.h> + +#include "lib.h" + +#define PKGDB_FILE "pkgdb.byfile.db" /* indexed by filename */ + +#if defined(HAVE_DBOPEN) +static DB *pkgdbp; +static int pkgdb_iter_flag; +#endif /* HAVE_DBOPEN */ + +/* + * Open the pkg-database + * Return value: + * 0: everything ok + * -1: error, see errno + */ +int +pkgdb_open(int ro) +{ +#if defined(HAVE_DBOPEN) + BTREEINFO info; + + pkgdb_iter_flag = 0; /* used in pkgdb_iter() */ + + /* try our btree format first */ + info.flags = 0; + info.cachesize = 2*1024*1024; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 4096; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + pkgdbp = (DB *) dbopen(_pkgdb_getPKGDB_FILE(), + ro ? O_RDONLY : O_RDWR | O_CREAT, + 0644, DB_BTREE, (void *) &info); + return (pkgdbp == NULL) ? -1 : 0; +#else + return 1; +#endif /* HAVE_DBOPEN */ +} + +/* + * Close the pkg database + */ +void +pkgdb_close(void) +{ +#if defined(HAVE_DBOPEN) + if (pkgdbp != NULL) { + (void) (pkgdbp->close) (pkgdbp); + pkgdbp = NULL; + } +#endif /* HAVE_DBOPEN */ +} + +/* + * Store value "val" with key "key" in database + * Return value is as from ypdb_store: + * 0: ok + * 1: key already present + * -1: some other error, see errno + */ +int +pkgdb_store(const char *key, const char *val) +{ +#if defined(HAVE_DBOPEN) + DBT keyd, vald; + + if (pkgdbp == NULL) + return -1; + + keyd.data = (void *) key; + keyd.size = strlen(key) + 1; + vald.data = (void *) val; + vald.size = strlen(val) + 1; + + if (keyd.size > FILENAME_MAX || vald.size > FILENAME_MAX) + return -1; + + return (pkgdbp->put) (pkgdbp, &keyd, &vald, R_NOOVERWRITE); +#else + return 0; +#endif /* HAVE_DBOPEN */ +} + +/* + * Recall value for given key + * Return value: + * NULL if some error occurred or value for key not found (check errno!) + * String for "value" else + */ +char * +pkgdb_retrieve(const char *key) +{ +#if defined(HAVE_DBOPEN) + DBT keyd, vald; + int status; + + if (pkgdbp == NULL) + return NULL; + + keyd.data = (void *) key; + keyd.size = strlen(key) + 1; + errno = 0; /* to be sure it's 0 if the key doesn't match anything */ + + vald.data = (void *)NULL; + vald.size = 0; + status = (pkgdbp->get) (pkgdbp, &keyd, &vald, 0); + if (status) { + vald.data = NULL; + vald.size = 0; + } + + return vald.data; +#else + return NULL; +#endif /* HAVE_DBOPEN */ +} + +/* + * Remove data set from pkgdb + * Return value as ypdb_delete: + * 0: everything ok + * 1: key not present + * -1: some error occurred (see errno) + */ +int +pkgdb_remove(const char *key) +{ +#if defined(HAVE_DBOPEN) + DBT keyd; + int status; + + if (pkgdbp == NULL) + return -1; + + keyd.data = (char *) key; + keyd.size = strlen(key) + 1; + if (keyd.size > FILENAME_MAX) + return -1; + + errno = 0; + status = (pkgdbp->del) (pkgdbp, &keyd, 0); + if (status) { + if (errno) + return -1; /* error */ + else + return 1; /* key not present */ + } else + return 0; /* everything fine */ +#else + return 0; +#endif /* HAVE_DBOPEN */ +} + +/* + * Iterate all pkgdb keys (which can then be handled to pkgdb_retrieve()) + * Return value: + * NULL if no more data is available + * !NULL else + */ +char * +pkgdb_iter(void) +{ +#if defined(HAVE_DBOPEN) + DBT key, val; + int status; + + if (pkgdb_iter_flag == 0) { + pkgdb_iter_flag = 1; + + status = (pkgdbp->seq) (pkgdbp, &key, &val, R_FIRST); + } else + status = (pkgdbp->seq) (pkgdbp, &key, &val, R_NEXT); + + if (status) + key.data = NULL; + + return (char *) key.data; +#else + return NULL; +#endif /* HAVE_DBOPEN */ +} + +/* + * Return filename as string that can be passed to free(3) + */ +char * +_pkgdb_getPKGDB_FILE(void) +{ + char *tmp; + + tmp = malloc(FILENAME_MAX); + if (tmp == NULL) + errx(1, "_pkgdb_getPKGDB_FILE: out of memory"); + snprintf(tmp, FILENAME_MAX, "%s/%s", _pkgdb_getPKGDB_DIR(), PKGDB_FILE); + return tmp; +} + +/* + * Return directory where pkgdb is stored + * as string that can be passed to free(3) + */ +char * +_pkgdb_getPKGDB_DIR(void) +{ + char *tmp; + static char *cache = NULL; + + if (cache == NULL) + cache = (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR; + + return cache; +} diff --git a/pkgtools/pkg_install/files/lib/plist.c b/pkgtools/pkg_install/files/lib/plist.c new file mode 100644 index 00000000000..c0466cc4d4d --- /dev/null +++ b/pkgtools/pkg_install/files/lib/plist.c @@ -0,0 +1,524 @@ +/* $NetBSD: plist.c,v 1.1.1.1 2002/12/20 18:14:04 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: plist.c,v 1.24 1997/10/08 07:48:15 charnier Exp"; +#else +__RCSID("$NetBSD: plist.c,v 1.1.1.1 2002/12/20 18:14:04 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * General packing list routines. + * + */ + +#include "lib.h" +#include <errno.h> + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_MD5GLOBAL_H +#include <md5global.h> +#endif + +#ifdef HAVE_MD5_H +#include <md5.h> +#endif + +/* This struct defines a plist command type */ +typedef struct cmd_t { + char *c_s; /* string to recognise */ + pl_ent_t c_type; /* type of command */ + int c_argc; /* # of arguments */ + int c_subst; /* can substitute real prefix */ +} cmd_t; + +/* Commands to recognise */ +static const cmd_t cmdv[] = { + {"cwd", PLIST_CWD, 1, 1}, + {"src", PLIST_SRC, 1, 1}, + {"cd", PLIST_CWD, 1, 1}, + {"exec", PLIST_CMD, 1, 0}, + {"unexec", PLIST_UNEXEC, 1, 0}, + {"mode", PLIST_CHMOD, 1, 0}, + {"owner", PLIST_CHOWN, 1, 0}, + {"group", PLIST_CHGRP, 1, 0}, + {"comment", PLIST_COMMENT, 1, 0}, + {"ignore", PLIST_IGNORE, 0, 0}, + {"ignore_inst", PLIST_IGNORE_INST, 0, 0}, + {"name", PLIST_NAME, 1, 0}, + {"display", PLIST_DISPLAY, 1, 0}, + {"pkgdep", PLIST_PKGDEP, 1, 0}, + {"pkgcfl", PLIST_PKGCFL, 1, 0}, + {"mtree", PLIST_MTREE, 1, 0}, + {"dirrm", PLIST_DIR_RM, 1, 0}, + {"option", PLIST_OPTION, 1, 0}, + {"blddep", PLIST_BLDDEP, 1, 0}, + {NULL, FAIL, 0, 0} +}; + +/* + * Add an item to the end of a packing list + */ +void +add_plist(package_t *p, pl_ent_t type, const char *arg) +{ + plist_t *tmp; + + tmp = new_plist_entry(); + tmp->name = (arg == (char *) NULL) ? (char *) NULL : strdup(arg); + tmp->type = type; + if (!p->head) { + p->head = p->tail = tmp; + } else { + tmp->prev = p->tail; + p->tail->next = tmp; + p->tail = tmp; + } +} + +/* + * Add an item to the start of a packing list + */ +void +add_plist_top(package_t *p, pl_ent_t type, const char *arg) +{ + plist_t *tmp; + + tmp = new_plist_entry(); + tmp->name = (arg == (char *) NULL) ? (char *) NULL : strdup(arg); + tmp->type = type; + if (!p->head) { + p->head = p->tail = tmp; + } else { + tmp->next = p->head; + p->head->prev = tmp; + p->head = tmp; + } +} + +/* + * Return the last (most recent) entry in a packing list + */ +plist_t * +last_plist(package_t *p) +{ + return p->tail; +} + +/* + * Mark all items in a packing list to prevent iteration over them + */ +void +mark_plist(package_t *pkg) +{ + plist_t *pp; + + for (pp = pkg->head; pp; pp = pp->next) { + pp->marked = TRUE; + } +} + +/* + * Find a given item in a packing list and, if so, return it (else NULL) + */ +plist_t * +find_plist(package_t *pkg, pl_ent_t type) +{ + plist_t *pp; + + for (pp = pkg->head; pp && pp->type != type; pp = pp->next) { + } + return pp; +} + +/* + * Look for a specific boolean option argument in the list + */ +char * +find_plist_option(package_t *pkg, char *name) +{ + plist_t *p; + + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_OPTION + && strcmp(p->name, name) == 0) { + return p->name; + } + } + + return (char *) NULL; +} + +/* + * Delete plist item 'type' in the list (if 'name' is non-null, match it + * too.) If 'all' is set, delete all items, not just the first occurance. + */ +void +delete_plist(package_t *pkg, Boolean all, pl_ent_t type, char *name) +{ + plist_t *p = pkg->head; + + while (p) { + plist_t *pnext = p->next; + + if (p->type == type && (!name || !strcmp(name, p->name))) { + free(p->name); + if (p->prev) + p->prev->next = pnext; + else + pkg->head = pnext; + if (pnext) + pnext->prev = p->prev; + else + pkg->tail = p->prev; + free(p); + if (!all) + return; + p = pnext; + } else + p = p->next; + } +} + +/* + * Allocate a new packing list entry, and return a pointer to it. + */ +plist_t * +new_plist_entry(void) +{ + plist_t *ret; + + if ((ret = (plist_t *) malloc(sizeof(plist_t))) == (plist_t *) NULL) { + err(EXIT_FAILURE, "can't allocate %ld bytes", (long) sizeof(plist_t)); + } + memset(ret, 0, sizeof(plist_t)); + return ret; +} + +/* + * Free an entire packing list + */ +void +free_plist(package_t *pkg) +{ + plist_t *p = pkg->head; + + while (p) { + plist_t *p1 = p->next; + + free(p->name); + free(p); + p = p1; + } + pkg->head = pkg->tail = NULL; +} + +/* + * For an ASCII string denoting a plist command, return its code and + * optionally its argument(s) + */ +int +plist_cmd(char *s, char **arg) +{ + const cmd_t *cmdp; + char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */ + char *cp; + char *sp; + + (void) strcpy(cmd, s); + str_lowercase(cmd); + for (cp = cmd, sp = s; *cp; cp++, sp++) { + if (isspace((unsigned char) *cp)) { + for (*cp = '\0'; isspace((unsigned char) *sp); sp++) { + } + break; + } + } + if (arg) { + *arg = sp; + } + for (cmdp = cmdv; cmdp->c_s && strcmp(cmdp->c_s, cmd) != 0; cmdp++) { + } + return cmdp->c_type; +} + +/* + * Read a packing list from a file + */ +void +read_plist(package_t *pkg, FILE * fp) +{ + char pline[FILENAME_MAX]; + char *cp; + int cmd; + int len; + + while (fgets(pline, FILENAME_MAX, fp) != (char *) NULL) { + for (len = strlen(pline); len && + isspace((unsigned char) pline[len - 1]);) { + pline[--len] = '\0'; + } + if (len == 0) { + continue; + } + if (*(cp = pline) == CMD_CHAR) { + if ((cmd = plist_cmd(pline + 1, &cp)) == FAIL) { + warnx("Unrecognised PLIST command `%s'", pline); + continue; + } + if (*cp == '\0') { + cp = NULL; + } + } else { + cmd = PLIST_FILE; + } + add_plist(pkg, cmd, cp); + } +} + +/* + * Write a packing list to a file, converting commands to ASCII equivs + */ +void +write_plist(package_t *pkg, FILE * fp, char *realprefix) +{ + plist_t *p; + const cmd_t *cmdp; + + for (p = pkg->head; p; p = p->next) { + if (p->type == PLIST_FILE) { + /* Fast-track files - these are the most common */ + (void) fprintf(fp, "%s\n", p->name); + continue; + } + for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) { + } + if (cmdp->c_type == FAIL) { + warnx("Unknown PLIST command type %d (%s)", p->type, p->name); + } else if (cmdp->c_argc == 0) { + (void) fprintf(fp, "%c%s\n", CMD_CHAR, cmdp->c_s); + } else if (cmdp->c_subst && realprefix) { + (void) fprintf(fp, "%c%s %s\n", CMD_CHAR, cmdp->c_s, realprefix); + } else { + (void) fprintf(fp, "%c%s %s\n", CMD_CHAR, cmdp->c_s, + (p->name) ? p->name : ""); + } + } +} + +/* + * Delete the results of a package installation. + * + * This is here rather than in the pkg_delete code because pkg_add needs to + * run it too in cases of failure. + */ +int +delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg) +{ + plist_t *p; + char *Where = ".", *last_file = ""; + int fail = SUCCESS; + Boolean preserve; + char tmp[FILENAME_MAX], *name = NULL; + + if (pkgdb_open(0) == -1) { + err(1, "cannot open pkgdb"); + } + + 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); + break; + + case PLIST_UNEXEC: + format_cmd(tmp, sizeof(tmp), p->name, Where, last_file); + if (Verbose) + printf("Execute `%s'\n", tmp); + if (!Fake && system(tmp)) { + warnx("unexec command for `%s' failed", tmp); + fail = FAIL; + } + break; + + case PLIST_FILE: + last_file = p->name; + (void) snprintf(tmp, sizeof(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 && /* || PLIST_MD5 - HF */ + strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) { + char *cp, buf[LegibleChecksumLen]; + + if ((cp = MD5File(tmp, buf)) != NULL) { + /* Mismatch? */ + if (strcmp(cp, p->next->name + ChecksumHeaderLen) != 0) { + 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 file %s\n", tmp); + if (!Fake) { + int restored = 0; /* restored from preserve? */ + + 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); + else + restored = 1; + } + } + } + + if (!restored) { +#ifdef PKGDB_DEBUG + printf("pkgdb_remove(\"%s\")\n", tmp); /* HF */ +#endif + errno = 0; + if (pkgdb_remove(tmp)) { + if (errno) { + perror("pkgdb_remove"); + } + } else { +#ifdef PKGDB_DEBUG + printf("pkgdb_remove: ok\n"); +#endif + } + } + } + } + break; + + case PLIST_DIR_RM: + (void) snprintf(tmp, sizeof(tmp), "%s/%s", Where, p->name); + if (fexists(tmp)) { + if (!isdir(tmp)) { + warnx("cannot remove `%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; + } + } + } else { + warnx("cannot remove non-existent directory `%s'\n" + "this packing list is incorrect - ignoring delete request", tmp); + } + last_file = p->name; + break; + default: + break; + } + } + pkgdb_close(); + return fail; +} + +#ifdef DEBUG +#define RMDIR(dir) vsystem("%s %s", RMDIR, dir) +#define REMOVE(dir,ie) vsystem("%s %s%s", RM, (ie ? "-f " : ""), dir) +#else +#define RMDIR rmdir +#define REMOVE(file,ie) (remove(file) && !(ie)) +#endif + +/* + * Selectively delete a hierarchy + * Returns 1 on error, 0 else. + */ +int +delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) +{ + char *cp1, *cp2; + + cp1 = cp2 = dir; + if (!fexists(dir)) { + if (!ign_err) + warnx("%s `%s' doesn't really exist", + isdir(dir) ? "directory" : "file", dir); + return !ign_err; + } else if (nukedirs) { + if (vsystem("%s -r%s %s", RM, (ign_err ? "f" : ""), dir)) + return 1; + } else if (isdir(dir)) { + if (RMDIR(dir) && !ign_err) + return 1; + } else { + if (REMOVE(dir, ign_err)) + return 1; + } + + if (!nukedirs) + return 0; + while (cp2) { + if ((cp2 = strrchr(cp1, '/')) != NULL) + *cp2 = '\0'; + if (!isemptydir(dir)) + return 0; + if (RMDIR(dir) && !ign_err) { + if (!fexists(dir)) + warnx("directory `%s' doesn't really exist", dir); + else + return 1; + } + /* back up the pathname one component */ + if (cp2) { + cp1 = dir; + } + } + return 0; +} diff --git a/pkgtools/pkg_install/files/lib/setenv.c b/pkgtools/pkg_install/files/lib/setenv.c new file mode 100644 index 00000000000..bce4c082930 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/setenv.c @@ -0,0 +1,74 @@ +/* $NetBSD: setenv.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> + +#ifndef HAVE_SETENV +int +setenv(name, value, overwrite) + const char *name; + const char *value; + int overwrite; +{ + size_t len; + int ret; + char *p; + + if (overwrite == 0 && getenv(name)) + return 0; + + if (value == NULL) + value = ""; + + len = strlen(name) + strlen(value) + 2; + p = (char *) malloc(len); + if (p == NULL) + return -1; + + (void) sprintf(p, "%s=%s", name, value); + ret = putenv(p); + return ret; +} +#endif diff --git a/pkgtools/pkg_install/files/lib/setprogname.c b/pkgtools/pkg_install/files/lib/setprogname.c new file mode 100644 index 00000000000..1de44d32f4b --- /dev/null +++ b/pkgtools/pkg_install/files/lib/setprogname.c @@ -0,0 +1,63 @@ +/* $Id: setprogname.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ +/* $NetBSD: setprogname.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Todd Vierling. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <stdio.h> + +static const char *__progname = "<unset_progname>"; + +#ifndef HAVE_SETPROGNAME +void +setprogname(const char *progname) +{ + __progname = strrchr(progname, '/'); + if (__progname == NULL) + __progname = progname; + else + __progname++; +} +#endif + +#ifndef HAVE_GETPROGNAME +const char * +getprogname(void) +{ + return __progname; +} +#endif diff --git a/pkgtools/pkg_install/files/lib/str.c b/pkgtools/pkg_install/files/lib/str.c new file mode 100644 index 00000000000..a994728892f --- /dev/null +++ b/pkgtools/pkg_install/files/lib/str.c @@ -0,0 +1,741 @@ +/* $NetBSD: str.c,v 1.1.1.1 2002/12/20 18:14:05 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "Id: str.c,v 1.5 1997/10/08 07:48:21 charnier Exp"; +#else +__RCSID("$NetBSD: str.c,v 1.1.1.1 2002/12/20 18:14:05 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous string utilities. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ASSERT_H +#include <assert.h> +#endif + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#include "lib.h" + +/* + * Return the suffix portion of a path + */ +const char * +suffix_of(const char *str) +{ + const char *dot; + + return ((dot = strrchr(basename_of(str), '.')) == NULL) ? "" : dot + 1; +} + +/* + * Return the filename portion of a path + */ +const char * +basename_of(const char *str) +{ + const char *slash; + + return ((slash = strrchr(str, '/')) == NULL) ? str : slash + 1; +} + +/* + * Return the dirname portion of a path + */ +const char * +dirname_of(const char *path) +{ + size_t cc; + char *s; + static char buf[PATH_MAX]; + + if ((s = strrchr(path, '/')) == NULL) { + return "."; + } + if (s == path) { + /* "/foo" -> return "/" */ + return "/"; + } + cc = (size_t) (s - path); + if (cc >= sizeof(buf)) + errx(1, "dirname_of: too long dirname: '%s'", path); + (void) memcpy(buf, path, cc); + buf[cc] = 0; + return buf; +} + +/* + * Get a string parameter as a file spec or as a "contents follow -" spec + */ +char * +get_dash_string(char **s) +{ + return *s = (**s == '-') ? strdup(*s + 1) : fileGetContents(*s); +} + +/* + * Lowercase a whole string + */ +void +str_lowercase(char *s) +{ + for (; *s; s++) { + *s = tolower(*s); + } +} + +/* pull in definitions and macros for resizing arrays as we go */ +#include "defs.h" + +/* do not modify these values, or things will NOT work */ +enum { + RC = -1, + Dot = 0, + Patch = 1 +}; + +/* this struct defines a version number */ +typedef struct arr_t { + unsigned c; /* # of version numbers */ + unsigned size; /* size of array */ + int64_t *v; /* array of decimal numbers */ + int64_t netbsd; /* any "nb" suffix */ +} arr_t; + +/* this struct describes a test */ +typedef struct test_t { + const char *s; /* string representation */ + unsigned len; /* length of string */ + int t; /* enumerated type of test */ +} test_t; + +enum { + LT, + LE, + EQ, + GE, + GT, + NE +}; + +/* the tests that are recognised. */ +static const test_t tests[] = { + { "<=", 2, LE }, + { "<", 1, LT }, + { ">=", 2, GE }, + { ">", 1, GT }, + { "==", 2, EQ }, + { "!=", 2, NE }, + { NULL, 0, 0 } +}; + + +/* locate the test in the tests array */ +static int +mktest(int *op, char *test) +{ + const test_t *tp; + + for (tp = tests ; tp->s ; tp++) { + if (strncasecmp(test, tp->s, tp->len) == 0) { + *op = tp->t; + return tp->len; + } + } + warnx("relational test not found `%.10s'", test); + return -1; +} + +/* + * make a component of a version number. + * '.' encodes as Dot which is '0' + * '_' encodes as 'patch level', or 'Dot', which is 0. + * 'pl' encodes as 'patch level', or 'Dot', which is 0. + * 'rc' encodes as 'release candidate', or RC, which is -1. + * 'nb' encodes as 'netbsd version', which is used after all other tests + */ +static int +mkcomponent(arr_t *ap, char *num) +{ + static const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; + int64_t n; + char *cp; + + if (*num == 0) { + return 0; + } + ALLOC(int64_t, ap->v, ap->size, ap->c, 62, "mkver", exit(EXIT_FAILURE)); + if (*num == '_') { + num += 1; + if (isdigit(*(num + 1))) { + ap->v[ap->c++] = Dot; + return 1; + } + } + if (isdigit(*num)) { + for (cp = num, n = 0 ; isdigit(*num) ; num++) { + n = (n * 10) + (*num - '0'); + } + ap->v[ap->c++] = n; + return (int)(num - cp); + } + if (strncasecmp(num, "rc", 2) == 0) { + ap->v[ap->c++] = RC; + return 2; + } + if (strncasecmp(num, "pl", 2) == 0) { + ap->v[ap->c++] = Dot; + return 2; + } + if (strncasecmp(num, "nb", 2) == 0) { + for (cp = num, num += 2, n = 0 ; isdigit(*num) ; num++) { + n = (n * 10) + (*num - '0'); + } + ap->netbsd = n; + return (int)(num - cp); + } + if (*num == '.') { + ap->v[ap->c++] = Dot; + return 1; + } + if (isalpha(*num)) { + ap->v[ap->c++] = Dot; + cp = strchr(alphas, tolower(*num)); + ALLOC(int64_t, ap->v, ap->size, ap->c, 62, "mkver", exit(EXIT_FAILURE)); + ap->v[ap->c++] = (int64_t)(cp - alphas) + 1; + return 1; + } + warnx("`%c' not recognised", *num); + return 1; +} + +/* make a version number string into an array of comparable 64bit ints */ +static int +mkversion(arr_t *ap, char *num) +{ + (void) memset(ap, 0, sizeof(arr_t)); + while (*num) { + num += mkcomponent(ap, num); + } + return 1; +} + +#define DIGIT(v, c, n) (((n) < (c)) ? v[n] : 0) + +/* compare the result against the test we were expecting */ +static int +result(int64_t cmp, int tst) +{ + switch(tst) { + case LT: + return cmp < 0; + case LE: + return cmp <= 0; + case GT: + return cmp > 0; + case GE: + return cmp >= 0; + case EQ: + return cmp == 0; + case NE: + return cmp != 0; + default: + warnx("result: unknown test %d", tst); + return 0; + } +} + +/* do the test on the 2 vectors */ +static int +vtest(arr_t *lhs, int tst, arr_t *rhs) +{ + int64_t cmp; + int c; + int i; + + for (i = 0, c = MAX(lhs->c, rhs->c) ; i < c ; i++) { + if ((cmp = DIGIT(lhs->v, lhs->c, i) - DIGIT(rhs->v, rhs->c, i)) != 0) { + return result(cmp, tst); + } + } + return result(lhs->netbsd - rhs->netbsd, tst); +} + +/* + * Compare two dewey decimal numbers + */ +static int +deweycmp(char *lhs, int op, char *rhs) +{ + arr_t right; + arr_t left; + + (void) memset(&left, 0, sizeof(left)); + if (!mkversion(&left, lhs)) { + warnx("Bad lhs version `%s'", lhs); + return 0; + } + (void) memset(&right, 0, sizeof(right)); + if (!mkversion(&right, rhs)) { + warnx("Bad rhs version `%s'", rhs); + return 0; + } + return vtest(&left, op, &right); +} + +/* + * Perform alternate match on "pkg" against "pattern", + * calling pmatch (recursively) to resolve any other patterns. + * Return 1 on match, 0 otherwise + */ +static int +alternate_match(const char *pattern, const char *pkg) +{ + char *sep; + char buf[FILENAME_MAX]; + char *last; + char *alt; + char *cp; + int cnt; + int found; + + if ((sep = strchr(pattern, '{')) == (char *) NULL) { + errx(1, "alternate_match(): '{' expected in `%s'", pattern); + } + (void) strncpy(buf, pattern, (size_t) (sep - pattern)); + alt = &buf[sep - pattern]; + last = (char *) NULL; + for (cnt = 0, cp = sep; *cp && last == (char *) NULL; cp++) { + if (*cp == '{') { + cnt++; + } else if (*cp == '}' && --cnt == 0 && last == (char *) NULL) { + last = cp + 1; + } + } + if (cnt != 0) { + errx(1, "Malformed alternate `%s'", pattern); + } + for (found = 0, 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 (pmatch(buf, pkg) == 1) { + found = 1; + } + } + return found; +} + +/* + * Perform dewey match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +dewey_match(const char *pattern, const char *pkg) +{ + char *cp; + char *sep; + char *ver; + char name[FILENAME_MAX]; + int op; + int n; + + if ((sep = strpbrk(pattern, "<>")) == NULL) { + errx(1, "dewey_match(): '<' or '>' expected in `%s'", pattern); + } + (void) snprintf(name, sizeof(name), "%.*s", (int) (sep - pattern), pattern); + if ((n = mktest(&op, sep)) < 0) { + warnx("Bad comparison `%s'", sep); + return 0; + } + ver = sep + n; + n = (int) (sep - pattern); + if ((cp = strrchr(pkg, '-')) != (char *) NULL) { + if (strncmp(pkg, name, (size_t) (cp - pkg)) == 0 && + n == (int)(cp - pkg)) { + if (deweycmp(cp + 1, op, ver)) { + return 1; + } + } + } + return 0; +} + +/* + * Perform glob match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +glob_match(const char *pattern, const char *pkg) +{ + return fnmatch(pattern, pkg, FNM_PERIOD) == 0; +} + +/* + * Perform simple match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +simple_match(const char *pattern, const char *pkg) +{ + return strcmp(pattern, pkg) == 0; +} + +/* + * Match pkg against pattern, return 1 if matching, 0 else + */ +int +pmatch(const char *pattern, const char *pkg) +{ + if (strchr(pattern, '{') != (char *) NULL) { + /* emulate csh-type alternates */ + return alternate_match(pattern, pkg); + } + if (strpbrk(pattern, "<>") != (char *) NULL) { + /* perform relational dewey match on version number */ + return dewey_match(pattern, pkg); + } + if (strpbrk(pattern, "*?[]") != (char *) NULL) { + /* glob match */ + return glob_match(pattern, pkg); + } + + /* no alternate, dewey or glob match -> simple compare */ + return simple_match(pattern, pkg); +} + +/* + * Search dir for pattern, calling match(pkg_found, data) for every match. + * Returns -1 on error, 1 if found, 0 otherwise. + */ +int +findmatchingname(const char *dir, const char *pattern, matchfn match, void *data) +{ + struct dirent *dp; + char tmp_pattern[PKG_PATTERN_MAX]; + DIR *dirp; + int found; + char pat_sfx[PKG_SUFFIX_MAX], file_sfx[PKG_SUFFIX_MAX]; /* suffixes */ + + if (strlen(pattern) >= PKG_PATTERN_MAX) + errx(1, "too long pattern '%s'", pattern); + + found = 0; + if ((dirp = opendir(dir)) == (DIR *) NULL) { + /* warnx("can't opendir dir '%s'", dir); */ + return -1; + } + + /* chop any possible suffix off of 'pattern' and + * store it in pat_sfx + */ + strip_txz(tmp_pattern, pat_sfx, pattern); + + while ((dp = readdir(dirp)) != (struct dirent *) NULL) { + char tmp_file[FILENAME_MAX]; + + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + + /* chop any possible suffix off of 'tmp_file' and + * store it in file_sfx + */ + strip_txz(tmp_file, file_sfx, dp->d_name); + + /* we need to match pattern and suffix separately, in case + * each is a different pattern class (e.g. dewey and + * character class (.t[bg]z)) */ + if (pmatch(tmp_pattern, tmp_file) + && pmatch(pat_sfx, file_sfx)) { + if (match) { + match(dp->d_name, data); + /* return value ignored for now */ + } + found = 1; + } + } + (void) closedir(dirp); + return found; +} + +/* + * Does the pkgname contain any of the special chars ("{[]?*<>")? + * If so, return 1, else 0 + */ +int +ispkgpattern(const char *pkg) +{ + return strpbrk(pkg, "<>[]?*{") != NULL; +} + +/* + * Auxiliary function called by findbestmatchingname() if pkg > data + * Also called for FTP matching + */ +int +findbestmatchingname_fn(const char *found, void *vp) +{ + char *best = vp; + char *found_version, *best_version; + char found_no_sfx[PKG_PATTERN_MAX]; + char best_no_sfx[PKG_PATTERN_MAX]; + + /* The same suffix-hack-off again, but we can't do it + * otherwise without changing the function call interface + */ + found_version = strrchr(found, '-'); + if (found_version) { + /* skip '-', if any version found */ + found_version++; + } + strip_txz(found_no_sfx, NULL, found_version); + found_version = found_no_sfx; + + best_version=NULL; + if (best && best[0] != '\0') { + best_version = strrchr(best, '-'); + if (best_version) { + /* skip '-' if any version found */ + best_version++; + } + strip_txz(best_no_sfx, NULL, best_version); + best_version = best_no_sfx; + } + + if (found_version == NULL) { + fprintf(stderr, "'%s' is not a usable package(version)\n", + found); + } else { + /* if best_version==NULL only if best==NULL + * (or best[0]='\0') */ + if (best == NULL || best[0] == '\0' || deweycmp(found_version, GT, best_version)) { + /* found pkg(version) is bigger than current "best" + * version - remember! */ + strcpy(best, found); + } + } + + return 0; +} + +/* + * Find best matching filename, i.e. the pkg with the highest + * matching(!) version. + * Returns pointer to pkg name (which can be free(3)ed), + * or NULL if no match is available. + */ +char * +findbestmatchingname(const char *dir, const char *pattern) +{ + char buf[FILENAME_MAX]; + + buf[0] = '\0'; + if (findmatchingname(dir, pattern, findbestmatchingname_fn, buf) > 0 + && buf[0] != '\0') { + return strdup(buf); + } + return NULL; +} + +/* + * Bounds-checking strncpy() + */ +char * +strnncpy(char *to, size_t tosize, char *from, size_t cc) +{ + size_t len; + + if ((len = cc) >= tosize - 1) { + len = tosize - 1; + } + (void) strncpy(to, from, len); + to[len] = 0; + return to; +} + +/* + * Strip off any .tgz, .tbz or .t[bg]z suffix from fname, + * and copy into buffer "buf", the suffix is stored in "sfx" + * if "sfx" is not NULL. If no suffix is found, "sfx" is set + * to an empty string. + */ +void +strip_txz(char *buf, char *sfx, const char *fname) +{ + static const char *const suffixes[] = { + ".tgz", ".tbz", ".t[bg]z", 0}; + const char *const *suffixp; + size_t len; + + len = strlen(fname); + assert(len < PKG_PATTERN_MAX); + + if (sfx) + sfx[0] = '\0'; + + for (suffixp = suffixes; *suffixp; suffixp++) { + size_t suffixlen = strlen(*suffixp); + + if (memcmp(&fname[len - suffixlen], *suffixp, suffixlen)) + continue; + + /* matched! */ + memcpy(buf, fname, len - suffixlen); + buf[len - suffixlen] = 0; + if (sfx) { + if (suffixlen >= PKG_SUFFIX_MAX) + errx(1, "too long suffix '%s'", fname); + memcpy(sfx, *suffixp, suffixlen+1); + return; + } + } + + /* not found */ + memcpy(buf, fname, len+1); +} + +/* + * Called to see if pkg is already installed as some other version, + * note found version in "note". + */ +int +note_whats_installed(const char *found, void *vp) +{ + char *note = vp; + + (void) strlcpy(note, found, FILENAME_MAX); + return 0; +} + +/* + * alloc lpkg for pkg and add it to list. + */ +int +add_to_list_fn(const char *pkg, void *vp) +{ + lpkg_head_t *pkgs = vp; + lpkg_t *lpp; + char fn[FILENAME_MAX]; + + snprintf(fn, sizeof(fn), "%s/%s", _pkgdb_getPKGDB_DIR(), pkg); + if (!isfile(fn)) { /* might as well use sanity_check() */ + lpp = alloc_lpkg(pkg); + TAILQ_INSERT_TAIL(pkgs, lpp, lp_link); + } + + return 0; +} + +#ifndef HAVE_STRSEP +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) +{ + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} +#endif + +#ifndef HAVE_STRLCPY +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif diff --git a/pkgtools/pkg_install/files/lib/unsetenv.c b/pkgtools/pkg_install/files/lib/unsetenv.c new file mode 100644 index 00000000000..e713732239b --- /dev/null +++ b/pkgtools/pkg_install/files/lib/unsetenv.c @@ -0,0 +1,63 @@ +/* $NetBSD: unsetenv.c,v 1.1.1.1 2002/12/20 18:14:06 schmonz Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <stdlib.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +extern char **environ; + +#ifndef HAVE_UNSETENV +void +unsetenv(name) + const char *name; +{ + size_t len = strlen(name); + char **ptr, **p; + + for (ptr = environ; *ptr; ptr++) + if (strncmp(name, *ptr, len) == 0 && (*ptr)[len] == '=') { + for (p = ptr;; ++p) + if (!(*p = *(p + 1))) + break; + } +} +#endif diff --git a/pkgtools/pkg_install/files/lib/version.c b/pkgtools/pkg_install/files/lib/version.c new file mode 100644 index 00000000000..f90ee301c5f --- /dev/null +++ b/pkgtools/pkg_install/files/lib/version.c @@ -0,0 +1,51 @@ +/* $NetBSD: version.c,v 1.1.1.1 2002/12/20 18:14:05 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: version.c,v 1.1.1.1 2002/12/20 18:14:05 schmonz Exp $"); +#endif +#endif + +/* + * Copyright (c) 2001 Thomas Klausner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Thomas Klausner for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> + +#include "lib.h" +#include "version.h" + +void +show_version(void) +{ + printf("%s\n", PKGTOOLS_VERSION); + exit (0); +} + diff --git a/pkgtools/pkg_install/files/lib/version.h b/pkgtools/pkg_install/files/lib/version.h new file mode 100644 index 00000000000..78017071760 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/version.h @@ -0,0 +1,38 @@ +/* $NetBSD: version.h,v 1.1.1.1 2002/12/20 18:14:05 schmonz Exp $ */ + +/* + * Copyright (c) 2001 Thomas Klausner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Thomas Klausner for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _INST_LIB_VERSION_H_ +#define _INST_LIB_VERSION_H_ + +#define PKGTOOLS_VERSION "20021123" + +#endif /* _INST_LIB_VERSION_H_ */ diff --git a/pkgtools/pkg_install/files/tkpkg b/pkgtools/pkg_install/files/tkpkg new file mode 100644 index 00000000000..73f2f2907e3 --- /dev/null +++ b/pkgtools/pkg_install/files/tkpkg @@ -0,0 +1,152 @@ +#!/usr/pkg/bin/wish -f +# from FreeBSD Id: tkpkg,v 1.4 1997/02/22 16:09:13 peter Exp +# +set pkgname "" +wm title . "Package Installation" +#-------------------------------------------------------------- +# The top level main window, consisting of a bar of buttons and a list +# of packages and a description of the current package. +#-------------------------------------------------------------- +frame .menu -relief raised -borderwidth 1 +frame .frame -borderwidth 4 + +scrollbar .frame.scroll -relief sunken -command ".frame.list yview" +listbox .frame.list -yscroll ".frame.scroll set" -relief sunken -setgrid 1 +pack append .frame .frame.scroll {right filly} \ + .frame.list {left expand fill} + +# build the lower window shoing the complete description of a pacage +frame .f -borderwidth 4 +text .f.t -width 80 -height 20 -yscrollcommand ".f.s set" -relief sunken + +# Initially display instructions in this window. Erase the +# instructions and show the package description when the user clicks +# on a package. +# +.f.t insert end "Double click on a package above to see its +complete description here." +scrollbar .f.s -relief sunken -command ".f.t yview" +pack append .f .f.s {right filly} .f.t {left expand fill} + +bind .frame.list <Double-Button-1> \ + { do_description [selection get] } +pack append . .menu {top fill} \ + .f {bottom expand fill} \ + .frame {bottom expand fill} + +#---------------------------------------------------------------- +# Make menu bar: +#---------------------------------------------------------------- +button .menu.inst -text "Install" \ + -command "apply_to_pkg \"pkg_add -v\"" +button .menu.dein -text "Deinstall" \ + -command "apply_to_pkg \"pkg_delete -v\"" +button .menu.installed -text "What is Installed?" \ + -command "list_pkgs \"pkg_info -I -a |tr ' ' ' '\"" +button .menu.available -text "What can I install?" \ + -command "list_pkgs \"pkg_info -I -c [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}] |tr ' ' ' '\"" +button .menu.cont -text "Contents?" \ + -command "apply_to_pkg \"pkg_info -d -v\"" +button .menu.quit -text "Quit" -command "destroy ." +button .menu.help -text "Help" -command "do_help" + +pack append .menu \ + .menu.inst left \ + .menu.dein left \ + .menu.installed left \ + .menu.available left \ + .menu.cont left \ + .menu.quit left \ + .menu.help right +#------------------------------------------------------- +# Display the package description. +#------------------------------------------------------- +proc list_pkgs {s} { + set line "" + set f [eval "open {| sh -c \"$s\" } r"] + .frame.list delete 0 end + while {[gets $f line] > 0} { + .frame.list insert end $line + } + close $f +} + +# display the list of available packages +set archives [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}] +if {$archives == ""} { + .frame.list delete 0 end + .frame.list insert end "Warning: no compressed tar archives files found." +} else { + list_pkgs "pkg_info -I -c $archives |tr ' ' ' '" +} + +#------------------------------------------------------- +# Display the package description. +#------------------------------------------------------- +proc do_description {s} { + global pkgname + regexp {[^ ]*} $s filename + set pkgname $filename + .f.t delete 0.0 end + set cmd "pkg_info -d $filename |tr -d ''" + set f [eval "open {| csh -c \"$cmd\" } r"] + while {![eof $f]} { + .f.t insert end [read $f] + } +} +#------------------------------------------------------- +# package install window. +#------------------------------------------------------- +proc do_help {{w .help}} { + catch {destroy $w} + toplevel $w + wm title $w "Help" + wm iconname $w "Help" + button $w.ok -text OK -command "destroy $w" + message $w.t -relief raised -bd 2 \ + -text "You can install, deinstall and list info on the available packages. To select a package and see its complete description, press mouse button 1 over the package name. To install a selected package, press the Install button. To exit, press the \"Quit\" button." + pack append $w $w.ok {bottom fillx} $w.t {expand fill} +} +#------------------------------------------------------- +# Apply a command to a package. +#------------------------------------------------------- +proc apply_to_pkg {s} { + apply_to_pkg_err $s "" +} +#------------------------------------------------------- +# Apply a command to a package, with error stream redirection instructions. +#------------------------------------------------------- +proc apply_to_pkg_err {s errredir} { + global pkgname + .f.t delete 0.0 end + if {$pkgname == ""} { + .f.t insert end "You must double click on a package name first!" + } else { + apply_to_pkg_int "$s $pkgname" "2>&1" + } +} +proc apply_to_pkg_int {s errredir} { + .f.t delete 0.0 end + .f.t insert end "Running: $s\n" + set f [eval "open {| sh -c \"$s $errredir\" } r"] + while {![eof $f]} { + .f.t insert end [read $f 64] + } +} +#------------------------------------------------------- +# Invoke an arbitrary command. +#------------------------------------------------------- +proc do_command {s} { + .f.t delete 0.0 end + .f.t insert end "Running: $s\n" + set f [eval "open {| $s} r"] + while {![eof $f]} { + .f.t insert end [read $f 64] + } +} +# local variables: +# mode: csh +# compile-command: "" +# comment-start: "# " +# comment-start-skip: "# " +# end: |