aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/pkg_install/Makefile3
-rw-r--r--usr.sbin/pkg_install/Makefile.inc1
-rw-r--r--usr.sbin/pkg_install/add/Makefile8
-rw-r--r--usr.sbin/pkg_install/add/add.h39
-rw-r--r--usr.sbin/pkg_install/add/extract.c101
-rw-r--r--usr.sbin/pkg_install/add/futil.c86
-rw-r--r--usr.sbin/pkg_install/add/main.c119
-rw-r--r--usr.sbin/pkg_install/add/perform.c205
-rw-r--r--usr.sbin/pkg_install/add/pkg_add.1125
-rw-r--r--usr.sbin/pkg_install/create/Makefile8
-rw-r--r--usr.sbin/pkg_install/create/create.h39
-rw-r--r--usr.sbin/pkg_install/create/main.c125
-rw-r--r--usr.sbin/pkg_install/create/perform.c165
-rw-r--r--usr.sbin/pkg_install/create/pkg_create.1185
-rw-r--r--usr.sbin/pkg_install/create/pl.c104
-rw-r--r--usr.sbin/pkg_install/delete/Makefile8
-rw-r--r--usr.sbin/pkg_install/delete/delete.h31
-rw-r--r--usr.sbin/pkg_install/delete/main.c108
-rw-r--r--usr.sbin/pkg_install/delete/perform.c119
-rw-r--r--usr.sbin/pkg_install/delete/pkg_delete.1107
-rw-r--r--usr.sbin/pkg_install/info/Makefile8
-rw-r--r--usr.sbin/pkg_install/info/info.h41
-rw-r--r--usr.sbin/pkg_install/info/main.c138
-rw-r--r--usr.sbin/pkg_install/info/perform.c144
-rw-r--r--usr.sbin/pkg_install/info/pkg_info.178
-rw-r--r--usr.sbin/pkg_install/info/show.c110
-rw-r--r--usr.sbin/pkg_install/lib/Makefile9
-rw-r--r--usr.sbin/pkg_install/lib/exec.c48
-rw-r--r--usr.sbin/pkg_install/lib/file.c164
-rw-r--r--usr.sbin/pkg_install/lib/global.c31
-rw-r--r--usr.sbin/pkg_install/lib/lib.h143
-rw-r--r--usr.sbin/pkg_install/lib/msg.c97
-rw-r--r--usr.sbin/pkg_install/lib/pen.c63
-rw-r--r--usr.sbin/pkg_install/lib/plist.c270
-rw-r--r--usr.sbin/pkg_install/lib/str.c85
35 files changed, 3115 insertions, 0 deletions
diff --git a/usr.sbin/pkg_install/Makefile b/usr.sbin/pkg_install/Makefile
new file mode 100644
index 000000000000..37a1f05783a6
--- /dev/null
+++ b/usr.sbin/pkg_install/Makefile
@@ -0,0 +1,3 @@
+SUBDIR=lib add create delete info
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/pkg_install/Makefile.inc b/usr.sbin/pkg_install/Makefile.inc
new file mode 100644
index 000000000000..363c20aee3dc
--- /dev/null
+++ b/usr.sbin/pkg_install/Makefile.inc
@@ -0,0 +1 @@
+BINDIR?= /usr/local/bin
diff --git a/usr.sbin/pkg_install/add/Makefile b/usr.sbin/pkg_install/add/Makefile
new file mode 100644
index 000000000000..d91baba68b7b
--- /dev/null
+++ b/usr.sbin/pkg_install/add/Makefile
@@ -0,0 +1,8 @@
+PROG= pkg_add
+
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD+= -L${.CURDIR}/../lib -linstall
+
+SRCS= main.c perform.c futil.c extract.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/add/add.h b/usr.sbin/pkg_install/add/add.h
new file mode 100644
index 000000000000..8206f0fb4708
--- /dev/null
+++ b/usr.sbin/pkg_install/add/add.h
@@ -0,0 +1,39 @@
+/* $Id: add.h,v 1.3 1993/08/24 09:23:13 jkh 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
+
+extern char *Prefix;
+extern Boolean NoInstall;
+extern Boolean NoRecord;
+extern char *Mode;
+extern char *Owner;
+extern char *Group;
+extern char *Directory;
+extern char *PkgName;
+
+int make_hierarchy(char *);
+void extract_plist(char *, Package *);
+void apply_perms(char *, char *);
+
+#endif /* _INST_ADD_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c
new file mode 100644
index 000000000000..62ae03e3acc9
--- /dev/null
+++ b/usr.sbin/pkg_install/add/extract.c
@@ -0,0 +1,101 @@
+#ifndef lint
+static const char *rcsid = "$Id: extract.c,v 1.4 1993/08/24 09:23:14 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "add.h"
+
+void
+extract_plist(char *home, Package *pkg)
+{
+ PackingList p = pkg->head;
+ char *last_file;
+
+ /* Reset the world */
+ Owner = NULL;
+ Group = NULL;
+ Mode = NULL;
+ last_file = NULL;
+ Directory = home;
+
+ /* Do it */
+ while (p) {
+ 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) {
+ copy_hierarchy(Directory, p->name, TRUE);
+ apply_perms(Directory, p->name);
+ }
+ break;
+
+ case PLIST_CWD:
+ if (Verbose)
+ printf("extract: CWD to %s\n", p->name);
+ if (strcmp(p->name, ".")) {
+ if (!Fake && make_hierarchy(p->name) == FAIL)
+ barf("Unable make directory '%s'.", p->name);
+ Directory = p->name;
+ }
+ else
+ Directory = home;
+ break;
+
+ case PLIST_CMD:
+ if (Verbose)
+ printf("extract: exec cmd '%s' (lastfile = %s)\n", p->name,
+ last_file);
+ if (!Fake && vsystem(p->name, last_file))
+ whinge("Command '%s' failed.", p->name);
+ break;
+
+ case PLIST_CHMOD:
+ Mode = p->name;
+ break;
+
+ case PLIST_CHOWN:
+ Owner = p->name;
+ break;
+
+ case PLIST_CHGRP:
+ Group = p->name;
+ break;
+
+ case PLIST_COMMENT:
+ break;
+
+ case PLIST_IGNORE:
+ p = p->next;
+ break;
+ }
+ p = p->next;
+ }
+}
diff --git a/usr.sbin/pkg_install/add/futil.c b/usr.sbin/pkg_install/add/futil.c
new file mode 100644
index 000000000000..2b70f5b967fd
--- /dev/null
+++ b/usr.sbin/pkg_install/add/futil.c
@@ -0,0 +1,86 @@
+#ifndef lint
+static const char *rcsid = "$Id: futil.c,v 1.3 1993/08/26 08:12:25 jkh Exp $";
+#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"
+#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 = index(cp1, '/')) !=NULL )
+ *cp2 = '\0';
+ if (fexists(dir)) {
+ if (!isdir(dir))
+ return FAIL;
+ }
+ else {
+ if (vsystem("mkdir %s", dir))
+ 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 *file)
+{
+ char fname[FILENAME_MAX];
+
+ if (!dir || *file == '/') /* absolute path? */
+ strcpy(fname, file);
+ else
+ sprintf(fname, "%s/%s", dir, file);
+ if (Mode)
+ if (vsystem("chmod -R %s %s", Mode, fname))
+ whinge("Couldn't change mode of '%s' to '%s'.",
+ fname, Mode);
+ if (Owner)
+ if (vsystem("chown -R %s %s", Owner, fname))
+ whinge("Couldn't change owner of '%s' to '%s'.",
+ fname, Owner);
+ if (Group)
+ if (vsystem("chgrp -R %s %s", Group, fname))
+ whinge("Couldn't change group of '%s' to '%s'.",
+ fname, Group);
+}
+
diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
new file mode 100644
index 000000000000..679dd12ca0ce
--- /dev/null
+++ b/usr.sbin/pkg_install/add/main.c
@@ -0,0 +1,119 @@
+#ifndef lint
+static char *rcsid = "$Id: main.c,v 1.5 1993/08/26 08:46:54 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "add.h"
+
+static char Options[] = "hvIRnp:";
+
+char *Prefix = NULL;
+Boolean NoInstall = FALSE;
+Boolean NoRecord = FALSE;
+
+char *Mode = NULL;
+char *Owner = NULL;
+char *Group = NULL;
+char *PkgName = NULL;
+char *Directory = NULL;
+
+int
+main(int argc, char **argv)
+{
+ int ch, err;
+ char **pkgs, **start;
+ char *prog_name = argv[0];
+
+ pkgs = start = argv;
+ while ((ch = getopt(argc, argv, Options)) != EOF)
+ switch(ch) {
+ case 'v':
+ Verbose = TRUE;
+ break;
+
+ case 'p':
+ Prefix = optarg;
+ break;
+
+ case 'I':
+ NoInstall = TRUE;
+ break;
+
+ case 'R':
+ NoRecord = TRUE;
+ break;
+
+ case 'n':
+ Fake = TRUE;
+ Verbose = TRUE;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ usage(prog_name, NULL);
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Get all the remaining package names, if any */
+ while (*argv)
+ *pkgs++ = *argv++;
+
+ /* If no packages, yelp */
+ if (pkgs == start)
+ usage(prog_name, "Missing package name(s)");
+ *pkgs = NULL;
+ if ((err = pkg_perform(start)) != NULL) {
+ if (Verbose)
+ fprintf(stderr, "%d package addition(s) failed.\n", err);
+ return err;
+ }
+ else
+ return 0;
+}
+
+void
+usage(const char *name, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ if (fmt) {
+ fprintf(stderr, "%s: ", name);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n\n");
+ }
+ va_end(args);
+ fprintf(stderr, "Usage: %s [args] pkg [ .. pkg ]\n", name);
+ fprintf(stderr, "Where args are one or more of:\n\n");
+ fprintf(stderr, "-v verbose\n");
+ fprintf(stderr, "-p arg override prefix with arg\n");
+ fprintf(stderr, "-I don't execute pkg install script, if any\n");
+ fprintf(stderr, "-R don't record installation (can't delete!)\n");
+ fprintf(stderr, "-n don't actually install, just show steps\n");
+ exit(1);
+}
diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c
new file mode 100644
index 000000000000..c86922b5c5e3
--- /dev/null
+++ b/usr.sbin/pkg_install/add/perform.c
@@ -0,0 +1,205 @@
+#ifndef lint
+static const char *rcsid = "$Id: perform.c,v 1.7 1993/08/26 08:46:55 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "add.h"
+
+#include <signal.h>
+
+static int pkg_do(char *);
+static char *find_name(Package *);
+static int sanity_check(char *);
+static char LogDir[FILENAME_MAX];
+
+
+int
+pkg_perform(char **pkgs)
+{
+ int i, err_cnt = 0;
+
+ signal(SIGINT, cleanup);
+ signal(SIGHUP, cleanup);
+
+ for (i = 0; pkgs[i]; i++)
+ err_cnt += pkg_do(pkgs[i]);
+ return err_cnt;
+}
+
+static Package Plist;
+
+/* This is seriously ugly code following. Written very fast! */
+static int
+pkg_do(char *pkg)
+{
+ char pkg_fullname[FILENAME_MAX];
+ FILE *cfile;
+ char *home;
+ int code = 0;
+
+ /* Reset some state */
+ if (Plist.head)
+ free_plist(&Plist);
+ LogDir[0] = '\0';
+ home = make_playpen();
+ if (pkg[0] == '/') /* full pathname? */
+ strcpy(pkg_fullname, pkg);
+ else
+ sprintf(pkg_fullname, "%s/%s", home, pkg);
+ if (!fexists(pkg_fullname)) {
+ whinge("Can't open package '%s'.", pkg_fullname);
+ return 1;
+ }
+
+ if (unpack(pkg_fullname, NULL))
+ return 1;
+
+ if (sanity_check(pkg_fullname))
+ return 1;
+
+ cfile = fopen(CONTENTS_FNAME, "r");
+ if (!cfile) {
+ whinge("Unable to open %s file.", CONTENTS_FNAME);
+ goto fail;
+ }
+ /* If we have a prefix, add it now */
+ if (Prefix)
+ add_plist(&Plist, PLIST_CWD, Prefix);
+ else
+ add_plist(&Plist, PLIST_CWD, home);
+ read_plist(&Plist, cfile);
+ fclose(cfile);
+ PkgName = find_name(&Plist);
+ if (fexists(REQUIRE_FNAME)) {
+ vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */
+ if (Verbose)
+ printf("Running requirements file first for %s..\n", PkgName);
+ if (vsystem("%s %s INSTALL", REQUIRE_FNAME, PkgName)) {
+ whinge("Package %s fails requirements - not installed.",
+ pkg_fullname);
+ goto fail;
+ }
+ }
+ if (!NoInstall && fexists(INSTALL_FNAME)) {
+ vsystem("chmod +x %s", INSTALL_FNAME); /* make sure */
+ if (Verbose)
+ printf("Running install with PRE-INSTALL for %s..\n", PkgName);
+ if (vsystem("%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
+ whinge("Install script returned error status.");
+ goto fail;
+ }
+ }
+ extract_plist(home, &Plist);
+ if (!NoInstall && fexists(INSTALL_FNAME)) {
+ if (Verbose)
+ printf("Running install with POST-INSTALL for %s..\n", PkgName);
+ if (vsystem("%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
+ whinge("Install script returned error status.");
+ goto fail;
+ }
+ }
+ if (!NoRecord && !Fake) {
+ if (getuid() != 0)
+ whinge("Not running as root - trying to record install anyway.");
+ if (!PkgName) {
+ whinge("No package name! Can't record package, sorry.");
+ code = 1;
+ goto success; /* well, partial anyway */
+ }
+ sprintf(LogDir, "%s/%s", LOG_DIR, PkgName);
+ if (Verbose)
+ printf("Attempting to record package into %s..\n", LogDir);
+ if (make_hierarchy(LogDir)) {
+ whinge("Can't record package into '%s', you're on your own!",
+ LogDir);
+ bzero(LogDir, FILENAME_MAX);
+ code = 1;
+ goto success; /* close enough for government work */
+ }
+ if (fexists(DEINSTALL_FNAME))
+ copy_file(".", DEINSTALL_FNAME, LogDir);
+ if (fexists(REQUIRE_FNAME))
+ copy_file(".", REQUIRE_FNAME, LogDir);
+ copy_file(".", CONTENTS_FNAME, LogDir);
+ copy_file(".", DESC_FNAME, LogDir);
+ copy_file(".", COMMENT_FNAME, LogDir);
+ if (Verbose)
+ printf("Package %s registered in %s\n", PkgName, LogDir);
+ }
+ goto success;
+
+ fail:
+ /* Nuke the whole (installed) show */
+ if (!Fake)
+ delete_package(FALSE, &Plist);
+
+ success:
+ /* delete the packing list contents */
+ leave_playpen();
+
+ return code;
+}
+
+static int
+sanity_check(char *pkg)
+{
+ if (!fexists(CONTENTS_FNAME)) {
+ whinge("Package %s has no CONTENTS file!", pkg);
+ return 1;
+ }
+ if (!fexists(COMMENT_FNAME)) {
+ whinge("Package %s has no COMMENT file!", pkg);
+ return 1;
+ }
+ if (!fexists(DESC_FNAME)) {
+ whinge("Package %s has no DESC file!", pkg);
+ return 1;
+ }
+ return 0;
+}
+
+static char *
+find_name(Package *pkg)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ if (p->type == PLIST_NAME)
+ return p->name;
+ p = p->next;
+ }
+ return "anonymous";
+}
+
+void
+cleanup(int signo)
+{
+ if (Plist.head) {
+ if (!Fake)
+ delete_package(FALSE, &Plist);
+ free_plist(&Plist);
+ }
+ if (!Fake && LogDir[0])
+ vsystem("%s -rf %s", REMOVE_CMD, LogDir);
+ leave_playpen();
+}
diff --git a/usr.sbin/pkg_install/add/pkg_add.1 b/usr.sbin/pkg_install/add/pkg_add.1
new file mode 100644
index 000000000000..4e332b72a71f
--- /dev/null
+++ b/usr.sbin/pkg_install/add/pkg_add.1
@@ -0,0 +1,125 @@
+.\"
+.\" 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
+.\"
+.TH pkg_add 1 "July 18, 1993" "" "FreeBSD"
+
+.SH NAME
+pkg_add - a utility for installing software package distributions.
+.SH SYNOPSIS
+.na
+.B pkg_add
+.RB [options]
+.RB "pkg-name\ [.. pkg-name]"
+
+.SH DESCRIPTION
+The
+.B pkg_add
+command is used to extract packages that have been previously created
+with the
+.B pkg_create
+command.
+
+.SH OPTIONS
+.TP
+The following command line options are supported.
+.TP
+.B \-v
+Turns on verbose output.
+.B "Optional."
+.TP
+.B \-I
+If an installation script exists for a given package, do not execute it.
+.B "Optional."
+.TP
+.B \-n
+Don't actually install a package, just report the steps that
+would be taken if it was.
+.B "Optional."
+.TP
+.B \-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!
+.B "Optional."
+.TP
+.BI "\-p\ " prefix
+Sets
+.I prefix
+as the directory in which to extract files from any packages
+which do not explicitly set theirs.
+.B "Optional."
+.PP
+.SH "TECHNICAL DETAILS"
+.B
+pkg_add
+is fairly simple. It simply extracts the requested packages into
+the current working directory and then performs the following steps:
+.PP
+If the package contains a
+.B require
+file (see
+.B pkg_create
+), then this is executed first with the flag
+.b INSTALL
+to see whether or not installation should
+continue (a non-zero exit status means no).
+.PP
+If an
+.B install
+script exists for the package, it is then executed as follows:
+.PP
+First, before installing files in the data set, the
+.B install
+script is called with the flags
+.PP
+.B <script>
+.I pkg-name PRE-INSTALL
+.PP
+Where
+.I pkg-name
+is the name of the package in question and
+.I PRE-INSTALL
+is a keyword denoting that this is the "pre installation" pass.
+Files are then copied from the packing list into their new homes, as expected,
+and the
+.B install
+script is then executed a second time with the flags
+.PP
+.B <script>
+.I pkg-name POST-INSTALL
+.PP
+This all allows you to write an
+.B install
+script that does "before and after" actions.
+.PP
+After installation is complete, a copy of the packing list, in addition
+to any
+.B deinstall
+script the package might have, is copied into /var/pkg/<pkg-name>
+for subsequent possible use by
+.B pkg-delete.
+.PP
+.SH BUGS
+Sure to be some.
+.SH "SEE ALSO"
+.BR pkg_create "(" 1 "),"
+.BR pkg_info "(" 1 "),"
+.BR pkg_delete "(" 1 "),"
+.SH AUTHORS
+Jordan Hubbard
+
diff --git a/usr.sbin/pkg_install/create/Makefile b/usr.sbin/pkg_install/create/Makefile
new file mode 100644
index 000000000000..01e6b20c2c56
--- /dev/null
+++ b/usr.sbin/pkg_install/create/Makefile
@@ -0,0 +1,8 @@
+PROG= pkg_create
+
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD+= -L${.CURDIR}/../lib -linstall
+
+SRCS= main.c perform.c pl.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/create/create.h b/usr.sbin/pkg_install/create/create.h
new file mode 100644
index 000000000000..2e1e73c3644d
--- /dev/null
+++ b/usr.sbin/pkg_install/create/create.h
@@ -0,0 +1,39 @@
+/* $Id: create.h,v 1.3 1993/08/24 09:23:32 jkh 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 *Install;
+extern char *DeInstall;
+extern char *Contents;
+extern char *Require;
+
+void check_list(char *, Package *);
+void usage(const char *, const char *, ...);
+int pkg_perform(char **);
+void copy_plist(char *, Package *);
+
+#endif /* _INST_CREATE_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/create/main.c b/usr.sbin/pkg_install/create/main.c
new file mode 100644
index 000000000000..63f669939678
--- /dev/null
+++ b/usr.sbin/pkg_install/create/main.c
@@ -0,0 +1,125 @@
+#ifndef lint
+static const char *rcsid = "$Id: main.c,v 1.3 1993/08/20 08:52:39 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "create.h"
+
+static char Options[] = "hvf:p:c:d:i:k:r:";
+
+char *Prefix = NULL;
+char *Comment = NULL;
+char *Desc = NULL;
+char *Install = NULL;
+char *DeInstall = NULL;
+char *Contents = NULL;
+char *Require = NULL;
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ char **pkgs, **start;
+ char *prog_name = argv[0];
+
+ pkgs = start = argv;
+ while ((ch = getopt(argc, argv, Options)) != EOF)
+ switch(ch) {
+ case 'v':
+ Verbose = TRUE;
+ break;
+
+ case 'p':
+ Prefix = 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 'r':
+ Require = optarg;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ usage(prog_name, NULL);
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Get all the remaining package names, if any */
+ while (*argv)
+ *pkgs++ = *argv++;
+
+ /* If no packages, yelp */
+ if (pkgs == start)
+ usage(prog_name, "Missing package name");
+ *pkgs = NULL;
+ if (start[1])
+ usage(prog_name, "Only one package name allowed\n\t('%s' extraneous)",
+ start[1]);
+ if (!pkg_perform(start)) {
+ if (Verbose)
+ fprintf(stderr, "Package creation failed.\n");
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void
+usage(const char *name, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ if (fmt) {
+ fprintf(stderr, "%s: ", name);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n\n");
+ }
+ va_end(args);
+ fprintf(stderr, "Usage: %s [args] pkg\n\n", name);
+ fprintf(stderr, "Where args are one or more of:\n\n");
+
+ fprintf(stderr, "-c [-]file Get one-line comment from file (-or arg)\n");
+ fprintf(stderr, "-d [-]file Get description from file (-or arg)\n");
+ fprintf(stderr, "-f file get list of files from file (- for stdin)\n");
+ fprintf(stderr, "-i script install script\n");
+ fprintf(stderr, "-p arg install prefix will be arg\n");
+ fprintf(stderr, "-k script de-install script\n");
+ fprintf(stderr, "-r script pre/post requirements script\n");
+ fprintf(stderr, "-v verbose\n");
+ exit(1);
+}
diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c
new file mode 100644
index 000000000000..634188b00b61
--- /dev/null
+++ b/usr.sbin/pkg_install/create/perform.c
@@ -0,0 +1,165 @@
+#ifndef lint
+static const char *rcsid = "$Id: perform.c,v 1.4 1993/08/26 08:12:52 jkh Exp $";
+#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"
+
+#include <signal.h>
+
+static void sanity_check(void);
+static void make_dist(char *, char *, char *, Package *);
+
+int
+pkg_perform(char **pkgs)
+{
+ char *pkg = *pkgs; /* Only one arg to create */
+ char *home, *cp;
+ FILE *pkg_in, *fp;
+ Package plist;
+ char *suffix; /* What we tack on to the end of the finished package */
+
+ /* Preliminary setup */
+ sanity_check();
+ if (Verbose)
+ printf("Creating package %s\n", pkg);
+ get_dash_string(&Comment);
+ get_dash_string(&Desc);
+ if (!strcmp(Contents, "-"))
+ pkg_in = stdin;
+ else {
+ pkg_in = fopen(Contents, "r");
+ if (!pkg_in)
+ barf("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 = index(pkg, '.')) != NULL) {
+ suffix = cp + 1;
+ *cp = '\0';
+ }
+ else
+ suffix = "tgz";
+
+ /* Register the package name (base part) */
+ add_plist(&plist, PLIST_NAME, pkg);
+ if (Prefix)
+ add_plist(&plist, PLIST_CWD, Prefix);
+
+ /* Slurp in the packing list */
+ read_plist(&plist, pkg_in);
+
+ /* Make a directory to stomp around in */
+ home = make_playpen();
+ signal(SIGINT, cleanup);
+ signal(SIGHUP, cleanup);
+
+ /* Make first "real contents" pass over it */
+ check_list(home, &plist);
+ copy_plist(home, &plist);
+ mark_plist(&plist);
+
+ /* 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);
+ }
+
+ /* Run through the list again, picking up extra "local" items */
+ check_list(".", &plist);
+ copy_plist(".", &plist);
+ mark_plist(&plist);
+
+ /* Finally, write out the packing list */
+ fp = fopen(CONTENTS_FNAME, "w");
+ if (!fp)
+ barf("Can't open file %s for writing.", CONTENTS_FNAME);
+ write_plist(&plist, fp);
+ if (fclose(fp))
+ barf("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);
+ cleanup(0);
+ return TRUE; /* Success */
+}
+
+static void
+make_dist(char *home, char *pkg, char *suffix, Package *plist)
+{
+ char tball[FILENAME_MAX];
+ char args[10];
+
+ sprintf(tball, "%s/%s.%s", home, pkg, suffix);
+ if (index(suffix, 'z')) /* Compress/gzip? */
+ strcpy(args, "z");
+ if (Verbose)
+ printf("Creating gzip'd tar ball in '%s', contents:\n", tball);
+ strcat(args, "cf");
+ if (vsystem("tar %s %s .", args, tball))
+ barf("tar command failed!");
+}
+
+static void
+sanity_check()
+{
+ if (!Comment)
+ barf("Required package comment string is missing (-c comment).");
+ if (!Desc)
+ barf("Required package description string is missing (-d desc).");
+ if (!Contents)
+ barf("Required package contents list is missing (-f [-]file).");
+}
+
+
+/* Clean up those things that would otherwise hang around */
+void
+cleanup(int sig)
+{
+ leave_playpen();
+}
diff --git a/usr.sbin/pkg_install/create/pkg_create.1 b/usr.sbin/pkg_install/create/pkg_create.1
new file mode 100644
index 000000000000..dd0e967714a4
--- /dev/null
+++ b/usr.sbin/pkg_install/create/pkg_create.1
@@ -0,0 +1,185 @@
+.\"
+.\" 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
+.\"
+.TH pkg_create 1 "July 18, 1993" "" "FreeBSD"
+
+.SH NAME
+pkg_create - a utility for creating software package distributions.
+.SH SYNOPSIS
+.na
+.B pkg_create
+.RB [options]
+.RB pkg-name
+
+.SH DESCRIPTION
+The
+.B pkg_create
+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
+.TP
+The following command line options are supported.
+.TP
+.B \-v
+Turns on verbose output.
+.B "Optional."
+.TP
+.BI "\-c\ " [-]desc
+Fetch package "one line description" from file
+.I desc
+or, if preceeded by
+.B -
+, the argument itself. This string should also
+give some idea of which version of the product (if any) the package
+represents.
+.B "Mandatory."
+.TP
+.BI "\-d\ " [-]desc
+Fetch long description for package from file
+.I desc
+or, if preceeded by
+.B -
+, the argument itself.
+.B "Mandatory."
+.TP
+.BI "\-f\ " file
+Fetch "packing list" for package from
+.I file
+or
+.B stdin
+if
+.I file
+is a
+.B -
+(dash).
+.B "Mandatory."
+.TP
+.BI "\-i\ " script
+Sets
+.I script
+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.
+.B "Optional."
+.TP
+.BI "\-p\ " prefix
+Sets
+.I prefix
+As the initial directory "base" to start from in selecting files for
+the package.
+.B "Optional."
+.TP
+.BI "\-k\ " script
+Sets
+.I script
+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.
+.B "Optional."
+.TP
+.BI "\-r\ " script
+Sets
+.I script
+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.
+.B "Optional."
+.PP
+.SH "TECHNICAL DETAILS"
+The "packing list" format (see \fB-f\fR) 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 imbeding specialized command sequences
+in the packing list. Briefly described, these sequences are:
+.TP
+.BI "@cwd\ " directory
+Sets the internal directory pointer to point to
+.I directory.
+All subsequent filenames will be assumed relative to this directory.
+.TP
+.BI "@exec\ " command
+Execute
+.I command
+as part of the unpacking process. If
+.I command
+contains a `%s' sequence somewhere in it, it will be expanded to
+the name of the last filename extracted. In practice, such
+weird things should be unnecessary in all but the most extenuating
+circumstances, but it's there should you need it nonetheless.
+.TP
+.BI "@mode\ " mode
+Sets default permission for all subsequently extracted files to
+.I mode.
+Format is the same as that used by the
+.B 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.
+.TP
+.BI "@owner\ " user
+Sets default ownership for all subsequently extracted files to
+.I user.
+Use without an arg to set back to default (extraction)
+ownership.
+.TP
+.BI "@group\ " group
+Sets default group ownership for all subsequently extracted files to
+.I group.
+Use without an arg to set back to default (extraction)
+group ownership.
+.TP
+.BI "@comment\ " string
+Imbed a comment in the packing list. Useful in
+trying to document some particularly hairy sequence that
+may trip someone up later.
+.TP
+.BI "@ignore\ " file
+Used internally to tell extraction to ignore the next file (don't
+copy it anywhere), as it's used for some special purpose. Also useful
+if you want to pack some specialized datafiles in with a distribution
+for your install script (or something) and want to have the installer
+ignore it.
+.TP
+.BI "@name\ " name
+Sets 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
+.B pkg_create
+currently derives this field from the package name and adds it
+automatically.
+
+.SH BUGS
+Sure to be some.
+.SH "SEE ALSO"
+.BR pkg_add "(" 1 "),"
+.BR pkg_info "(" 1 "),"
+.BR pkg_delete "(" 1 "),"
+.SH AUTHORS
+Jordan Hubbard
+
diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c
new file mode 100644
index 000000000000..3b9a2d048388
--- /dev/null
+++ b/usr.sbin/pkg_install/create/pl.c
@@ -0,0 +1,104 @@
+#ifndef lint
+static const char *rcsid = "$Id: pl.c,v 1.4 1993/08/26 08:12:53 jkh Exp $";
+#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"
+
+#define QUERY_GZIP \
+"File '%s' appears to be gzip'd.\nWould you like to unpack it first"
+#define UNZIP "gzip -d %s"
+
+#define QUERY_COMPRESS \
+"File '%s' appears to be compressed.\nWould you like to unpack it first"
+#define UNCOMPRESS "compress -d %s"
+
+/* Check a list for files that require preconversion */
+void
+check_list(char *home, Package *pkg)
+{
+ char cmd[FILENAME_MAX];
+ char name[FILENAME_MAX];
+ char *where = home;
+ PackingList p = pkg->head;
+
+ while (p) {
+ if (p->type == PLIST_CWD)
+ where = p->name;
+ else if (p->type == PLIST_IGNORE)
+ p = p->next;
+ else if (p->type == PLIST_FILE) {
+ cmd[0] = '\0';
+ sprintf(name, "%s/%s", where, p->name);
+ /* gzip? */
+ if ((suffix(name, "gz") || suffix(name, "z")) &&
+ y_or_n(TRUE, QUERY_GZIP, name))
+ sprintf(cmd, UNZIP, name);
+
+ /* Compress? */
+ else if (suffix(name, "Z") && y_or_n(TRUE, QUERY_COMPRESS, name))
+ sprintf(cmd, UNCOMPRESS, name);
+
+ if (*cmd) {
+ if (Verbose)
+ printf("Uncompressing-> %s\n", cmd);
+ if (system(cmd))
+ barf("%s failed!", cmd);
+ nuke_suffix(p->name);
+ }
+ }
+ p = p->next;
+ }
+}
+
+/*
+ * Copy unmarked files in packing list to playpen - marked files
+ * have already been copied in an earlier pass through the list.
+ */
+void
+copy_plist(char *home, Package *plist)
+{
+ PackingList p = plist->head;
+ char *where = home;
+
+ while (p) {
+ if (p->type == PLIST_CWD)
+ where = p->name;
+ else if (p->type == PLIST_IGNORE)
+ p = p->next;
+ else if (p->type == PLIST_FILE && !p->marked) {
+ char fn[FILENAME_MAX];
+
+ /* First, look for it in the "home" dir */
+ sprintf(fn, "%s/%s", home, p->name);
+ if (fexists(fn))
+ copy_hierarchy(home, p->name, FALSE);
+ /*
+ * Otherwise, try along the actual extraction path..
+ */
+ else
+ copy_hierarchy(where, p->name, FALSE);
+ }
+ p = p->next;
+ }
+}
diff --git a/usr.sbin/pkg_install/delete/Makefile b/usr.sbin/pkg_install/delete/Makefile
new file mode 100644
index 000000000000..16a110f92a26
--- /dev/null
+++ b/usr.sbin/pkg_install/delete/Makefile
@@ -0,0 +1,8 @@
+PROG= pkg_delete
+
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD+= -L${.CURDIR}/../lib -linstall
+
+SRCS= main.c perform.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/delete/delete.h b/usr.sbin/pkg_install/delete/delete.h
new file mode 100644
index 000000000000..2828cdf3d327
--- /dev/null
+++ b/usr.sbin/pkg_install/delete/delete.h
@@ -0,0 +1,31 @@
+/* $Id$ */
+
+/*
+ * 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 Boolean NoDeInstall;
+extern char *Directory;
+extern char *PkgName;
+
+#endif /* _INST_DELETE_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/delete/main.c b/usr.sbin/pkg_install/delete/main.c
new file mode 100644
index 000000000000..63bc65da0128
--- /dev/null
+++ b/usr.sbin/pkg_install/delete/main.c
@@ -0,0 +1,108 @@
+#ifndef lint
+static char *rcsid = "$Id: main.c,v 1.4 1993/08/26 08:47:02 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "delete.h"
+
+static char Options[] = "hvDnp:";
+
+char *Prefix = NULL;
+Boolean NoDeInstall = FALSE;
+
+int
+main(int argc, char **argv)
+{
+ int ch, err;
+ char **pkgs, **start;
+ char *prog_name = argv[0];
+
+ pkgs = start = argv;
+ while ((ch = getopt(argc, argv, Options)) != EOF)
+ switch(ch) {
+ case 'v':
+ Verbose = TRUE;
+ break;
+
+ case 'p':
+ Prefix = optarg;
+ break;
+
+ case 'D':
+ NoDeInstall = TRUE;
+ break;
+
+ case 'n':
+ Fake = TRUE;
+ Verbose = TRUE;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ usage(prog_name, NULL);
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Get all the remaining package names, if any */
+ /* Get all the remaining package names, if any */
+ while (*argv)
+ *pkgs++ = *argv++;
+
+ /* If no packages, yelp */
+ if (pkgs == start)
+ usage(prog_name, "Missing package name(s)");
+ *pkgs = NULL;
+ if ((err = pkg_perform(start)) != NULL) {
+ if (Verbose)
+ fprintf(stderr, "%d package deletion(s) failed.\n", err);
+ return err;
+ }
+ else
+ return 0;
+}
+
+void
+usage(const char *name, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ if (fmt) {
+ fprintf(stderr, "%s: ", name);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n\n");
+ }
+ va_end(args);
+ fprintf(stderr, "Usage: %s [args] pkg [ .. pkg ]\n", name);
+ fprintf(stderr, "Where args are one or more of:\n\n");
+ fprintf(stderr, "-v verbose\n");
+ fprintf(stderr, "-p arg override prefix with arg\n");
+ fprintf(stderr, "-D don't execute pkg de-install script, if any\n");
+ fprintf(stderr, "-n don't actually de-install, just show steps\n");
+ exit(1);
+}
diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c
new file mode 100644
index 000000000000..2694a0ac125f
--- /dev/null
+++ b/usr.sbin/pkg_install/delete/perform.c
@@ -0,0 +1,119 @@
+#ifndef lint
+static const char *rcsid = "$Id: perform.c,v 1.1 1993/08/20 08:53:36 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "delete.h"
+
+static int pkg_do(char *);
+static void sanity_check(char *);
+static char LogDir[FILENAME_MAX];
+
+
+int
+pkg_perform(char **pkgs)
+{
+ int i, err_cnt = 0;
+
+ for (i = 0; pkgs[i]; i++)
+ err_cnt += pkg_do(pkgs[i]);
+ return err_cnt;
+}
+
+static Package Plist;
+
+/* This is seriously ugly code following. Written very fast! */
+static int
+pkg_do(char *pkg)
+{
+ FILE *cfile;
+ char home[FILENAME_MAX];
+
+ /* Reset some state */
+ if (Plist.head)
+ free_plist(&Plist);
+
+ sprintf(LogDir, "%s/%s", LOG_DIR, pkg);
+ if (!fexists(LogDir)) {
+ whinge("No such package '%s' installed.", pkg);
+ return 1;
+ }
+ if (!getcwd(home, FILENAME_MAX))
+ barf("Unable to get current working directory!");
+ if (chdir(LogDir) == FAIL) {
+ whinge("Unable to change directory to %s! Deinstall failed.", LogDir);
+ return 1;
+ }
+ sanity_check(LogDir);
+ if (fexists(REQUIRE_FNAME)) {
+ if (Verbose)
+ printf("Executing 'require' script.\n");
+ vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */
+ if (vsystem("%s %s DEINSTALL", REQUIRE_FNAME, pkg)) {
+ whinge("Package %s fails requirements - not deleted.", pkg);
+ return 1;
+ }
+ }
+ cfile = fopen(CONTENTS_FNAME, "r");
+ if (!cfile) {
+ whinge("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);
+ if (!NoDeInstall && fexists(DEINSTALL_FNAME)) {
+ if (Fake)
+ printf("Would execute de-install script at this point.\n");
+ else {
+ vsystem("chmod +x %s", DEINSTALL_FNAME); /* make sure */
+ if (vsystem("%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) {
+ whinge("De-Install script returned error status.");
+ return 1;
+ }
+ }
+ }
+ if (chdir(home) == FAIL)
+ barf("Toto! This doesn't look like Kansas anymore!");
+ delete_package(FALSE, &Plist);
+ if (!Fake && vsystem("%s -r %s", REMOVE_CMD, LogDir)) {
+ whinge("Couldn't remove log entry in %s, de-install failed.", LogDir);
+ return 1;
+ }
+ return 0;
+}
+
+static void
+sanity_check(char *pkg)
+{
+ if (!fexists(CONTENTS_FNAME))
+ barf("Installed package %s has no %s file!", pkg, CONTENTS_FNAME);
+}
+
+void
+cleanup(int sig)
+{
+ /* Nothing to do */
+}
diff --git a/usr.sbin/pkg_install/delete/pkg_delete.1 b/usr.sbin/pkg_install/delete/pkg_delete.1
new file mode 100644
index 000000000000..d9da7f1f9866
--- /dev/null
+++ b/usr.sbin/pkg_install/delete/pkg_delete.1
@@ -0,0 +1,107 @@
+.\"
+.\" 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_delete.1
+.\"
+.TH pkg_delete 1 "July 18, 1993" "" "FreeBSD"
+
+.SH NAME
+pkg_delete - a utility for deleting previously installed software package distributions.
+.SH SYNOPSIS
+.na
+.B pkg_delete
+.RB [options]
+.RB "pkg-name\ [.. pkg-name]"
+
+.SH DESCRIPTION
+The
+.B pkg_delete
+command is used to delete packages that have been previously installed
+with the
+.B pkg_add
+command.
+
+.SH OPTIONS
+.TP
+The following command line options are supported.
+.TP
+.B \-v
+Turns on verbose output.
+.B "Optional."
+.TP
+.B \-D
+If an de-installation script exists for a given package, do not execute it.
+.B "Optional."
+.TP
+.B \-n
+Don't actually de-install a package, just report the steps that
+would be taken if it was.
+.B "Optional."
+.TP
+.BI "\-p\ " prefix
+Sets
+.I prefix
+as the directory in which to delete files from any installed packages
+which do not explicitly set theirs.
+.B "Optional."
+.PP
+.SH "TECHNICAL DETAILS"
+.B
+pkg_delete
+does pretty much what it says. It looks for a package in /var/db/pkg
+and sets about deleting the files that make up the package and, finally,
+the record of the package itself.
+.PP
+If the package contains a
+.B require
+file (see
+.B pkg_create
+), then this is executed first with the flag
+.B DEINSTALL
+to see whether or not de-installation should continue (a non-zero exit
+status means no).
+.PP
+If a
+.B de-install
+script exists for the package, it is executed before any files are removed.
+It is this script's responsibility to clean up any additional messy details
+around the package's installation, since all
+.B pkg_delete
+knows how to do is delete the files created in the original distribution.
+The
+.B de-install
+script is called with the flags
+.PP
+.B <script>
+.I pkg-name DEINSTALL
+.PP
+Where
+.I pkg-name
+is the name of the package in question and
+.I DEINSTALL
+is a keyword denoting that this is a deinstallation. Passing the keyword
+lets you potentially write only one program/script that handles all
+aspects of installation and deletion.
+.PP
+.SH BUGS
+Sure to be some.
+.SH "SEE ALSO"
+.BR pkg_create "(" 1 "),"
+.BR pkg_info "(" 1 "),"
+.BR pkg_add "(" 1 "),"
+.SH AUTHORS
+Jordan Hubbard
+
diff --git a/usr.sbin/pkg_install/info/Makefile b/usr.sbin/pkg_install/info/Makefile
new file mode 100644
index 000000000000..2b4f04e0d7ac
--- /dev/null
+++ b/usr.sbin/pkg_install/info/Makefile
@@ -0,0 +1,8 @@
+PROG= pkg_info
+
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD+= -L${.CURDIR}/../lib -linstall
+
+SRCS= main.c perform.c show.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/info/info.h b/usr.sbin/pkg_install/info/info.h
new file mode 100644
index 000000000000..9584afb04cb2
--- /dev/null
+++ b/usr.sbin/pkg_install/info/info.h
@@ -0,0 +1,41 @@
+/* $Id: info.h,v 1.3 1993/08/26 08:47:04 jkh 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
+
+#define SHOW_COMMENT 0x1
+#define SHOW_DESC 0x2
+#define SHOW_PLIST 0x4
+#define SHOW_INSTALL 0x8
+#define SHOW_DEINSTALL 0x10
+#define SHOW_REQUIRE 0x20
+#define SHOW_PREFIX 0x40
+#define SHOW_INDEX 0x80
+
+extern int Flags;
+extern Boolean AllInstalled;
+
+extern void show_file(char *, char *);
+extern void show_plist(char *, Package *, plist_t);
+
+#endif /* _INST_INFO_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/info/main.c b/usr.sbin/pkg_install/info/main.c
new file mode 100644
index 000000000000..9a5e540ae81a
--- /dev/null
+++ b/usr.sbin/pkg_install/info/main.c
@@ -0,0 +1,138 @@
+#ifndef lint
+static char *rcsid = "$Header: /usr1/cvs/jkh/pkg_install/info/main.c,v 1.4 1993/08/26 08:47:05 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "info.h"
+
+static char Options[] = "acdfikrpIvh";
+
+int Flags = 0;
+Boolean AllInstalled = FALSE;
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ char **pkgs, **start;
+ char *prog_name = argv[0];
+
+ pkgs = start = argv;
+ while ((ch = getopt(argc, argv, Options)) != EOF)
+ switch(ch) {
+ case 'a':
+ AllInstalled = TRUE;
+ break;
+
+ case 'v':
+ Verbose = TRUE;
+ /* Reasonable definition of 'everything' */
+ Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
+ SHOW_DEINSTALL | SHOW_REQUIRE;
+ break;
+
+ case 'I':
+ Flags |= SHOW_INDEX;
+ break;
+
+ case 'p':
+ Flags |= SHOW_PREFIX;
+ break;
+
+ case 'c':
+ Flags |= SHOW_COMMENT;
+ break;
+
+ case 'd':
+ Flags |= SHOW_DESC;
+ break;
+
+ case 'f':
+ Flags |= SHOW_PLIST;
+ break;
+
+ case 'i':
+ Flags |= SHOW_INSTALL;
+ break;
+
+ case 'k':
+ Flags |= SHOW_DEINSTALL;
+ break;
+
+ case 'r':
+ Flags |= SHOW_REQUIRE;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ usage(prog_name, NULL);
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Set some reasonable defaults */
+ if (!Flags)
+ Flags = SHOW_COMMENT | SHOW_DESC;
+
+ /* Get all the remaining package names, if any */
+ while (*argv)
+ *pkgs++ = *argv++;
+
+ /* If no packages, yelp */
+ if (pkgs == start && !AllInstalled)
+ usage(prog_name, "Missing package name(s)");
+ *pkgs = NULL;
+ return pkg_perform(start);
+}
+
+void
+usage(const char *name, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ if (fmt) {
+ fprintf(stderr, "%s: ", name);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n\n");
+ }
+ va_end(args);
+ fprintf(stderr, "Usage: %s [args] pkg [ .. pkg ]\n", name);
+ fprintf(stderr, "Where args are one or more of:\n\n");
+ fprintf(stderr, "-a show all installed packages (if any)\n");
+ fprintf(stderr, "-I print 'index' of packages\n");
+ fprintf(stderr, "-c print `one line comment'\n");
+ fprintf(stderr, "-d print description\n");
+ fprintf(stderr, "-f show packing list\n");
+ fprintf(stderr, "-i show install script\n");
+ fprintf(stderr, "-k show deinstall script\n");
+ fprintf(stderr, "-r show requirements script\n");
+ fprintf(stderr, "-p show prefix\n");
+ fprintf(stderr, "-v show all information\n");
+ fprintf(stderr, "\n[no args = -c -d]\n");
+ exit(1);
+}
diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c
new file mode 100644
index 000000000000..3a3842186c0e
--- /dev/null
+++ b/usr.sbin/pkg_install/info/perform.c
@@ -0,0 +1,144 @@
+#ifndef lint
+static const char *rcsid = "$Id: perform.c,v 1.3 1993/08/26 08:47:06 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "info.h"
+
+#include <signal.h>
+
+static int pkg_do(char *);
+
+int
+pkg_perform(char **pkgs)
+{
+ int i, err_cnt = 0;
+
+ signal(SIGINT, cleanup);
+
+ /* Overriding action? */
+ if (AllInstalled) {
+ if (isdir(LOG_DIR)) {
+ DIR *dirp;
+ struct dirent *dp;
+
+ dirp = opendir(LOG_DIR);
+ if (dirp) {
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, ".."))
+ err_cnt += pkg_do(dp->d_name);
+ }
+ (void)closedir(dirp);
+ }
+ else
+ ++err_cnt;
+ }
+ }
+ for (i = 0; pkgs[i]; i++)
+ err_cnt += pkg_do(pkgs[i]);
+ return err_cnt;
+}
+
+static int
+pkg_do(char *pkg)
+{
+ Boolean installed = FALSE;
+ char log_dir[FILENAME_MAX];
+ char *home;
+ Package plist;
+ FILE *fp;
+
+ if (fexists(pkg)) {
+ char fname[FILENAME_MAX];
+
+ home = make_playpen();
+ if (pkg[0] == '/')
+ strcpy(fname, pkg);
+ else
+ sprintf(fname, "%s/%s", home, pkg);
+ if (unpack(fname, "+*")) {
+ whinge("Error during unpacking, no info for '%s' available.", pkg);
+ return 1;
+ }
+ }
+ else {
+ sprintf(log_dir, "%s/%s", LOG_DIR, pkg);
+ if (!fexists(log_dir)) {
+ whinge("Can't find package '%s' installed or in a file!", pkg);
+ return 1;
+ }
+ if (chdir(log_dir) == FAIL) {
+ whinge("Can't change directory to '%s'!", log_dir);
+ return 1;
+ }
+ installed = TRUE;
+ }
+
+ /* Suck in the contents list */
+ plist.head = plist.tail = NULL;
+ fp = fopen(CONTENTS_FNAME, "r");
+ if (!fp) {
+ whinge("Unable to open %s file.", CONTENTS_FNAME);
+ return 1;
+ }
+ /* If we have a prefix, add it now */
+ read_plist(&plist, fp);
+ fclose(fp);
+
+ /*
+ * Index is special info type that has to override all others to make
+ * any sense.
+ */
+ if (Flags & SHOW_INDEX) {
+ char fname[FILENAME_MAX];
+
+ sprintf(fname, "%s\t", pkg);
+ show_file(fname, COMMENT_FNAME);
+ }
+ else {
+ /* Start showing the package contents */
+ printf(" Information for %s:\n\n", pkg);
+ if (Flags & SHOW_COMMENT)
+ show_file(" Comment:\n", COMMENT_FNAME);
+ if (Flags & SHOW_DESC)
+ show_file(" Description:\n", DESC_FNAME);
+ if (Flags & SHOW_PLIST)
+ show_plist(" Packing list:\n", &plist, (plist_t)-1);
+ if ((Flags & SHOW_INSTALL) && fexists(INSTALL_FNAME))
+ show_file(" Install script:\n", INSTALL_FNAME);
+ if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME))
+ show_file(" De-Install script:\n", DEINSTALL_FNAME);
+ if (Flags & SHOW_PREFIX)
+ show_plist(" Prefix(s):\n", &plist, PLIST_CWD);
+ putchar('\014');
+ }
+ free_plist(&plist);
+ leave_playpen();
+ return 0;
+}
+
+void
+cleanup(int sig)
+{
+ leave_playpen();
+}
diff --git a/usr.sbin/pkg_install/info/pkg_info.1 b/usr.sbin/pkg_install/info/pkg_info.1
new file mode 100644
index 000000000000..d74c1ffbca40
--- /dev/null
+++ b/usr.sbin/pkg_install/info/pkg_info.1
@@ -0,0 +1,78 @@
+.\"
+.\" 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
+.\"
+.TH pkg_info 1 "July 18, 1993" "" "FreeBSD"
+
+.SH NAME
+pkg_info - a utility for getting information on software package distributions.
+.SH SYNOPSIS
+.na
+.B pkg_info
+.RB [options]
+.RB "pkg-file|pkg-name\ [.. pkg-file|pkg-name]"
+
+.SH DESCRIPTION
+The
+.B pkg_info
+command is used to dump out information for packages, either packed up in
+files or already installed on the system
+with the
+.B pkg_create
+command.
+
+.SH OPTIONS
+.TP
+The following command line options are supported.
+.TP
+.B \-a
+Show all currently installed packages.
+.TP
+.B \-v
+Turns on verbose output.
+.TP
+.B \-p
+Show the installation prefix for each package.
+.TP
+.B \-c
+Show the comment (one liner) field for each package.
+.TP
+.B \-d
+Show the long description field for each package.
+.TP
+.B \-i
+Show the install script (if any) for each package.
+.TP
+.B \-k
+Show the de-install script (if any) for each package.
+.TP
+.B \-r
+Show the requirements script (if any) for each package.
+.PP
+.SH "TECHNICAL DETAILS"
+Package info is either extracted from files supplied on the
+command line, or from already installed package information
+in /var/db/pkg/<pkg-name>.
+.SH BUGS
+Sure to be some.
+.SH "SEE ALSO"
+.BR pkg_add "(" 1 "),"
+.BR pkg_create "(" 1 "),"
+.BR pkg_delete "(" 1 "),"
+.SH AUTHORS
+Jordan Hubbard
+
diff --git a/usr.sbin/pkg_install/info/show.c b/usr.sbin/pkg_install/info/show.c
new file mode 100644
index 000000000000..8e73e88fe100
--- /dev/null
+++ b/usr.sbin/pkg_install/info/show.c
@@ -0,0 +1,110 @@
+#ifndef lint
+static const char *rcsid = "$Id: show.c,v 1.3 1993/08/26 08:47:07 jkh Exp $";
+#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.
+ *
+ */
+
+#include "lib.h"
+#include "info.h"
+
+void
+show_file(char *title, char *fname)
+{
+ FILE *fp;
+ char line[1024];
+ int n;
+
+ printf(title);
+ fp = fopen(fname, "r");
+ if (!fp) {
+ whinge("show_file: Can't open '%s' for reading.", fname);
+ return;
+ }
+ while (n = fread(line, 1, 1024, fp))
+ fwrite(line, 1, n, stdout);
+ fclose(fp);
+ printf("\n"); /* just in case */
+}
+
+/* Show a packing list item type. If type is -1, show all */
+void
+show_plist(char *title, Package *plist, plist_t type)
+{
+ PackingList p;
+ Boolean ign = FALSE;
+
+ printf(title);
+ p = plist->head;
+ while (p) {
+ if (p->type != type && type != -1) {
+ p = p->next;
+ continue;
+ }
+ switch(p->type) {
+ case PLIST_FILE:
+ if (ign) {
+ printf("File: %s (ignored)\n", p->name);
+ ign = FALSE;
+ }
+ else
+ printf("File: %s\n", p->name);
+ break;
+
+ case PLIST_CWD:
+ printf("\tCWD to %s\n", p->name);
+ break;
+
+ case PLIST_CMD:
+ printf("\tEXEC '%s'\n", p->name);
+ break;
+
+ case PLIST_CHMOD:
+ printf("\tCHMOD to %s\n", p->name ? p->name : "(no default)");
+ break;
+
+ case PLIST_CHOWN:
+ printf("\tCHOWN to %s\n", p->name ? p->name : "(no default)");
+ break;
+
+ case PLIST_CHGRP:
+ printf("\tCHGRP to %s\n", p->name ? p->name : "(no default)");
+ break;
+
+ case PLIST_COMMENT:
+ printf("\tComment: %s\n", p->name);
+ break;
+
+ case PLIST_IGNORE:
+ ign = TRUE;
+ break;
+
+ case PLIST_NAME:
+ printf("\tPackage name: %s\n", p->name);
+ break;
+
+ default:
+ barf("Unknown command type %d (%s)\n", p->type, p->name);
+ break;
+ }
+ p = p->next;
+ }
+}
+
diff --git a/usr.sbin/pkg_install/lib/Makefile b/usr.sbin/pkg_install/lib/Makefile
new file mode 100644
index 000000000000..72da09860554
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/Makefile
@@ -0,0 +1,9 @@
+LIB= install
+SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c
+NOPROFILE= yes
+CFLAGS+= -g -Wall
+
+install:
+ @echo -n
+
+.include <bsd.lib.mk>
diff --git a/usr.sbin/pkg_install/lib/exec.c b/usr.sbin/pkg_install/lib/exec.c
new file mode 100644
index 000000000000..6f1a67299b36
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/exec.c
@@ -0,0 +1,48 @@
+#ifndef lint
+static const char *rcsid = "$Id: exec.c,v 1.3 1993/08/24 09:24:04 jkh Exp $";
+#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.
+ *
+ */
+
+#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[FILENAME_MAX * 2]; /* reasonable default for what I do */
+ int ret;
+
+ va_start(args, fmt);
+ vsprintf(cmd, fmt, args);
+#ifdef DEBUG
+printf("Executing %s\n", cmd);
+#endif
+ ret = system(cmd);
+ va_end(args);
+ return ret;
+}
+
diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c
new file mode 100644
index 000000000000..ac7e4d7ac819
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/file.c
@@ -0,0 +1,164 @@
+#ifndef lint
+static const char *rcsid = "$Id: file.c,v 1.5 1993/08/26 08:13:48 jkh Exp $";
+#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"
+
+/* Quick check to see if a file exists */
+Boolean
+fexists(char *fname)
+{
+ if (!access(fname, F_OK))
+ return TRUE;
+ return FALSE;
+}
+
+/* Quick check to see if something is a directory */
+Boolean
+isdir(char *fname)
+{
+ struct stat sb;
+
+ if (stat(fname, &sb) != FAIL &&
+ (sb.st_mode & S_IFDIR))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Check to see if file is a dir, and is empty */
+Boolean
+isempty(char *fname)
+{
+ if (isdir(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;
+}
+
+char *
+get_file_contents(char *fname)
+{
+ char *contents;
+ struct stat sb;
+ int fd;
+
+ if (stat(fname, &sb) == FAIL)
+ barf("Can't stat '%s'.", fname);
+
+ contents = (char *)malloc(sb.st_size + 1);
+ fd = open(fname, O_RDONLY, 0);
+ if (fd == FAIL)
+ barf("Unable to open '%s' for reading.", fname);
+ if (read(fd, contents, sb.st_size) != sb.st_size)
+ barf("Short read on '%s' - did not get %d bytes.", fname, sb.st_size);
+ close(fd);
+ contents[sb.st_size] = '\0';
+ return contents;
+}
+
+/* Write the contents of "str" to a file */
+void
+write_file(char *name, char *str)
+{
+ FILE *fp;
+ int len;
+
+ fp = fopen(name, "w");
+ if (!fp)
+ barf("Can't fopen '%s' for writing.", name);
+ len = strlen(str);
+ if (fwrite(str, 1, len, fp) != len)
+ barf("Short fwrite on '%s', tried to write %d bytes.", name, len);
+ if (fclose(fp))
+ barf("failure to fclose '%s'.", name);
+}
+
+void
+copy_file(char *dir, char *fname, char *to)
+{
+ if (vsystem("cp -p -r %s/%s %s", dir, fname, to))
+ barf("Couldn't copy %s/%s to %s!", dir, fname, to);
+}
+
+/*
+ * Copy a hierarchy (possibly from dir) to the current directory, or
+ * if "to" is TRUE, from the current directory to a location someplace
+ * else.
+ *
+ * Though slower, using tar to copy preserves symlinks and everything
+ * without me having to write some big hairy routine to do it.
+ */
+void
+copy_hierarchy(char *dir, char *fname, Boolean to)
+{
+ char cmd[FILENAME_MAX * 3];
+
+ if (!to) {
+ /* If absolute path, use it */
+ if (*fname == '/')
+ dir = "/";
+ sprintf(cmd, "tar cf - -C %s %s | tar xpf -", dir, fname);
+ }
+ else
+ sprintf(cmd, "tar cf - %s | tar xpf - -C %s", fname, dir);
+ if (system(cmd))
+ barf("copy_file: Couldn't perform '%s'", cmd);
+}
+
+/* Unpack a tar file */
+int
+unpack(char *pkg, char *flist)
+{
+ char args[10], suffix[80], *cp;
+
+ /*
+ * Figure out by a crude heuristic whether this or not this is probably
+ * compressed.
+ */
+ cp = rindex(pkg, '.');
+ if (cp) {
+ strcpy(suffix, cp + 1);
+ if (index(suffix, 'z') || index(suffix, 'Z'))
+ strcpy(args, "z");
+ }
+ strcat(args, "xpf");
+ if (vsystem("tar %s %s %s", args, pkg, flist ? flist : "")) {
+ whinge("Tar extract of %s failed!", pkg);
+ return 1;
+ }
+ return 0;
+}
diff --git a/usr.sbin/pkg_install/lib/global.c b/usr.sbin/pkg_install/lib/global.c
new file mode 100644
index 000000000000..f5eda0e31917
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/global.c
@@ -0,0 +1,31 @@
+#ifndef lint
+static const char *rcsid = "$Id$";
+#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 two are global for all utils */
+Boolean Verbose = FALSE;
+Boolean Fake = FALSE;
+
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
new file mode 100644
index 000000000000..05d43e7f54ae
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -0,0 +1,143 @@
+/* $Id: lib.h,v 1.4 1993/08/24 09:24:07 jkh 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_
+
+/* Includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+
+/* Macros */
+#define SUCCESS (0)
+#define FAIL (-1)
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+/* Usually "rm", but often "echo" during debugging! */
+#define REMOVE_CMD "rm"
+
+/* Usually "rm", but often "echo" during debugging! */
+#define RMDIR_CMD "rmdir"
+
+/* Where we put logging information */
+#define LOG_DIR "/var/db/pkg"
+
+/* 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 CMD_CHAR '@' /* prefix for extended PLIST cmd */
+
+enum _plist_t {
+ PLIST_FILE, PLIST_CWD, PLIST_CMD, PLIST_CHMOD,
+ PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT,
+ PLIST_IGNORE, PLIST_NAME
+};
+typedef enum _plist_t plist_t;
+
+/* Types */
+typedef unsigned int Boolean;
+
+struct _plist {
+ struct _plist *prev, *next;
+ char *name;
+ Boolean marked;
+ plist_t type;
+};
+typedef struct _plist *PackingList;
+
+struct _pack {
+ struct _plist *head, *tail;
+};
+typedef struct _pack Package;
+
+/* Prototypes */
+/* Misc */
+int vsystem(const char *, ...);
+void cleanup(int);
+char *make_playpen(void);
+void leave_playpen(void);
+
+/* String */
+char *get_dash_string(char **);
+char *copy_string(char *);
+Boolean suffix(char *, char *);
+void nuke_suffix(char *);
+void str_lowercase(char *);
+
+/* File */
+Boolean fexists(char *);
+Boolean isdir(char *);
+Boolean isempty(char *);
+char *get_file_contents(char *);
+void write_file(char *, char *);
+void copy_file(char *, char *, char *);
+void copy_hierarchy(char *, char *, Boolean);
+int delete_hierarchy(char *, Boolean);
+int unpack(char *, char *);
+
+/* Msg */
+void upchuck(const char *);
+void barf(const char *, ...);
+void whinge(const char *, ...);
+Boolean y_or_n(Boolean, const char *, ...);
+
+/* Packing list */
+PackingList new_plist_entry(void);
+PackingList last_plist(Package *);
+void free_plist(Package *);
+void mark_plist(Package *);
+void csum_plist_entry(char *, PackingList);
+void add_plist(Package *, int, char *);
+void write_plist(Package *, FILE *);
+void read_plist(Package *, FILE *);
+int plist_cmd(char *, char **);
+void delete_package(Boolean, Package *);
+
+/* For all */
+void usage(const char *, const char *, ...);
+int pkg_perform(char **);
+
+/* Externs */
+extern Boolean Verbose;
+extern Boolean Fake;
+
+#endif /* _INST_LIB_LIB_H_ */
diff --git a/usr.sbin/pkg_install/lib/msg.c b/usr.sbin/pkg_install/lib/msg.c
new file mode 100644
index 000000000000..4c742907cb3a
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/msg.c
@@ -0,0 +1,97 @@
+#ifndef lint
+static const char *rcsid = "$Id: msg.c,v 1.2 1993/08/16 14:20:18 jkh Exp $";
+#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 message routines.
+ *
+ */
+
+#include "lib.h"
+
+/* Die a relatively simple death */
+void
+upchuck(const char *err)
+{
+ fprintf(stderr, "Fatal error during execution: ");
+ perror(err);
+ cleanup(0);
+ exit(1);
+}
+
+/* Die a more complex death */
+void
+barf(const char *err, ...)
+{
+ va_list args;
+
+ va_start(args, err);
+ vfprintf(stderr, err, args);
+ fputc('\n', stderr);
+ va_end(args);
+ cleanup(0);
+ exit(2);
+}
+
+/* Get annoyed about something but don't go to pieces over it */
+void
+whinge(const char *err, ...)
+{
+ va_list args;
+
+ va_start(args, err);
+ vfprintf(stderr, err, args);
+ fputc('\n', stderr);
+ va_end(args);
+}
+
+/*
+ * As a yes/no question, prompting from the varargs string and using
+ * default if user just hits return.
+ */
+Boolean
+y_or_n(Boolean def, const char *msg, ...)
+{
+ va_list args;
+ int ch = 0;
+ FILE *tty;
+
+ va_start(args, msg);
+ /*
+ * Need to open /dev/tty because file collection may have been
+ * collected on stdin
+ */
+ tty = fopen("/dev/tty", "r");
+ if (!tty)
+ barf("Can't open /dev/tty!\n");
+ while (ch != 'Y' && ch != 'N') {
+ vfprintf(stderr, msg, args);
+ if (def)
+ fprintf(stderr, " [yes]? ");
+ else
+ fprintf(stderr, " [no]? ");
+ fflush(stderr);
+ ch = toupper(fgetc(tty));
+ if (ch == '\n')
+ ch = (def) ? 'Y' : 'N';
+ }
+ return (ch == 'Y') ? TRUE : FALSE;
+}
+
+
diff --git a/usr.sbin/pkg_install/lib/pen.c b/usr.sbin/pkg_install/lib/pen.c
new file mode 100644
index 000000000000..8a3416f6b068
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/pen.c
@@ -0,0 +1,63 @@
+#ifndef lint
+static const char *rcsid = "$Id: pen.c,v 1.1 1993/08/24 09:24:08 jkh Exp $";
+#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".
+ *
+ */
+
+#include "lib.h"
+
+/* For keeping track of where we are */
+static char Cwd[FILENAME_MAX];
+static char Pen[FILENAME_MAX];
+
+
+/*
+ * Make a temporary directory to play in and chdir() to it, returning
+ * pathname of previous working directory.
+ */
+char *
+make_playpen(void)
+{
+ if (!getcwd(Cwd, FILENAME_MAX))
+ upchuck("getcwd");
+ strcpy(Pen, "/tmp/instmp.XXXXXX");
+ if (!mktemp(Pen))
+ barf("Can't mktemp '%s'.", Pen);
+ if (mkdir(Pen, 0755) == FAIL)
+ barf("Can't mkdir '%s'.", Pen);
+ if (chdir(Pen) == FAIL)
+ barf("Can't chdir to '%s'.", Pen);
+ return Cwd;
+}
+
+/* Convenience routine for getting out of playpen */
+void
+leave_playpen(void)
+{
+ if (Cwd[0]) {
+ if (chdir(Cwd) == FAIL)
+ barf("Can't chdir back to '%s'.", Cwd);
+ if (vsystem("rm -rf %s", Pen))
+ fprintf(stderr, "Couldn't remove temporary dir '%s'\n", Pen);
+ Cwd[0] = '\0';
+ }
+}
+
diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c
new file mode 100644
index 000000000000..f2992c6963fb
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/plist.c
@@ -0,0 +1,270 @@
+#ifndef lint
+static const char *rcsid = "$Id: plist.c,v 1.5 1993/08/26 08:13:49 jkh Exp $";
+#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"
+
+/* Add an item to a packing list */
+void
+add_plist(Package *p, int type, char *arg)
+{
+ PackingList tmp;
+
+ tmp = new_plist_entry();
+ tmp->name = copy_string(arg);
+ tmp->type = type;
+
+ if (!p->head)
+ p->head = p->tail = tmp;
+ else {
+ tmp->prev = p->tail;
+ p->tail->next = tmp;
+ p->tail = tmp;
+ }
+}
+
+/* Return the last (most recent) entry in a packing list */
+PackingList
+last_plist(Package *p)
+{
+ return p->tail;
+}
+
+/* Mark all items in a packing list to prevent iteration over them */
+void
+mark_plist(Package *pkg)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ p->marked = TRUE;
+ p = p->next;
+ }
+}
+
+/* Allocate a new packing list entry */
+PackingList
+new_plist_entry(void)
+{
+ PackingList ret;
+
+ ret = (PackingList)malloc(sizeof(struct _plist));
+ bzero(ret, sizeof(struct _plist));
+ return ret;
+}
+
+/* Free an entire packing list */
+void
+free_plist(Package *pkg)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ PackingList 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)
+{
+ char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */
+ char *cp, *sp;
+
+ strcpy(cmd, s);
+ str_lowercase(cmd);
+ cp = cmd;
+ sp = s;
+ while (*cp) {
+ if (isspace(*cp)) {
+ *cp = '\0';
+ while (isspace(*sp)) /* Never sure if macro, increment later */
+ ++sp;
+ break;
+ }
+ ++cp, ++sp;
+ }
+ if (arg)
+ *arg = sp;
+ if (!strcmp(cmd, "cwd"))
+ return PLIST_CWD;
+ else if (!strcmp(cmd, "exec"))
+ return PLIST_CMD;
+ else if (!strcmp(cmd, "mode"))
+ return PLIST_CHMOD;
+ else if (!strcmp(cmd, "owner"))
+ return PLIST_CHOWN;
+ else if (!strcmp(cmd, "group"))
+ return PLIST_CHGRP;
+ else if (!strcmp(cmd, "comment"))
+ return PLIST_COMMENT;
+ else if (!strcmp(cmd, "ignore"))
+ return PLIST_IGNORE;
+ else if (!strcmp(cmd, "name"))
+ return PLIST_NAME;
+ else
+ return FAIL;
+}
+
+/* Read a packing list from a file */
+void
+read_plist(Package *pkg, FILE *fp)
+{
+ char *cp, pline[FILENAME_MAX];
+ int cmd;
+
+ while (fgets(pline, FILENAME_MAX, fp)) {
+ int len = strlen(pline) - 1;
+
+ while (isspace(pline[len]))
+ pline[len--] = '\0';
+ if (!len)
+ continue;
+ cp = pline;
+ if (pline[0] == CMD_CHAR) {
+ cmd = plist_cmd(pline + 1, &cp);
+ if (cmd == FAIL)
+ barf("Bad command '%s'", pline);
+ }
+ 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 *pkg, FILE *fp)
+{
+ PackingList plist = pkg->head;
+
+ while (plist) {
+ switch(plist->type) {
+ case PLIST_FILE:
+ fprintf(fp, "%s\n", plist->name);
+ break;
+
+ case PLIST_CWD:
+ fprintf(fp, "%ccwd %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_CMD:
+ fprintf(fp, "%cexec %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_CHMOD:
+ fprintf(fp, "%cchmod %s\n", CMD_CHAR,
+ plist->name ? plist->name : "");
+ break;
+
+ case PLIST_CHOWN:
+ fprintf(fp, "%cchown %s\n", CMD_CHAR,
+ plist->name ? plist->name : "");
+ break;
+
+ case PLIST_CHGRP:
+ fprintf(fp, "%cchgrp %s\n", CMD_CHAR,
+ plist->name ? plist->name : "");
+ break;
+
+ case PLIST_COMMENT:
+ fprintf(fp, "%ccomment %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_IGNORE:
+ fprintf(fp, "%cignore\n", CMD_CHAR);
+ break;
+
+ case PLIST_NAME:
+ fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name);
+ break;
+
+ default:
+ barf("Unknown command type %d (%s)\n", plist->type, plist->name);
+ break;
+ }
+ plist = plist->next;
+ }
+}
+
+/* Delete the results of a package installation, not the packaging itself */
+void
+delete_package(Boolean ign_err, Package *pkg)
+{
+ PackingList p = pkg->head;
+ char *Where = ".";
+
+ while (p) {
+ if (p->type == PLIST_CWD) {
+ Where = p->name;
+ if (Verbose)
+ printf("Delete: (CWD to %s)\n", Where);
+ }
+ else if (p->type == PLIST_IGNORE)
+ p = p->next;
+ else if (p->type == PLIST_FILE) {
+ char full_name[FILENAME_MAX];
+
+ sprintf(full_name, "%s/%s", Where, p->name);
+ if (Verbose)
+ printf("Delete: %s\n", full_name);
+
+ if (!Fake && delete_hierarchy(full_name, ign_err))
+ whinge("Unable to completely remove file '%s'", full_name);
+ }
+ p = p->next;
+ }
+}
+
+/* Selectively delete a hierarchy */
+int
+delete_hierarchy(char *dir, Boolean ign_err)
+{
+ char *cp1, *cp2;
+
+ cp1 = cp2 = dir;
+ if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir))
+ return 1;
+ while (cp2) {
+ if ((cp2 = rindex(cp1, '/')) != NULL)
+ *cp2 = '\0';
+ if (!isempty(dir))
+ return 0;
+ if (vsystem("%s %s", RMDIR_CMD, dir) && ign_err)
+ return 1;
+ /* Put it back */
+ if (cp2) {
+ *cp2 = '/';
+ cp1 = cp2 - 1;
+ }
+ }
+ return 0;
+}
diff --git a/usr.sbin/pkg_install/lib/str.c b/usr.sbin/pkg_install/lib/str.c
new file mode 100644
index 000000000000..8d68f9291f1d
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/str.c
@@ -0,0 +1,85 @@
+#ifndef lint
+static const char *rcsid = "$Id";
+#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.
+ *
+ */
+
+#include "lib.h"
+
+char *
+get_dash_string(char **str)
+{
+ char *s = *str;
+
+ if (*s == '-')
+ *str = copy_string(s + 1);
+ else
+ *str = get_file_contents(s);
+ return *str;
+}
+
+char *
+copy_string(char *str)
+{
+ char *ret;
+
+ if (!str)
+ ret = NULL;
+ else {
+ ret = (char *)malloc(strlen(str) + 1);
+ strcpy(ret, str);
+ }
+ return ret;
+}
+
+/* Return TRUE if 'str' ends in suffix 'suff' */
+Boolean
+suffix(char *str, char *suff)
+{
+ char *idx;
+ Boolean ret = FALSE;
+
+ idx = rindex(str, '.');
+ if (idx && !strcmp(idx + 1, suff))
+ ret = TRUE;
+ return ret;
+}
+
+/* Assuming str has a suffix, brutally murder it! */
+void
+nuke_suffix(char *str)
+{
+ char *idx;
+
+ idx = rindex(str, '.');
+ if (idx)
+ *idx = '\0'; /* Yow! Don't try this on a const! */
+}
+
+/* Lowercase a whole string */
+void
+str_lowercase(char *str)
+{
+ while (*str) {
+ *str = tolower(*str);
+ ++str;
+ }
+}