From: paul@hal.COM (Paul Sander)
Newsgroups: comp.unix.aux
Subject: systemfolder replacement
Summary: Helps when products are installed in System Folder
Date: 10 Jan 93 07:10:27 GMT
Organization: HaL Computer Systems, Inc.
NNTP-Posting-Host: parlo.hal.com

When I upgraded to A/UX 3.0, I found it difficult to upgrade the A/UX
desktop because I had a bunch of stuff installed so that people creating
personal System Folders would pick up the additional software.  (Examples
of such things are additional fonts, inits, and so on.)  I had wished that
I could easily separate out the installed products so that I could easily
upgrade each individual product as well as the A/UX system software.

Here is a Perl (4.019) script that replaces the systemfolder script and
builds a personal System Folder based on files that have been installed
in /mac/lib/SystemFiles and also other product-specific directories.

Unpack the following sharchive.  It will produce the Perl script, a Makefile,
and a man page.  Edit the Makefile to install the script in the right place,
and select a convenient location for the product directories.  Then do a
"make" to build the final product and format the man page.  Then do a 
"make install" to install the script and the man page.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Makefile mksystem.perl mksystem.man
# Wrapped by paul@sander on Sat Jan  9 18:18:27 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(1016 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# Makefile for mksystem
X
X# Set this to the directory containing files that extend the System Folder.
XPRODUCTS=/usr2/mac/SystemFiles
X
X# Set this to the install point of the script
XDESTDIR=/usr/local/bin
X
X# Set this to the directory containing local man pages
XMANDIR=/usr/catman/l_man/man1
X
Xall: mksystem mksystem24 mksystem.1 mksystem24.1
X
Xmksystem: mksystem.perl
X	sed -e "s@XX-PRODUCTS-XX@$(PRODUCTS)@g" mksystem.perl > mksystem
X	chmod 755 mksystem
X
Xmksystem24: mksystem
X	ln mksystem mksystem24
X
Xmksystem.1: mksystem.man
X	sed -e "s@XX-PRODUCTS-XX@$(PRODUCTS)@g" mksystem.man | nroff -man | \
X		col -b > mksystem.1
X
Xmksystem24.1: mksystem.1
X	ln mksystem.1 mksystem24.1
X
Xinstall: mksystem mksystem.1
X	cp mksystem $(DESTDIR)/mksystem
X	chmod 755 $(DESTDIR)/mksystem
X	ln $(DESTDIR)/mksystem $(DESTDIR)/mksystem24
X	cp mksystem.1 $(MANDIR)/mksystem.1
X	pack $(MANDIR)/mksystem.1
X	chmod 644 $(MANDIR)/mksystem.1.z
X	ln $(MANDIR)/mksystem.1.z $(MANDIR)/mksystem24.1.z
X
Xclean:
X	rm -f mksystem mksystem24 mksystem.1 mksystem24.1
END_OF_Makefile
if test 1016 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mksystem.perl -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mksystem.perl\"
else
echo shar: Extracting \"mksystem.perl\" \(8816 characters\)
sed "s/^X//" >mksystem.perl <<'END_OF_mksystem.perl'
X#!/usr/local/bin/perl
X#
X# mksystem
X#
X# Set up a local System folder, with local extensions.
X#
X
X# Initialize parameters and parse the command line
X
X$CHOWN = 0;
X$force = 0;
X$user = "";
Xwhile ( $#ARGV >= 0 )
X{
X	if ( $ARGV[0] eq '-f' )
X	{
X		# Force copying of System File
X		$force = 1;
X		shift(@ARGV);
X	}
X	elsif ( $ARGV[0] eq '-u' )
X	{
X		# Build system folder on behalf of another user
X		$CHOWN = 1;
X		$user = $ARGV[1];
X		if ( $user eq "" )
X		{
X			&usage;
X		}
X		shift(@ARGV);
X		shift(@ARGV);
X	}
X	elsif ( substr($ARGV[0],0,2) eq '-u' )
X	{
X		# Build system folder on behalf of another user
X		$CHOWN = 1;
X		$user = substr($ARGV[0],2);
X		shift(@ARGV);
X		shift(@ARGV);
X	}
X	else
X	{
X		# Display usage message
X		&usage;
X	}
X}
X
X# Locate the files to be contained in the local System Folder.  XX-PRODUCTS-XX
X# is substituted with the directory containing local extensions as it is
X# set up in the Makefile.
X
X$systemdir = '/mac/lib/SystemFiles';
X$systemfolder = '/mac/sys/System Folder';
X$products = 'XX-PRODUCTS-XX';
X
X# Read our umask for use later
X
X$umask = umask;
Xumask($umask);
X
X# Get the home directory of the user who will own the new local System Folder.
X# If the owner is not the same as the invoker, then we need the owner's
X# uid and default gid for chown.
X
Xif ( $CHOWN )
X{
X	($p_name,$p_passwd,$p_uid,$p_gid,$p_quota,$p_comment,$p_gcos,$HOME) =
X		getpwnam($user);
X}
Xelse
X{
X	($p_name,$p_passwd,$p_uid,$p_gid,$p_quota,$p_comment,$p_gcos,$HOME) =
X		getpwuid($<);
X	$p_uid = $<;
X	$p_gid = $(;
X}
X
Xif ( $HOME eq '' )
X{
X	print STDERR "User <$user> not listed in /etc/passwd!\n";
X	exit 1;
X}
X
X# Compute the name of the local System Folder based on how mksystem was
X# invoked; it has two names:  mksystem and mksystem24.
X
Xif ( substr($0,-2,2) eq "24" )
X{
X	$mydir = "$HOME/System Folder24";
X}
Xelse
X{
X	$mydir = "$HOME/System Folder";
X}
X
X# Look for Apple's system files.
X
Xif ( ! -d $systemdir )
X{
X	print STDERR "$0:  Cannot find global system folder $systemdir.\n";
X	exit 1;
X}
X
X# Check permissions on the new local System Folder, creating it if necessary.
X
Xif ( -f $mydir )
X{
X	print STDERR "$0: Cannot create '$mydir'.\n";
X	print STDERR "A regular file by that name currently exists.\n";
X	exit 1;
X}
Xelsif ( -d $mydir )
X{
X	if ( ! -w $mydir )
X	{
X		print STDERR "$0: cannot update $mydir.  Permission denied.\n";
X		exit 1;
X	}
X	print "System Folder '$mydir' already exists - updating.\n";
X	if ( $force == 0 )
X	{
X		print "\n";
X		print STDERR "CAUTION: Existing private (writable) files will ";
X		print STDERR "not be updated.\n";
X		print STDERR "         Use the force option (-f) to update ";
X		print STDERR "these files!\n";
X	}
X}
Xelse
X{
X	print "Creating System Folder '$mydir'\n";
X	$newdir = 1;
X	if ( mkdir($mydir,( 0777 & ~ $umask )) eq 0 )
X	{
X		print STDERR "Cannot create $mydir:\n$!\n";
X		exit 1;
X	}
X}
X
X# Always want local stuff in favor of Apple stuff.  Therefore, if
X# forced, want to do the local stuff last.  Otherwise do the local
X# stuff first.
X
Xif ( $force )
X{
X	&appleStuff;
X	&localStuff;
X}
Xelse
X{
X	&localStuff;
X	&appleStuff;
X}
X
X# This subroutine copies $old to $new, using the command specified in $how.
X# $how contains a Unix command with "$old" representing the source file and
X# "$new" representing the destination file.  For example:  "/bin/cp $old $new".
X# File names are treated in an 8-bit clean fashion.
X
Xsub copyFile
X{
X	local($how,$old,$new) = @_;
X	local(@args,$arg);
X
X	@args = split(/ /,$how);
X	foreach $arg ( 0 .. $#args )
X	{
X		eval("\$args[\$arg] = \"$args[$arg]\"");
X	}
X	&spawn(@args);
X}
X
X# This subroutine copies a directory.  Regular files are copied according
X# to the "how" parameter, which includes an "$old" keyword specifying the
X# source of the copy, and a "$new" keyword specifying the destination of
X# the copy.  The "src" parameter specifies the source directory, and the
X# "dest" parameter specifies the destination directory, which may or may
X# not exist prior to invoking copyDir.  The "force" parameter causes regular
X# files to be copied, even if the destination already exists.  Ownerships
X# of the files copied and directories created are set to the "uid" and
X# "gid" parameters.
X
Xsub copyDir
X{
X	local($how,$src,$dest,$force,$uid,$gid) = @_;
X	local(@dirs,$name,$this,$spath,$dpath,$status,$s_dev,$s_ino,$s_mode);
X
X	# Initialize the directory list
X	@dirs = ( '.' );
X
X	# Copy each directoy in the directory list.
X	while ( ( $this = shift(@dirs) ) ne "" )
X	{
X		# "." is a special case, and we don't want to have dots
X		# in paths of files that we copy.  Looks bad when the copy
X		# is really a symbolic link.
X		if ( $this eq '.' )
X		{
X			$dpath = $dest;
X			$spath = $src;
X		}
X		else
X		{
X			$dpath = "$dest/$this";
X			$spath = "$src/$this";
X		}
X
X		# See that the dest directory exists.
X		if ( -d $dpath )
X		{
X			0; # Do nothing
X		}
X		elsif ( -e $dpath )
X		{
X			print STDERR "Cannot create directory $dpath, ";
X			print STDERR "as it already exists\n";
X			next;
X		}
X		else
X		{
X			if ( mkdir($dpath,(0777 & ~ $umask)) == 0 )
X			{
X				print STDERR "Unable to create $dpath:\n$!\n";
X				next;
X			}
X		}
X
X		# Copy everything in the src directory to the dest directory,
X		# except for . and ..
X		if ( opendir(DIR,$spath) eq "" )
X		{
X			print STDERR "Unable to read directory $spath:\n$!\n";
X			next;
X		}
X		while ( ( $name = readdir(DIR) ) ne "" )
X		{
X			if ( ( $name eq '.' ) ||
X			     ( $name eq '..' ) )
X			{
X				next;
X			}
X
X			# Remove . from paths.  They look bad when the copy
X			# of regular files are really symbolic links.
X			if ( $this eq '.' )
X			{
X				$spath = "$src/$name";
X				$dpath = "$dest/$name";
X			}
X			else
X			{
X				$spath = "$src/$this/$name";
X				$dpath = "$dest/$this/$name";
X			}
X			if ( -d $spath )
X			{
X				# Src is a directory, add it to the directory
X				# list for later processing.
X				if ( $this eq '.' )
X				{
X					unshift(@dirs,"$name");
X				}
X				else
X				{
X					unshift(@dirs,"$this/$name");
X				}
X			}
X			else
X			{
X				# Copy a regular file
X				if ( $this eq '.' )
X				{
X					print "\t$name\n";
X				}
X				else
X				{
X					print "\t$this/$name\n";
X				}
X
X				# Forced copy, unlink the destination file
X				# if it already exists.
X				if ( ( -e $dpath ) && ( $force ) )
X				{
X					unlink($dpath);
X				}
X
X				# Copy the file, if the dest doesn't already
X				# exist, and change ownership if needed.
X				if ( ! -e $dpath )
X				{
X					&copyFile($how,$spath,$dpath);
X					( $s_dev,$s_ino,$s_mode ) =
X					    stat($dpath);
X					chmod(($s_mode | 0200),$dpath);
X					if ( $uid != $< )
X					{
X						chown($uid,$gid,$dpath);
X					}
X				}
X			}
X		}
X		closedir(DIR);
X	}
X
X	# Change the ownership of the directory just processed.  This is
X	# done afterwards so that we have write permission into the directory
X	# for making copies.
X	if ( $uid != $< )
X	{
X		chown($uid,$gid,"$dest/$this");
X	}
X}
X
X# This subroutine copies system files distributed with A/UX
X
Xsub appleStuff
X{
X	# Create subdirectories; copy or link files
X	print "Shared files ...\n";
X	&copyDir('/bin/ln -s $old $new',"$systemdir/shared",$mydir,1,
X	         $p_uid,$p_gid);
X
X	print "Private files ...\n";
X	&copyDir('/bin/cp $old $new',"$systemdir/private",$mydir,
X	         $force,$p_uid,$p_gid);
X
X	foreach $file ( "Desktop DF", "Desktop DB", ".fs_cache", ".fs_dirIDs" )
X	{
X		$spath = "$systemfolder/$file";
X		$dpath = "$mydir/$file";
X		if ( ( ! -f $dpath ) && ( -f $spath ) )
X		{
X			&copyFile('/bin/cp $old $new',$spath,$dpath);
X		}
X	}
X}
X
X# This subroutine copies products installed locally for private system files.
X
Xsub localStuff
X{
X	# Copy products
X	if ( ( -d $products ) && ( opendir(PDIR,$products) ne "" ) )
X	{
X		# Scan each product
X		while ( ( $this = readdir(PDIR) ) ne "" )
X		{
X			# Skip if . or ..
X			if ( ( $this eq '.' ) || ( $this eq '..' ) )
X			{
X				next;
X			}
X
X			# Copy a specific product.  First create symlinks
X			# to the sharable files, then copy the ones that must
X			# be unique.
X			print "$this ...\n";
X			$spath = "$products/$this/shared";
X			if ( -d $spath )
X			{
X				&copyDir('/bin/ln -s $old $new',$spath,
X				         $mydir,1,$p_uid,$p_gid);
X			}
X			$spath = "$products/$this/private";
X			if ( -d $spath )
X			{
X				&copyDir('/bin/cp $old $new',$spath,
X				         $mydir,$force,$p_uid,$p_gid);
X			}
X		}
X		closedir(PDIR);
X	}
X}
X
X# This subroutine spawns a child process and waits for it to finish.  The
X# command line is treated in an 8-bit clean fashion.
X
Xsub spawn
X{
X	local($forking);
X
X	$forking = 1;
X	while ( $forking )
X	{
X		if ( $pid = fork )
X		{
X			waitpid($pid,0);
X			$forking = 0;
X		}
X		elsif ( defined $pid )
X		{
X			exec(@_);
X			print STDERR "Failed to exec \'@_'\n";
X			die;
X		}
X		elsif ( $! =~ /No more process/ )
X		{
X			sleep(5);
X		}
X		else
X		{
X			print "Failed to fork:  $!\n";
X			die;
X		}
X	}
X}
X
X# This subroutine displays a usage message.
X
Xsub usage
X{
X    print 'usage: mksystem [-f] [-u user]\n';
X    print '       mksystem24 [-f] [-u user]\n';
X    exit 1;
X}
X
X### End of File ###
X
END_OF_mksystem.perl
if test 8816 -ne `wc -c <mksystem.perl`; then
    echo shar: \"mksystem.perl\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mksystem.man -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mksystem.man\"
else
echo shar: Extracting \"mksystem.man\" \(3312 characters\)
sed "s/^X//" >mksystem.man <<'END_OF_mksystem.man'
X.TH MKSYSTEM 1 local sander
X.SH NAME
Xmksystem \- Make local system folder
X.SH SYNOPSIS
X.LP
Xmksystem [
X.B -f
X] [
X.B -u
X.I user
X]
X.LP
Xmksystem24 [
X.B -f
X] [
X.B -u
X.I user
X]
X.SH DESCRIPTION
XThe
X\fBmksystem\fR(1)
Xscript duplicates the action of the
X\fBsystemfolder\fR(1)
Xscript, except that
X\fBmksystem\fR(1)
Xalso installs third party software that ordinarily must be installed by
Xthe user.
X.LP
XThe third party software is located in the
XXX-PRODUCTS-XX
Xdirectory.  Each directory found there belongs to a different product, and
Xeach contains a "private" and "shared" directory that in turn contain the
Xwritable and read-only files, respectively, that make up the product.
XFiles contained in the "private" directory are copied to the user's personal
XSystem Folder, while files contained in the "shared" directory appear in the
Xuser's personal System Folder as symbolic links.
X.SH OPTIONS
X.TP 1i
X.B -f
XForces the update of the System file.  By default, the System file is not
Xupdated if it already exists in teh personal System Folder.  This convention
Xprevents overwriting personal fonts, desk accessories, and so on.
X.TP 1i
X\fB-u\fIuser\fR
XCreates a personal System Folder for the user designated by
X.IR user .
XThis option can only be used by the system administrator.  In this case,
Xthe System Folder is created in the home directory of the user designated
Xby
X.IR user .
X.SH FILES
X.TP 1i
X$HOME/System Folder
XDirectory corresponding to a new System Folder
X.TP 1i
X$HOME/System Folder24
XDirectory corresponding to a new System Folder for 24 bit mode
X.TP 1i
XXX-PRODUCTS-XX/*
XDirectories containing third party software
X.TP 1i
XXX-PRODUCTS-XX/*/private/*
XFiles that are copied into a new System Folder
X.TP 1i
XXX-PRODUCTS-XX/*/shared/*
XFiles that become links in a new System Folder
X.SH SEE ALSO
X.LP
Xstartmac(1M) in
X.I A/UX System Administrator's Reference
X.LP
XsystemFolder(1)
X.SH EXAMPLE
X.LP
XHere is an example directory structure that illustrates the installation of
Xfiles that are processed by
X.B mksystem
Xinto personal System Folders.  In this example, Adobe Type Manager and Adobe
XPlus Pack have been installed, and a System file has been modified with local
Xchanges (e.g. new fonts and sounds have been added).
X.LP
XXX-PRODUCTS-XX
X.RS .2i
X    Adobe Type Manager
X.RS .2i
X      shared
X.RS .2i
X        Couri
X.br
X        CouriBol
X.br
X        CouriBolObl
X.br
X        CouriObl
X.br
X        Helve
X.br
X        HelveBol
X.br
X        HelveBolObl
X.br
X        HelveObl
X.br
X        Symbo
X.br
X        TimesBol
X.br
X        TimesBolIta
X.br
X        TimesIta
X.br
X        TimesRom
X.RE
X      private
X.RS .2i
X        ~ATM 68020_030
X.br
X        Control Panels
X.RS .2i
X          ~ATM*
X.RE
X.RE
X.RE
X    Adobe Plus Pack
X.RS .2i
X      shared
X.RS .2i
X        AvantGarBoo
X.br
X        AvantGarBooObl
X.br
X        AvantGarDem
X.br
X        AvantGarDemObl
X.br
X        BookmDem
X.br
X        BookmDemIta
X.br
X        BookmLig
X.br
X        BookmLigIta
X.br
X        HelveNar
X.br
X        HelveNarBol
X.br
X        HelveNarBolObl
X.br
X        HelveNarObl
X.br
X        NewCenSchBol
X.br
X        NewCenSchBolIta
X.br
X        NewCenSchIta
X.br
X        NewCenSchRom
X.br
X        PalatBol
X.br
X        PalatBolIta
X.br
X        PalatIta
X.br
X        PalatRom
X.br
X        ZapfChaMedIta
X.br
X        ZapfDin
X.RE
X.RE
X    System
X.RS .2i
X      private
X.RS .2i
X        System
X.RE
X.RE
X.RE
END_OF_mksystem.man
if test 3312 -ne `wc -c <mksystem.man`; then
    echo shar: \"mksystem.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0

-- 
Paul M. Sander  (408) 379-7000  |  "If everything were easy, where would be
HaL Computer Systems, Inc.      |   the challenge?"
1315 Dell Avenue                |
Campbell, CA  95008  USA        |