aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/pkg_install/add/add.h4
-rw-r--r--usr.sbin/pkg_install/add/extract.c7
-rw-r--r--usr.sbin/pkg_install/add/main.c27
-rw-r--r--usr.sbin/pkg_install/add/perform.c100
-rw-r--r--usr.sbin/pkg_install/add/pkg_add.173
5 files changed, 173 insertions, 38 deletions
diff --git a/usr.sbin/pkg_install/add/add.h b/usr.sbin/pkg_install/add/add.h
index 6c5d46f77327..019fc925737f 100644
--- a/usr.sbin/pkg_install/add/add.h
+++ b/usr.sbin/pkg_install/add/add.h
@@ -23,6 +23,8 @@
#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;
@@ -31,6 +33,8 @@ extern char *Owner;
extern char *Group;
extern char *Directory;
extern char *PkgName;
+extern char *PlayPen;
+extern add_mode_t AddMode;
int make_hierarchy(char *);
void extract_plist(char *, Package *);
diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c
index 84160f74d66b..997d6d8d094b 100644
--- a/usr.sbin/pkg_install/add/extract.c
+++ b/usr.sbin/pkg_install/add/extract.c
@@ -52,7 +52,12 @@ extract_plist(char *home, Package *pkg)
if (Verbose)
printf("extract: %s/%s\n", Directory, p->name);
if (!Fake) {
- copy_hierarchy(Directory, p->name, TRUE);
+ char try[FILENAME_MAX];
+
+ /* first try to rename it into place */
+ sprintf(try, "%s/%s", Directory, p->name);
+ if (rename(p->name, try) == FAIL)
+ copy_hierarchy(Directory, p->name, TRUE);
apply_perms(Directory, p->name);
}
break;
diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
index cb8cc65d2854..a1f5ba1ef5ec 100644
--- a/usr.sbin/pkg_install/add/main.c
+++ b/usr.sbin/pkg_install/add/main.c
@@ -26,7 +26,7 @@ static char *rcsid = "$Id: main.c,v 1.6 1993/09/04 05:06:28 jkh Exp $";
#include "lib.h"
#include "add.h"
-static char Options[] = "hvIRnp:";
+static char Options[] = "hvIRnp:SM";
char *Prefix = NULL;
Boolean NoInstall = FALSE;
@@ -37,6 +37,8 @@ char *Owner = NULL;
char *Group = NULL;
char *PkgName = NULL;
char *Directory = NULL;
+char *PlayPen = NULL;
+add_mode_t AddMode = NORMAL;
int
main(int argc, char **argv)
@@ -69,6 +71,18 @@ main(int argc, char **argv)
Verbose = TRUE;
break;
+ case 't':
+ PlayPen = optarg;
+ break;
+
+ case 'S':
+ AddMode = SLAVE;
+ break;
+
+ case 'M':
+ AddMode = MASTER;
+ break;
+
case 'h':
case '?':
default:
@@ -84,9 +98,13 @@ main(int argc, char **argv)
*pkgs++ = *argv++;
/* If no packages, yelp */
- if (pkgs == start)
- usage(prog_name, "Missing package name(s)");
*pkgs = NULL;
+ if (pkgs == start && AddMode != SLAVE)
+ usage(prog_name, "Missing package name(s)");
+ else if (start[1] && AddMode == MASTER)
+ usage(prog_name, "Only one package name may be specified with master mode");
+ else if (pkgs != start && AddMode == SLAVE)
+ whinge("Package names ignored in slave mode.");
if ((err = pkg_perform(start)) != NULL) {
if (Verbose)
fprintf(stderr, "%d package addition(s) failed.\n", err);
@@ -115,5 +133,8 @@ usage(const char *name, const char *fmt, ...)
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");
+ fprintf(stderr, "-t temp use temp as template for mktemp()\n");
+ fprintf(stderr, "-S run in SLAVE mode\n");
+ fprintf(stderr, "-M run in MASTER mode\n");
exit(1);
}
diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c
index 64203e552d4e..d285c0e1f3e0 100644
--- a/usr.sbin/pkg_install/add/perform.c
+++ b/usr.sbin/pkg_install/add/perform.c
@@ -41,8 +41,12 @@ pkg_perform(char **pkgs)
signal(SIGINT, cleanup);
signal(SIGHUP, cleanup);
- for (i = 0; pkgs[i]; i++)
- err_cnt += pkg_do(pkgs[i]);
+ if (AddMode == SLAVE)
+ err_cnt = pkg_do(NULL);
+ else {
+ for (i = 0; pkgs[i]; i++)
+ err_cnt += pkg_do(pkgs[i]);
+ }
return err_cnt;
}
@@ -61,40 +65,65 @@ pkg_do(char *pkg)
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 (AddMode == SLAVE) {
+ char tmp_dir[FILENAME_MAX];
+
+ fgets(tmp_dir, FILENAME_MAX, stdin);
+ tmp_dir[strlen(tmp_dir) - 1] = '\0'; /* pesky newline! */
+ if (chdir(tmp_dir) == FAIL) {
+ whinge("pkg_add in SLAVE mode can't chdir to %s.", tmp_dir);
+ return 1;
+ }
+ read_plist(&Plist, stdin);
}
+ else {
+ home = make_playpen(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 (unpack(pkg_fullname, NULL))
+ return 1;
- if (sanity_check(pkg_fullname))
- 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;
+ cfile = fopen(CONTENTS_FNAME, "r");
+ if (!cfile) {
+ whinge("Unable to open %s file.", CONTENTS_FNAME);
+ goto fail;
+ }
+ read_plist(&Plist, cfile);
+ fclose(cfile);
+ if (Prefix) {
+ /*
+ * If we have a prefix, delete the first one we see and add this
+ * one in place of it.
+ */
+ delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
+ add_plist_top(&Plist, PLIST_CWD, Prefix);
+ }
+ /* Just to be safe - overridden if package has made a choice */
+ else
+ add_plist_top(&Plist, PLIST_CWD, home);
+ /* 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);
+ return;
+ }
}
- /* 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)) {
+ if (!Fake && vsystem("%s %s INSTALL", REQUIRE_FNAME, PkgName)) {
whinge("Package %s fails requirements - not installed.",
pkg_fullname);
goto fail;
@@ -104,7 +133,7 @@ pkg_do(char *pkg)
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)) {
+ if (!Fake && vsystem("%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
whinge("Install script returned error status.");
goto fail;
}
@@ -113,12 +142,15 @@ pkg_do(char *pkg)
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)) {
+ if (!Fake && vsystem("%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
whinge("Install script returned error status.");
goto fail;
}
}
if (!NoRecord && !Fake) {
+ char contents[FILENAME_MAX];
+ FILE *cfile;
+
if (getuid() != 0)
whinge("Not running as root - trying to record install anyway.");
if (!PkgName) {
@@ -140,7 +172,15 @@ pkg_do(char *pkg)
copy_file(".", DEINSTALL_FNAME, LogDir);
if (fexists(REQUIRE_FNAME))
copy_file(".", REQUIRE_FNAME, LogDir);
- copy_file(".", CONTENTS_FNAME, LogDir);
+ sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
+ cfile = fopen(contents, "w");
+ if (!cfile) {
+ whinge("Can't open new contents file '%s'! Can't register pkg.",
+ contents);
+ goto success; /* can't log, but still keep pkg */
+ }
+ write_plist(&Plist, cfile);
+ fclose(cfile);
copy_file(".", DESC_FNAME, LogDir);
copy_file(".", COMMENT_FNAME, LogDir);
if (Verbose)
@@ -194,6 +234,8 @@ find_name(Package *pkg)
void
cleanup(int signo)
{
+ if (signo)
+ printf("Signal %d received, cleaning up..\n", signo);
if (Plist.head) {
if (!Fake)
delete_package(FALSE, &Plist);
diff --git a/usr.sbin/pkg_install/add/pkg_add.1 b/usr.sbin/pkg_install/add/pkg_add.1
index 4e332b72a71f..1f652d56041b 100644
--- a/usr.sbin/pkg_install/add/pkg_add.1
+++ b/usr.sbin/pkg_install/add/pkg_add.1
@@ -60,15 +60,77 @@ you know what you are doing!
.BI "\-p\ " prefix
Sets
.I prefix
-as the directory in which to extract files from any packages
-which do not explicitly set theirs.
+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 directory default will
+be replaced, since
+.B pkg_add
+has no way of knowing which directory settings are relative and
+which are absolute. It is rare, in any case, that more than one
+directory transition is made, but when such is the case then you
+may wish to look into the use of
+.B MASTER
+and
+.B SLAVE
+mode (see
+.B \-M
+and
+.B \-S
+options).
+.B "Optional."
+.TP
+.BI "\-t\ " template
+Use
+.I template
+as the input to mktemp(3). By default, this is the string
+.B /tmp/instmp.XXXXXX
+, but it may be necessary to override it in the situation where
+space in your
+.B /tmp
+directory is limited. Be sure to leave some number of `X' characters
+for mktemp(3) to fill in with a unique ID.
.B "Optional."
+.TP
+.B \-M
+Run in
+.B MASTER
+mode. This is a very specialized mode for running
+.B pkg_add
+and is meant to be run in conjunction with
+.B SLAVE
+mode. When run in this mode,
+.B pkg_add
+does no work beyond extracting the package into a temporary staging
+area (see
+.B \-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
+.B sed(1).
+When used in conjunction with
+.B SLAVE
+mode, it allows you to make radical changes to the package structure
+before acting on its contents.
+.TP
+.B \-S
+Run in
+.B SLAVE
+mode. This is a very specialized mode for running
+.B pkg_add
+and is meant to be run in conjunction with
+.B MASTER
+mode. When run in this mode,
+.B pkg_add
+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.
.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:
+a "staging area" directory and then performs the following steps:
.PP
If the package contains a
.B require
@@ -95,8 +157,8 @@ Where
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
+Using the packing list as a guide, files are then moved (or copied,
+as necessary) from the staging area into their new homes and the
.B install
script is then executed a second time with the flags
.PP
@@ -113,6 +175,7 @@ to any
script the package might have, is copied into /var/pkg/<pkg-name>
for subsequent possible use by
.B pkg-delete.
+Finally, the staging area is deleted and the program terminates.
.PP
.SH BUGS
Sure to be some.