1993-08-26 01:19:55 +00:00
# ifndef lint
1995-08-17 00:36:06 +00:00
static const char * rcsid = " $Id: perform.c,v 1.28 1995/08/06 03:20:01 jkh Exp $ " ;
1993-08-26 01:19:55 +00:00
# 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>
1994-12-06 00:51:50 +00:00
# include <sys/wait.h>
1993-08-26 01:19:55 +00:00
static int pkg_do ( char * ) ;
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 ) ;
1993-09-05 04:53:51 +00:00
if ( AddMode = = SLAVE )
err_cnt = pkg_do ( NULL ) ;
else {
for ( i = 0 ; pkgs [ i ] ; i + + )
err_cnt + = pkg_do ( pkgs [ i ] ) ;
}
1993-08-26 01:19:55 +00:00
return err_cnt ;
}
static Package Plist ;
1995-04-26 15:06:26 +00:00
/*
* This is seriously ugly code following . Written very fast !
* [ And subsequently made even worse . . Sigh ! This code was just born
* to be hacked , I guess . . : ) - jkh ]
*/
1993-08-26 01:19:55 +00:00
static int
pkg_do ( char * pkg )
{
char pkg_fullname [ FILENAME_MAX ] ;
1994-10-14 05:43:41 +00:00
char home [ FILENAME_MAX ] ;
1995-04-22 13:58:24 +00:00
char extract_contents [ FILENAME_MAX ] ;
char * where_to , * tmp ;
1993-08-26 01:19:55 +00:00
FILE * cfile ;
int code = 0 ;
1994-05-25 06:24:18 +00:00
PackingList p ;
1994-10-04 16:07:50 +00:00
struct stat sb ;
1995-04-26 15:06:26 +00:00
char * isTMP = NULL ;
1993-08-26 01:19:55 +00:00
/* Reset some state */
if ( Plist . head )
free_plist ( & Plist ) ;
LogDir [ 0 ] = ' \0 ' ;
1995-04-26 07:43:35 +00:00
1995-04-26 15:06:26 +00:00
/* Are we coming in for a second pass, everything already extracted? */
1993-09-05 04:53:51 +00:00
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 ) ;
1993-08-26 01:19:55 +00:00
}
1995-04-26 15:06:26 +00:00
/* Nope - do it now */
1993-09-05 04:53:51 +00:00
else {
1994-10-14 05:34:04 +00:00
if ( ! getcwd ( home , FILENAME_MAX ) )
1995-05-30 03:57:47 +00:00
upchuck ( " getcwd " ) ;
1994-10-14 05:34:04 +00:00
1995-04-26 15:06:26 +00:00
if ( isURL ( pkg ) ) {
char * newname = fileGetURL ( pkg ) ;
if ( ! newname ) {
whinge ( " Unable to fetch `%s' by URL. " , pkg ) ;
return 1 ;
}
strcpy ( pkg_fullname , newname ) ;
isTMP = pkg_fullname ;
}
else {
if ( pkg [ 0 ] = = ' / ' ) /* full pathname? */
strcpy ( pkg_fullname , pkg ) ;
else
sprintf ( pkg_fullname , " %s/%s " , home , pkg ) ;
if ( ! fexists ( pkg_fullname ) ) {
char * tmp = fileFindByPath ( pkg ) ;
if ( ! tmp ) {
whinge ( " Can't find package `%s'. " , pkg ) ;
return 1 ;
}
strcpy ( pkg_fullname , tmp ) ;
}
1993-09-05 04:53:51 +00:00
}
1995-08-17 00:36:06 +00:00
if ( stat ( pkg_fullname , & sb ) = = FAIL ) {
whinge ( " Can't stat package file '%s'. " , pkg_fullname ) ;
goto bomb ;
}
Home = make_playpen ( PlayPen , sb . st_size * 4 ) ;
1995-08-06 03:21:04 +00:00
where_to = PlayPen ;
1995-04-22 13:58:24 +00:00
sprintf ( extract_contents , " --fast-read %s " , CONTENTS_FNAME ) ;
if ( unpack ( pkg_fullname , extract_contents ) ) {
whinge ( " Unable to extract table of contents file from `%s' - not a package?. " , pkg_fullname ) ;
goto bomb ;
}
cfile = fopen ( CONTENTS_FNAME , " r " ) ;
if ( ! cfile ) {
whinge ( " Unable to open table of contents file `%s' - not a package? " , CONTENTS_FNAME ) ;
goto bomb ;
}
read_plist ( & Plist , cfile ) ;
fclose ( cfile ) ;
/*
* If we have a prefix , delete the first one we see and add this
* one in place of it .
*/
if ( Prefix ) {
delete_plist ( & Plist , FALSE , PLIST_CWD , NULL ) ;
add_plist_top ( & Plist , PLIST_CWD , Prefix ) ;
}
/* Extract directly rather than moving? Oh goodie! */
if ( find_plist_option ( & Plist , " extract-in-place " ) ) {
if ( Verbose )
printf ( " Doing in-place extraction for %s \n " , pkg_fullname ) ;
p = find_plist ( & Plist , PLIST_CWD ) ;
if ( p ) {
1995-04-26 07:43:35 +00:00
if ( ! isdir ( p - > name ) & & ! Fake ) {
1995-04-22 13:58:24 +00:00
if ( Verbose )
printf ( " Desired prefix of %s does not exist, creating.. \n " , p - > name ) ;
vsystem ( " mkdir -p %s " , p - > name ) ;
if ( chdir ( p - > name ) ) {
whinge ( " Unable to change directory to `%s' - no permission? " , p - > name ) ;
perror ( " chdir " ) ;
1995-04-26 15:06:26 +00:00
goto bomb ;
1995-04-22 13:58:24 +00:00
}
}
where_to = p - > name ;
}
else {
whinge ( " No prefix specified in `%s' - this is a bad package! " ,
pkg_fullname ) ;
1995-04-26 15:06:26 +00:00
goto bomb ;
1995-04-22 13:58:24 +00:00
}
}
1995-07-30 09:11:20 +00:00
1994-10-04 16:07:50 +00:00
/*
* Apply a crude heuristic to see how much space the package will
* take up once it ' s unpacked . I ' ve noticed that most packages
1994-10-14 05:34:04 +00:00
* compress an average of 75 % , so multiply by 4 for good measure .
1994-10-04 16:07:50 +00:00
*/
1993-08-26 01:19:55 +00:00
1995-04-22 13:58:24 +00:00
if ( min_free ( where_to ) < sb . st_size * 4 ) {
1995-08-06 03:21:04 +00:00
whinge ( " Projected size of %d exceeds available free space. \n Please set your PKG_TMPDIR variable to point to a location with more \n free space and try again. " , sb . st_size * 4 ) ;
whinge ( " Not extracting %s \n into %s, sorry! " , pkg_fullname , where_to ) ;
1995-04-22 13:58:24 +00:00
goto bomb ;
1995-04-22 07:41:02 +00:00
}
1993-08-26 01:19:55 +00:00
1995-04-22 13:58:24 +00:00
setenv ( PKG_PREFIX_VNAME ,
( p = find_plist ( & Plist , PLIST_CWD ) ) ? p - > name : NULL , 1 ) ;
/* Protect against old packages with bogus @name fields */
PkgName = ( p = find_plist ( & Plist , PLIST_NAME ) ) ? p - > name : " anonymous " ;
/* See if we're already registered */
sprintf ( LogDir , " %s/%s " , ( tmp = getenv ( PKG_DBDIR ) ) ? tmp : DEF_LOG_DIR ,
basename_of ( PkgName ) ) ;
if ( isdir ( LogDir ) ) {
char tmp [ FILENAME_MAX ] ;
whinge ( " Package `%s' already recorded as installed. \n " , PkgName ) ;
code = 1 ;
goto success ; /* close enough for government work */
}
1995-04-26 07:43:35 +00:00
/* Now check the packing list for dependencies */
for ( p = Plist . head ; p ; p = p - > next ) {
1995-04-26 15:06:26 +00:00
char * isTMP = NULL ; /* local copy for depends only */
1995-04-26 07:43:35 +00:00
if ( p - > type ! = PLIST_PKGDEP )
continue ;
if ( Verbose )
printf ( " Package `%s' depends on `%s' " , pkg , p - > name ) ;
if ( ! Fake & & vsystem ( " pkg_info -e %s " , p - > name ) ) {
1995-04-26 15:06:26 +00:00
char path [ FILENAME_MAX ] , * cp = NULL ;
1995-04-26 07:43:35 +00:00
if ( Verbose )
printf ( " which is not currently loaded " ) ;
1995-04-26 15:06:26 +00:00
if ( ! isURL ( p - > name ) ) {
1995-06-11 19:33:05 +00:00
snprintf ( path , FILENAME_MAX , " %s/%s.tgz " , Home , p - > name ) ;
1995-04-26 15:06:26 +00:00
if ( fexists ( path ) )
cp = path ;
else
cp = fileFindByPath ( p - > name ) ;
}
else {
cp = fileGetURL ( p - > name ) ;
isTMP = cp ;
1995-04-26 07:43:35 +00:00
}
1995-04-26 15:06:26 +00:00
if ( cp ) {
1995-04-26 07:43:35 +00:00
if ( Verbose )
printf ( " but was found - loading: \n " ) ;
1995-04-26 15:06:26 +00:00
if ( ! Fake & & vsystem ( " pkg_add %s " , cp ) ) {
whinge ( " Autoload of dependency `%s' failed%s " ,
p - > name , Force ? " (proceeding anyway) " : " ! " ) ;
1995-04-26 07:43:35 +00:00
if ( ! Force )
+ + code ;
}
else if ( Verbose )
printf ( " \t `%s' loaded successfully. \n " , p - > name ) ;
1995-04-26 15:06:26 +00:00
/* Nuke the temporary URL copy */
if ( isTMP ) {
unlink ( isTMP ) ;
isTMP = NULL ;
}
1995-04-26 07:43:35 +00:00
}
else {
if ( Verbose )
printf ( " and was not found%s. \n " ,
Force ? " (proceeding anyway) " : " " ) ;
else
printf ( " Package dependency %s for %s not found%s \n " ,
p - > name , pkg ,
1995-04-26 15:06:26 +00:00
Force ? " (proceeding anyway) " : " ! " ) ;
1995-04-26 07:43:35 +00:00
if ( ! Force )
+ + code ;
}
}
else if ( Verbose )
printf ( " - already installed. \n " ) ;
}
1995-04-26 15:06:26 +00:00
/* If this is a direct extract and we didn't want it, stop now */
if ( where_to ! = PlayPen & & Fake )
goto success ;
1995-04-22 13:58:24 +00:00
/* Finally unpack the whole mess */
if ( unpack ( pkg_fullname , NULL ) ) {
whinge ( " Unable to extract `%s'! " , pkg_fullname ) ;
goto bomb ;
1993-09-05 04:53:51 +00:00
}
1995-04-22 13:58:24 +00:00
1995-04-26 07:43:35 +00:00
/* Check for sanity and dependencies */
1995-04-22 13:58:24 +00:00
if ( sanity_check ( pkg_fullname ) )
goto bomb ;
1993-09-05 04:53:51 +00:00
/* 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 ) ;
1993-10-10 20:25:31 +00:00
return 0 ;
1993-09-05 04:53:51 +00:00
}
1993-08-26 01:19:55 +00:00
}
1994-12-06 00:51:50 +00:00
1995-04-26 07:43:35 +00:00
/* Look for the requirements file */
1993-08-26 01:19:55 +00:00
if ( fexists ( REQUIRE_FNAME ) ) {
vsystem ( " chmod +x %s " , REQUIRE_FNAME ) ; /* be sure */
if ( Verbose )
printf ( " Running requirements file first for %s.. \n " , PkgName ) ;
1993-10-08 01:19:35 +00:00
if ( ! Fake & & vsystem ( " ./%s %s INSTALL " , REQUIRE_FNAME , PkgName ) ) {
1994-12-06 00:51:50 +00:00
whinge ( " Package %s fails requirements %s " ,
pkg_fullname ,
Force ? " installing anyway " : " - not installed. " ) ;
if ( ! Force ) {
code = 1 ;
goto success ; /* close enough for government work */
}
1993-08-26 01:19:55 +00:00
}
}
1995-04-26 07:43:35 +00:00
/* If we're really installing, and have an installation file, run it */
1993-08-26 01:19:55 +00:00
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 ) ;
1993-10-08 01:19:35 +00:00
if ( ! Fake & & vsystem ( " ./%s %s PRE-INSTALL " , INSTALL_FNAME , PkgName ) ) {
1993-08-26 01:19:55 +00:00
whinge ( " Install script returned error status. " ) ;
1995-04-22 13:58:24 +00:00
unlink ( INSTALL_FNAME ) ;
1994-12-06 00:51:50 +00:00
code = 1 ;
goto success ; /* nothing to uninstall yet */
1993-08-26 01:19:55 +00:00
}
}
1995-04-26 07:43:35 +00:00
/* Now finally extract the entire show if we're not going direct */
if ( where_to = = PlayPen & & ! Fake )
extract_plist ( home , & Plist ) ;
if ( ! Fake & & fexists ( MTREE_FNAME ) ) {
1994-12-06 00:51:50 +00:00
if ( Verbose )
printf ( " Running mtree for %s.. \n " , PkgName ) ;
p = find_plist ( & Plist , PLIST_CWD ) ;
if ( Verbose )
1995-04-28 04:16:30 +00:00
printf ( " mtree -U -f %s -d -e -p %s \n " , MTREE_FNAME ,
1994-12-06 00:51:50 +00:00
p ? p - > name : " / " ) ;
1995-04-28 04:16:30 +00:00
if ( ! Fake ) {
if ( vsystem ( " /usr/sbin/mtree -U -f %s -d -e -p %s " ,
MTREE_FNAME , p ? p - > name : " / " ) )
whinge ( " mtree returned a non-zero status - continuing. " ) ;
}
1995-04-22 13:58:24 +00:00
unlink ( MTREE_FNAME ) ;
1994-12-06 00:51:50 +00:00
}
1995-04-26 07:43:35 +00:00
1995-04-26 15:06:26 +00:00
/* Run the installation script one last time? */
1993-08-26 01:19:55 +00:00
if ( ! NoInstall & & fexists ( INSTALL_FNAME ) ) {
if ( Verbose )
printf ( " Running install with POST-INSTALL for %s.. \n " , PkgName ) ;
1993-10-08 01:19:35 +00:00
if ( ! Fake & & vsystem ( " ./%s %s POST-INSTALL " , INSTALL_FNAME , PkgName ) ) {
1993-08-26 01:19:55 +00:00
whinge ( " Install script returned error status. " ) ;
1995-04-22 13:58:24 +00:00
unlink ( INSTALL_FNAME ) ;
1994-12-06 00:51:50 +00:00
code = 1 ;
1993-08-26 01:19:55 +00:00
goto fail ;
}
1995-04-22 13:58:24 +00:00
unlink ( INSTALL_FNAME ) ;
1993-08-26 01:19:55 +00:00
}
1995-04-26 07:43:35 +00:00
1995-04-26 15:06:26 +00:00
/* Time to record the deed? */
1993-08-26 01:19:55 +00:00
if ( ! NoRecord & & ! Fake ) {
1993-09-05 04:53:51 +00:00
char contents [ FILENAME_MAX ] ;
FILE * cfile ;
1994-12-06 00:51:50 +00:00
umask ( 022 ) ;
1993-08-26 01:19:55 +00:00
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 */
}
1995-04-19 14:02:01 +00:00
sprintf ( LogDir , " %s/%s " ,
( tmp = getenv ( PKG_DBDIR ) ) ? tmp : DEF_LOG_DIR ,
basename_of ( PkgName ) ) ;
1993-08-26 01:19:55 +00:00
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 */
}
1993-09-18 03:38:48 +00:00
/* Make sure pkg_info can read the entry */
vsystem ( " chmod a+rx %s " , LogDir ) ;
1993-08-26 01:19:55 +00:00
if ( fexists ( DEINSTALL_FNAME ) )
1995-04-22 13:58:24 +00:00
move_file ( " . " , DEINSTALL_FNAME , LogDir ) ;
1993-08-26 01:19:55 +00:00
if ( fexists ( REQUIRE_FNAME ) )
1995-04-22 13:58:24 +00:00
move_file ( " . " , REQUIRE_FNAME , LogDir ) ;
1993-09-05 04:53:51 +00:00
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 ) ;
1995-04-22 13:58:24 +00:00
move_file ( " . " , DESC_FNAME , LogDir ) ;
move_file ( " . " , COMMENT_FNAME , LogDir ) ;
1994-12-06 00:51:50 +00:00
if ( fexists ( DISPLAY_FNAME ) )
1995-04-22 13:58:24 +00:00
move_file ( " . " , DISPLAY_FNAME , LogDir ) ;
1994-12-06 00:51:50 +00:00
for ( p = Plist . head ; p ; p = p - > next ) {
if ( p - > type ! = PLIST_PKGDEP )
continue ;
if ( Verbose )
printf ( " Attempting to record dependency on package `%s' \n " ,
p - > name ) ;
1995-04-19 14:02:01 +00:00
sprintf ( contents , " %s/%s/%s " ,
( tmp = getenv ( PKG_DBDIR ) ) ? tmp : DEF_LOG_DIR ,
basename_of ( p - > name ) , REQUIRED_BY_FNAME ) ;
1994-12-06 00:51:50 +00:00
cfile = fopen ( contents , " a " ) ;
1995-06-11 19:33:05 +00:00
if ( ! cfile )
whinge ( " Warning: Can't open dependency file '%s'! \n \t Dependency registration is incomplete. " , contents ) ;
else {
fprintf ( cfile , " %s \n " , basename_of ( PkgName ) ) ;
if ( fclose ( cfile ) = = EOF )
warn ( " Cannot properly close file %s " , contents ) ;
1994-12-06 00:51:50 +00:00
}
}
1993-08-26 01:19:55 +00:00
if ( Verbose )
printf ( " Package %s registered in %s \n " , PkgName , LogDir ) ;
}
1995-05-30 03:57:47 +00:00
1994-12-06 00:51:50 +00:00
if ( p = find_plist ( & Plist , PLIST_DISPLAY ) ) {
FILE * fp ;
char buf [ BUFSIZ ] ;
fp = fopen ( p - > name , " r " ) ;
if ( fp ) {
putc ( ' \n ' , stdout ) ;
while ( fgets ( buf , sizeof ( buf ) , fp ) )
fputs ( buf , stdout ) ;
putc ( ' \n ' , stdout ) ;
( void ) fclose ( fp ) ;
} else
warn ( " Cannot open display file `%s'. " , p - > name ) ;
}
1993-08-26 01:19:55 +00:00
goto success ;
1995-04-22 13:58:24 +00:00
bomb :
code = 1 ;
goto success ;
1993-08-26 01:19:55 +00:00
fail :
1994-12-06 00:51:50 +00:00
/* Nuke the whole (installed) show, XXX but don't clean directories */
1993-08-26 01:19:55 +00:00
if ( ! Fake )
1994-12-06 00:51:50 +00:00
delete_package ( FALSE , FALSE , & Plist ) ;
1993-08-26 01:19:55 +00:00
success :
/* delete the packing list contents */
leave_playpen ( ) ;
1995-04-26 15:06:26 +00:00
if ( isTMP )
unlink ( isTMP ) ;
1993-08-26 01:19:55 +00:00
return code ;
}
static int
sanity_check ( char * pkg )
{
1995-04-26 07:43:35 +00:00
PackingList p ;
int code = 0 ;
1993-08-26 01:19:55 +00:00
if ( ! fexists ( CONTENTS_FNAME ) ) {
whinge ( " Package %s has no CONTENTS file! " , pkg ) ;
1995-04-26 07:43:35 +00:00
code = 1 ;
1993-08-26 01:19:55 +00:00
}
1995-04-26 07:43:35 +00:00
else if ( ! fexists ( COMMENT_FNAME ) ) {
1993-08-26 01:19:55 +00:00
whinge ( " Package %s has no COMMENT file! " , pkg ) ;
1995-04-26 07:43:35 +00:00
code = 1 ;
1993-08-26 01:19:55 +00:00
}
1995-04-26 07:43:35 +00:00
else if ( ! fexists ( DESC_FNAME ) ) {
1993-08-26 01:19:55 +00:00
whinge ( " Package %s has no DESC file! " , pkg ) ;
1995-04-26 07:43:35 +00:00
code = 1 ;
1993-08-26 01:19:55 +00:00
}
1995-04-26 07:43:35 +00:00
return code ;
1993-08-26 01:19:55 +00:00
}
void
cleanup ( int signo )
{
1993-09-05 04:53:51 +00:00
if ( signo )
printf ( " Signal %d received, cleaning up.. \n " , signo ) ;
1993-08-26 01:19:55 +00:00
if ( Plist . head ) {
if ( ! Fake )
1994-12-06 00:51:50 +00:00
delete_package ( FALSE , FALSE , & Plist ) ;
1993-08-26 01:19:55 +00:00
free_plist ( & Plist ) ;
}
if ( ! Fake & & LogDir [ 0 ] )
vsystem ( " %s -rf %s " , REMOVE_CMD , LogDir ) ;
leave_playpen ( ) ;
}