Make it possible to have separate install scripts as well as have

an on-delete script.

Submitted by:	Rajesh Vaidheeswarran <rv@fore.com>
This commit is contained in:
jkh 1998-12-16 13:59:31 +00:00
parent 31fba727bc
commit be66220741
10 changed files with 310 additions and 54 deletions

View File

@ -1,6 +1,6 @@
#ifndef lint
static const char rcsid[] =
"$Id: perform.c,v 1.52 1998/09/08 03:02:45 jkh Exp $";
"$Id: perform.c,v 1.53 1998/09/11 07:26:54 jkh Exp $";
#endif
/*
@ -72,6 +72,11 @@ pkg_do(char *pkg)
PackingList p;
struct stat sb;
int inPlace;
/* support for separate pre/post install scripts */
int new_m = 0;
char pre_script[FILENAME_MAX] = INSTALL_FNAME;
char post_script[FILENAME_MAX];
char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX];
code = 0;
zapLogDir = 0;
@ -318,17 +323,35 @@ pkg_do(char *pkg)
}
}
/* Test whether to use the old method of passing tokens to installation
* scripts, and set appropriate variables..
*/
if (fexists(POST_INSTALL_FNAME)) {
new_m = 1;
sprintf(post_script, "%s", POST_INSTALL_FNAME);
sprintf(pre_arg, "");
sprintf(post_arg, "");
} else {
if (fexists(INSTALL_FNAME)) {
sprintf(post_script, "%s", INSTALL_FNAME);
sprintf(pre_arg, "PRE-INSTALL");
sprintf(post_arg, "POST-INSTALL");
}
}
/* If we're really installing, and have an installation file, run it */
if (!NoInstall && fexists(INSTALL_FNAME)) {
vsystem("chmod +x %s", INSTALL_FNAME); /* make sure */
if (!NoInstall && fexists(pre_script)) {
vsystem("chmod +x %s", pre_script); /* make sure */
if (Verbose)
printf("Running install with PRE-INSTALL for %s..\n", PkgName);
if (!Fake && vsystem("./%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
printf("Running pre-install for %s..\n", PkgName);
if (!Fake && vsystem("./%s %s %s", pre_script, PkgName, pre_arg)) {
warnx("install script returned error status");
unlink(INSTALL_FNAME);
unlink(pre_script);
code = 1;
goto success; /* nothing to uninstall yet */
}
if (new_m) unlink(pre_script);
}
/* Now finally extract the entire show if we're not going direct */
@ -349,16 +372,17 @@ pkg_do(char *pkg)
}
/* Run the installation script one last time? */
if (!NoInstall && fexists(INSTALL_FNAME)) {
if (!NoInstall && fexists(post_script)) {
vsystem("chmod +x %s", post_script); /* make sure */
if (Verbose)
printf("Running install with POST-INSTALL for %s..\n", PkgName);
if (!Fake && vsystem("./%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
printf("Running post-install for %s..\n", PkgName);
if (!Fake && vsystem("./%s %s %s", post_script, PkgName, post_arg)) {
warnx("install script returned error status");
unlink(INSTALL_FNAME);
unlink(post_script);
code = 1;
goto fail;
}
unlink(INSTALL_FNAME);
unlink(post_script);
}
/* Time to record the deed? */
@ -389,6 +413,8 @@ pkg_do(char *pkg)
vsystem("chmod a+rx %s", LogDir);
if (fexists(DEINSTALL_FNAME))
move_file(".", DEINSTALL_FNAME, LogDir);
if (fexists(POST_DEINSTALL_FNAME))
move_file(".", POST_DEINSTALL_FNAME, LogDir);
if (fexists(REQUIRE_FNAME))
move_file(".", REQUIRE_FNAME, LogDir);
sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);

View File

@ -15,7 +15,7 @@
.\"
.\"
.\" @(#)pkg_add.1
.\" $Id$
.\" $Id: pkg_add.1,v 1.26 1998/07/14 08:27:58 jkoshy Exp $
.\"
.Dd November 25, 1994
.Dt pkg_add 1
@ -48,10 +48,10 @@ attacks from miscreants who create dangerous package files.
You are advised to verify the competence and identity of those who
provide installable package files. For extra protection, use the
.Fl M
flag to extract the package file, and inspect its contents and scripts
to insure it poses no danger to your system's integrity. Pay particular
attention to any +INSTALL, +DEINSTALL, +REQUIRE or +MTREE_DIRS files,
and inspect the +CONTENTS file for
flag to extract the package file, and inspect its contents and scripts to
insure it poses no danger to your system's integrity. Pay particular
attention to any +INSTALL, +POST-INSTALL, +DEINSTALL, +POST-DEINSTALL,
+REQUIRE or +MTREE_DIRS files, and inspect the +CONTENTS file for
.Cm @cwd ,
.Cm @mode
(check for setuid),
@ -78,7 +78,8 @@ will search them in each directory named by
.It Fl v
Turn on verbose output.
.It Fl I
If an installation script exists for a given package, do not execute it.
If a installation scripts (pre-install or post-install) exist for a given
package, do not execute them.
.It Fl n
Don't actually install a package, just report the steps that
would be taken if it was.
@ -197,7 +198,7 @@ passive mode
.Ef
ftp.
.Sh TECHNICAL DETAILS
.Nm Pkg_add
.Nm pkg_add
is fairly simple. It extracts each package's "packing list"
into a special staging directory, parses it,
and then runs through the following sequence to fully extract the contents:
@ -244,18 +245,32 @@ is the name of the package in question and the
keyword denotes this as an installation requirements check (useful if
you want to have one script serving multiple functions).
.It
If an
.Ar install
script exists for the package, it is then executed with the following arguments:
If a
.Ar pre-install
script exists for the package, it is then executed with the following
arguments:
.Bd -filled -offset indent -compact
.Cm script
.Ar pkg-name
.Ar PRE-INSTALL
.Ar PRE-INSTALL
.Ed
where
.Ar pkg-name
is the name of the package in question and
.Ar PRE-INSTALL
is a keyword denoting this as the preinstallation phase.
.Cm Note:
The
.Ar PRE-INSTALL
keyword will not appear if separate scripts for pre-install and post-install
are given during package creation time (using the
.Cm Fl i
and
.Cm Fl I
flags to
.Xr pkg_create 1 ).
.It
If
.Cm @option extract-in-place
@ -289,17 +304,39 @@ flag was specified, the name of the first directory named by a
.Cm @cwd
directive within this package.
.It
If an
.Ar install
If a
.Ar post-install
script exists for the package, it is then executed as
.Bd -filled -offset indent -compact
.Cm script
.Ar pkg-name
.Ar POST-INSTALL
.Ed
This all allows you to write a single
where
.Ar pkg-name
is the name of the package in question and
.Ar POST-INSTALL
is a keyword denoting this as the post-installation phase.
.Cm Note:
The
.Ar POST-INSTALL
keyword will not appear if separate scripts for pre-install and post-install
are given during package creation time (using the
.Cm Fl i
and
.Cm Fl I
flags to
.Xr pkg_create 1 ).
Reasoning behind passing keywords such as
.Ar POST-INSTALL
and
.Ar PRE-INSTALL
is that this allows you to write a single
.Ar install
script that does both ``before and after'' actions.
script that does both ``before and after'' actions. But, separating the
functionality is more advantageous and easier from a maintainence viewpoint.
.It
After installation is complete, a copy of the packing list,
.Ar deinstall

View File

@ -1,4 +1,4 @@
/* $Id: create.h,v 1.12 1997/06/06 12:19:11 jkh Exp $ */
/* $Id: create.h,v 1.13 1997/10/08 07:46:19 charnier Exp $ */
/*
* FreeBSD install - a package for the installation and maintainance
@ -28,7 +28,9 @@ extern char *Comment;
extern char *Desc;
extern char *Display;
extern char *Install;
extern char *PostInstall;
extern char *DeInstall;
extern char *PostDeInstall;
extern char *Contents;
extern char *Require;
extern char *SrcDir;

View File

@ -1,6 +1,6 @@
#ifndef lint
static const char rcsid[] =
"$Id: main.c,v 1.16 1997/06/06 12:19:11 jkh Exp $";
"$Id: main.c,v 1.17 1997/10/08 07:46:23 charnier Exp $";
#endif
/*
@ -18,7 +18,7 @@ static const char rcsid[] =
#include "lib.h"
#include "create.h"
static char Options[] = "YNOhvf:p:P:c:d:i:k:r:t:X:D:m:s:";
static char Options[] = "YNOhvf:p:P:c:d:i:I:k:K:r:t:X:D:m:s:";
char *Prefix = NULL;
char *Comment = NULL;
@ -26,7 +26,9 @@ char *Desc = NULL;
char *SrcDir = NULL;
char *Display = NULL;
char *Install = NULL;
char *PostInstall = NULL;
char *DeInstall = NULL;
char *PostDeInstall = NULL;
char *Contents = NULL;
char *Require = NULL;
char *ExcludeFrom = NULL;
@ -87,10 +89,18 @@ main(int argc, char **argv)
Install = optarg;
break;
case 'I':
PostInstall = optarg;
break;
case 'k':
DeInstall = optarg;
break;
case 'K':
PostDeInstall = optarg;
break;
case 'r':
Require = optarg;
break;
@ -151,10 +161,11 @@ main(int argc, char **argv)
static void
usage()
{
fprintf(stderr, "%s\n%s\n%s\n%s\n",
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
"usage: pkg_create [-YNOhv] [-P pkgs] [-p prefix] [-f contents] [-i iscript]",
" [-k dscript] [-r rscript] [-t template] [-X excludefile]",
" [-D displayfile] [-m mtreefile] -c comment -d description",
" -f packlist pkg-name");
" [-I piscript] [-k dscript] [-K pdscript] [-r rscript] ",
" [-t template] [-X excludefile] [-D displayfile] ",
" [-m mtreefile] -c comment -d description -f packlist ",
" pkg-name");
exit(1);
}

View File

@ -1,6 +1,6 @@
#ifndef lint
static const char rcsid[] =
"$Id: perform.c,v 1.45 1998/09/11 07:26:57 jkh Exp $";
"$Id: perform.c,v 1.46 1998/12/05 06:28:58 asami Exp $";
#endif
/*
@ -156,11 +156,21 @@ pkg_perform(char **pkgs)
add_plist(&plist, PLIST_IGNORE, NULL);
add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
}
if (PostInstall) {
copy_file(home, PostInstall, POST_INSTALL_FNAME);
add_plist(&plist, PLIST_IGNORE, NULL);
add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
}
if (DeInstall) {
copy_file(home, DeInstall, DEINSTALL_FNAME);
add_plist(&plist, PLIST_IGNORE, NULL);
add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
}
if (PostDeInstall) {
copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
add_plist(&plist, PLIST_IGNORE, NULL);
add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
}
if (Require) {
copy_file(home, Require, REQUIRE_FNAME);
add_plist(&plist, PLIST_IGNORE, NULL);
@ -270,8 +280,12 @@ make_dist(char *home, char *pkg, char *suffix, Package *plist)
if (Install)
fprintf(totar, "%s\n", INSTALL_FNAME);
if (PostInstall)
fprintf(totar, "%s\n", POST_INSTALL_FNAME);
if (DeInstall)
fprintf(totar, "%s\n", DEINSTALL_FNAME);
if (PostDeInstall)
fprintf(totar, "%s\n", POST_DEINSTALL_FNAME);
if (Require)
fprintf(totar, "%s\n", REQUIRE_FNAME);
if (Display)

View File

@ -15,7 +15,7 @@
.\"
.\"
.\" @(#)pkg_create.1
.\" $Id: pkg_create.1,v 1.25 1998/05/24 03:11:17 steve Exp $
.\" $Id: pkg_create.1,v 1.26 1998/06/26 07:15:37 jkoshy Exp $
.\"
.\" hacked up by John Kohl for NetBSD--fixed a few bugs, extended keywords,
.\" added dependency tracking, etc.
@ -36,7 +36,9 @@
.Op Fl p Ar prefix
.Op Fl f Ar contents
.Op Fl i Ar iscript
.Op Fl I Ar piscript
.Op Fl k Ar dscript
.Op Fl K Ar pdscript
.Op Fl r Ar rscript
.Op Fl s Ar srcdir
.Op Fl t Ar template
@ -102,9 +104,28 @@ are dumped, rather than the links themselves.
.It Fl i Ar iscript
Set
.Ar iscript
to be the install procedure for the package. This can be any
to be the pre-install procedure for the package. This can be any executable
program (or shell script). It will be invoked automatically when the
package is later installed. It will be passed the package's name as the
first argument.
.Cm Note:
if the
.Cm Fl I
option is not given, this script will serve as both the pre-install and the
post-install script for the package, differentiating between the
functionality by passing the keywords
.Ar PRE-INSTALL
and
.Ar POST-INSTALL
respectively, along with the package's name.
.It Fl I Ar piscript
Set
.Ar piscript
to be the post-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.
when the package is later installed. It will be passed the package's name as
the first argument.
.It Fl P Ar pkgs
Set the initial package dependency list to
.Ar pkgs .
@ -120,9 +141,29 @@ the package.
.It Fl k Ar dscript
Set
.Ar dscript
to be the de-install procedure for the package. This can be any
executable program (or shell script). It will be invoked automatically
when the package is later (if ever) de-installed.
to be the de-install procedure for the package. This can be any executable
program (or shell script). It will be invoked automatically when the
package is later (if ever) de-installed. It will be passed the package's
name as the first argument.
.Cm Note:
if the
.Cm Fl K
option is not given, this script will serve as both the de-install and the
post-deinstall script for the package, differentiating between the
functionality by passing the keywords
.Ar DEINSTALL
and
.Ar POST-DEINSTALL
respectively, along with the package's name.
.It Fl K Ar pdscript
Set
.Ar pdscript
to be the post-deinstall procedure for the package. This can be any
executable program (or shell script). It will be invoked automatically when
the package is later de-installed. It will be passed the package's name as
the first argument.
.It Fl r Ar rscript
Set
.Ar rscript

View File

@ -1,6 +1,6 @@
#ifndef lint
static const char rcsid[] =
"$Id: perform.c,v 1.16 1998/09/11 07:26:58 jkh Exp $";
"$Id: perform.c,v 1.17 1998/11/11 06:09:04 jkh Exp $";
#endif
/*
@ -54,6 +54,11 @@ pkg_do(char *pkg)
PackingList p;
char *tmp;
int len;
/* support for separate pre/post install scripts */
int new_m = 0;
char pre_script[FILENAME_MAX] = DEINSTALL_FNAME;
char post_script[FILENAME_MAX];
char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX];
if (!pkg || !(len = strlen(pkg)))
return 1;
@ -66,18 +71,22 @@ pkg_do(char *pkg)
sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
pkg);
if (!fexists(LogDir)) {
warnx("no such package '%s' installed", pkg);
return 1;
}
if (!getcwd(home, FILENAME_MAX)) {
cleanup(0);
errx(2, "unable to get current working directory!");
}
if (chdir(LogDir) == FAIL) {
warnx("unable to change directory to %s! deinstall failed", LogDir);
return 1;
}
if (!isemptyfile(REQUIRED_BY_FNAME)) {
char buf[512];
warnx("package `%s' is required by these other packages\n"
@ -93,23 +102,29 @@ pkg_do(char *pkg)
if (!Force)
return 1;
}
sanity_check(LogDir);
cfile = fopen(CONTENTS_FNAME, "r");
if (!cfile) {
warnx("unable to open '%s' file", CONTENTS_FNAME);
return 1;
}
/* If we have a prefix, add it now */
if (Prefix)
add_plist(&Plist, PLIST_CWD, Prefix);
read_plist(&Plist, cfile);
fclose(cfile);
p = find_plist(&Plist, PLIST_CWD);
if (!p) {
warnx("package '%s' doesn't have a prefix", pkg);
return 1;
}
setenv(PKG_PREFIX_VNAME, p->name, 1);
if (fexists(REQUIRE_FNAME)) {
if (Verbose)
printf("Executing 'require' script.\n");
@ -121,34 +136,81 @@ pkg_do(char *pkg)
return 1;
}
}
if (!NoDeInstall && fexists(DEINSTALL_FNAME)) {
/* Test whether to use the old method of passing tokens to deinstallation
* scripts, and set appropriate variables..
*/
if (fexists(POST_DEINSTALL_FNAME)) {
new_m = 1;
sprintf(post_script, "%s", POST_DEINSTALL_FNAME);
sprintf(pre_arg, "");
sprintf(post_arg, "");
} else {
if (fexists(DEINSTALL_FNAME)) {
sprintf(post_script, "%s", DEINSTALL_FNAME);
sprintf(pre_arg, "DEINSTALL");
sprintf(post_arg, "POST-DEINSTALL");
}
}
if (!NoDeInstall && fexists(pre_script)) {
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)) {
vsystem("chmod +x %s", pre_script); /* make sure */
if (vsystem("./%s %s %s", pre_script, pkg, pre_arg)) {
warnx("deinstall script returned error status");
if (!Force)
return 1;
}
}
}
if (chdir(home) == FAIL) {
cleanup(0);
errx(2, "Toto! This doesn't look like Kansas anymore!");
}
if (!Fake) {
/* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */
if (delete_package(FALSE, CleanDirs, &Plist) == FAIL)
warnx(
"couldn't entirely delete package (perhaps the packing list is\n"
"incorrectly specified?)");
}
if (chdir(LogDir) == FAIL) {
warnx("unable to change directory to %s! deinstall failed", LogDir);
return 1;
}
if (!NoDeInstall && fexists(post_script)) {
if (Fake)
printf("Would execute post-deinstall script at this point.\n");
else {
vsystem("chmod +x %s", post_script); /* make sure */
if (vsystem("./%s %s %s", post_script, pkg, post_arg)) {
warnx("post-deinstall script returned error status");
if (!Force)
return 1;
}
}
}
if (chdir(home) == FAIL) {
cleanup(0);
errx(2, "Toto! This doesn't look like Kansas anymore!");
}
if (!Fake) {
if (vsystem("%s -r %s", REMOVE_CMD, LogDir)) {
warnx("couldn't remove log entry in %s, deinstall failed", LogDir);
if (!Force)
return 1;
}
}
for (p = Plist.head; p ; p = p->next) {
if (p->type != PLIST_PKGDEP)
continue;

View File

@ -47,9 +47,9 @@ You are advised to verify the competence and identity of those who
provide installable package files. For extra protection, examine all
the package control files in the package record directory (
.Pa /var/db/pkg/<pkg-name>/ ).
Pay particular
attention to any +INSTALL, +DEINSTALL, +REQUIRE or +MTREE_DIRS files,
and inspect the +CONTENTS file for
Pay particular attention to any +INSTALL, +POST-INSTALL, +DEINSTALL,
+POST-DEINSTALL, +REQUIRE or +MTREE_DIRS files, and inspect the +CONTENTS
file for
.Cm @cwd ,
.Cm @mode
(check for setuid),
@ -97,7 +97,7 @@ deinstall or require script fails.
.Pp
.Sh TECHNICAL DETAILS
.Nm Pkg_delete
.Nm pkg_delete
does pretty much what it says. It examines installed package records in
.Pa /var/db/pkg/<pkg-name> ,
deletes the package contents, and finally removes the package records.
@ -140,14 +140,71 @@ The
.Nm deinstall
script is called as:
.Bd -filled -offset indent -compact
.Cm deinstall
.Cm script
.Ar <pkg-name>
.Ar DEINSTALL
.Ed
Passing the keyword
where
.Ar pkg-name
is the name of the package in question and
.Ar DEINSTALL
lets you potentially write only one program/script that handles all
aspects of installation and deletion.
is a keyword denoting this as the pre-deinstallation phase.
.Cm Note:
The
.Ar DEINSTALL
keyword will not appear if separate scripts for deinstall and post-deinstall
are given during package creation time (using the
.Cm Fl k
and
.Cm Fl K
flags to
.Xr pkg_create 1 ).
.Pp
If a
.Cm post-deinstall
script exists for the package, it is executed
.Cm after
all files are removed. It is this script's responsibility to clean up any
additional messy details around the package's installation, and leave the
system (hopefully) in the same state that it was prior to the installation
of the package.
The
.Nm post-deinstall
script is called as:
.Bd -filled -offset indent -compact
.Cm script
.Ar <pkg-name>
.Ar POST-DEINSTALL
.Ed
where
.Ar pkg-name
is the name of the package in question and
.Ar POST-DEINSTALL
is a keyword denoting this as the post-deinstallation phase.
.Cm Note:
The
.Ar POST-DEINSTALL
keyword will not appear if separate scripts for deinstall and post-deinstall
are given during package creation time (using the
.Cm Fl k
and
.Cm Fl K
flags to
.Xr pkg_create 1 ).
Reasoning behind passing keywords such as
.Ar DEINSTALL
and
.Ar POST-DEINSTALL
is that it lets you potentially write only one program/script that handles
all aspects of installation and deletion.
But experience has proved that this is a lot more difficult to maintain and
is not as advantageous as having separate scripts that handle each aspect of
installation and deinstallation.
.Pp
All scripts are called with the environment variable
.Ev PKG_PREFIX

View File

@ -1,6 +1,6 @@
#ifndef lint
static const char rcsid[] =
"$Id: perform.c,v 1.24 1998/02/16 17:16:38 jkh Exp $";
"$Id: perform.c,v 1.25 1998/09/11 07:26:58 jkh Exp $";
#endif
/*
@ -179,8 +179,12 @@ pkg_do(char *pkg)
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_INSTALL) && fexists(POST_INSTALL_FNAME))
show_file("Post-Install script:\n", POST_INSTALL_FNAME);
if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME))
show_file("De-Install script:\n", DEINSTALL_FNAME);
if ((Flags & SHOW_DEINSTALL) && fexists(POST_DEINSTALL_FNAME))
show_file("Post-DeInstall script:\n", POST_DEINSTALL_FNAME);
if ((Flags & SHOW_MTREE) && fexists(MTREE_FNAME))
show_file("mtree file:\n", MTREE_FNAME);
if (Flags & SHOW_PREFIX)

View File

@ -1,4 +1,4 @@
/* $Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp $ */
/* $Id: lib.h,v 1.26 1998/02/16 17:16:47 jkh Exp $ */
/*
* FreeBSD install - a package for the installation and maintainance
@ -66,7 +66,9 @@
#define COMMENT_FNAME "+COMMENT"
#define DESC_FNAME "+DESC"
#define INSTALL_FNAME "+INSTALL"
#define POST_INSTALL_FNAME "+POST-INSTALL"
#define DEINSTALL_FNAME "+DEINSTALL"
#define POST_DEINSTALL_FNAME "+POST-DEINSTALL"
#define REQUIRE_FNAME "+REQUIRE"
#define REQUIRED_BY_FNAME "+REQUIRED_BY"
#define DISPLAY_FNAME "+DISPLAY"