home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / unix / aux / 4587 / mksystem.perl < prev   
Encoding:
Text File  |  1993-01-10  |  8.6 KB  |  419 lines

  1. #!/usr/local/bin/perl
  2. #
  3. # mksystem
  4. #
  5. # Set up a local System folder, with local extensions.
  6. #
  7.  
  8. # Initialize parameters and parse the command line
  9.  
  10. $CHOWN = 0;
  11. $force = 0;
  12. $user = "";
  13. while ( $#ARGV >= 0 )
  14. {
  15.     if ( $ARGV[0] eq '-f' )
  16.     {
  17.         # Force copying of System File
  18.         $force = 1;
  19.         shift(@ARGV);
  20.     }
  21.     elsif ( $ARGV[0] eq '-u' )
  22.     {
  23.         # Build system folder on behalf of another user
  24.         $CHOWN = 1;
  25.         $user = $ARGV[1];
  26.         if ( $user eq "" )
  27.         {
  28.             &usage;
  29.         }
  30.         shift(@ARGV);
  31.         shift(@ARGV);
  32.     }
  33.     elsif ( substr($ARGV[0],0,2) eq '-u' )
  34.     {
  35.         # Build system folder on behalf of another user
  36.         $CHOWN = 1;
  37.         $user = substr($ARGV[0],2);
  38.         shift(@ARGV);
  39.         shift(@ARGV);
  40.     }
  41.     else
  42.     {
  43.         # Display usage message
  44.         &usage;
  45.     }
  46. }
  47.  
  48. # Locate the files to be contained in the local System Folder.  XX-PRODUCTS-XX
  49. # is substituted with the directory containing local extensions as it is
  50. # set up in the Makefile.
  51.  
  52. $systemdir = '/mac/lib/SystemFiles';
  53. $systemfolder = '/mac/sys/System Folder';
  54. $products = 'XX-PRODUCTS-XX';
  55.  
  56. # Read our umask for use later
  57.  
  58. $umask = umask;
  59. umask($umask);
  60.  
  61. # Get the home directory of the user who will own the new local System Folder.
  62. # If the owner is not the same as the invoker, then we need the owner's
  63. # uid and default gid for chown.
  64.  
  65. if ( $CHOWN )
  66. {
  67.     ($p_name,$p_passwd,$p_uid,$p_gid,$p_quota,$p_comment,$p_gcos,$HOME) =
  68.         getpwnam($user);
  69. }
  70. else
  71. {
  72.     ($p_name,$p_passwd,$p_uid,$p_gid,$p_quota,$p_comment,$p_gcos,$HOME) =
  73.         getpwuid($<);
  74.     $p_uid = $<;
  75.     $p_gid = $(;
  76. }
  77.  
  78. if ( $HOME eq '' )
  79. {
  80.     print STDERR "User <$user> not listed in /etc/passwd!\n";
  81.     exit 1;
  82. }
  83.  
  84. # Compute the name of the local System Folder based on how mksystem was
  85. # invoked; it has two names:  mksystem and mksystem24.
  86.  
  87. if ( substr($0,-2,2) eq "24" )
  88. {
  89.     $mydir = "$HOME/System Folder24";
  90. }
  91. else
  92. {
  93.     $mydir = "$HOME/System Folder";
  94. }
  95.  
  96. # Look for Apple's system files.
  97.  
  98. if ( ! -d $systemdir )
  99. {
  100.     print STDERR "$0:  Cannot find global system folder $systemdir.\n";
  101.     exit 1;
  102. }
  103.  
  104. # Check permissions on the new local System Folder, creating it if necessary.
  105.  
  106. if ( -f $mydir )
  107. {
  108.     print STDERR "$0: Cannot create '$mydir'.\n";
  109.     print STDERR "A regular file by that name currently exists.\n";
  110.     exit 1;
  111. }
  112. elsif ( -d $mydir )
  113. {
  114.     if ( ! -w $mydir )
  115.     {
  116.         print STDERR "$0: cannot update $mydir.  Permission denied.\n";
  117.         exit 1;
  118.     }
  119.     print "System Folder '$mydir' already exists - updating.\n";
  120.     if ( $force == 0 )
  121.     {
  122.         print "\n";
  123.         print STDERR "CAUTION: Existing private (writable) files will ";
  124.         print STDERR "not be updated.\n";
  125.         print STDERR "         Use the force option (-f) to update ";
  126.         print STDERR "these files!\n";
  127.     }
  128. }
  129. else
  130. {
  131.     print "Creating System Folder '$mydir'\n";
  132.     $newdir = 1;
  133.     if ( mkdir($mydir,( 0777 & ~ $umask )) eq 0 )
  134.     {
  135.         print STDERR "Cannot create $mydir:\n$!\n";
  136.         exit 1;
  137.     }
  138. }
  139.  
  140. # Always want local stuff in favor of Apple stuff.  Therefore, if
  141. # forced, want to do the local stuff last.  Otherwise do the local
  142. # stuff first.
  143.  
  144. if ( $force )
  145. {
  146.     &appleStuff;
  147.     &localStuff;
  148. }
  149. else
  150. {
  151.     &localStuff;
  152.     &appleStuff;
  153. }
  154.  
  155. # This subroutine copies $old to $new, using the command specified in $how.
  156. # $how contains a Unix command with "$old" representing the source file and
  157. # "$new" representing the destination file.  For example:  "/bin/cp $old $new".
  158. # File names are treated in an 8-bit clean fashion.
  159.  
  160. sub copyFile
  161. {
  162.     local($how,$old,$new) = @_;
  163.     local(@args,$arg);
  164.  
  165.     @args = split(/ /,$how);
  166.     foreach $arg ( 0 .. $#args )
  167.     {
  168.         eval("\$args[\$arg] = \"$args[$arg]\"");
  169.     }
  170.     &spawn(@args);
  171. }
  172.  
  173. # This subroutine copies a directory.  Regular files are copied according
  174. # to the "how" parameter, which includes an "$old" keyword specifying the
  175. # source of the copy, and a "$new" keyword specifying the destination of
  176. # the copy.  The "src" parameter specifies the source directory, and the
  177. # "dest" parameter specifies the destination directory, which may or may
  178. # not exist prior to invoking copyDir.  The "force" parameter causes regular
  179. # files to be copied, even if the destination already exists.  Ownerships
  180. # of the files copied and directories created are set to the "uid" and
  181. # "gid" parameters.
  182.  
  183. sub copyDir
  184. {
  185.     local($how,$src,$dest,$force,$uid,$gid) = @_;
  186.     local(@dirs,$name,$this,$spath,$dpath,$status,$s_dev,$s_ino,$s_mode);
  187.  
  188.     # Initialize the directory list
  189.     @dirs = ( '.' );
  190.  
  191.     # Copy each directoy in the directory list.
  192.     while ( ( $this = shift(@dirs) ) ne "" )
  193.     {
  194.         # "." is a special case, and we don't want to have dots
  195.         # in paths of files that we copy.  Looks bad when the copy
  196.         # is really a symbolic link.
  197.         if ( $this eq '.' )
  198.         {
  199.             $dpath = $dest;
  200.             $spath = $src;
  201.         }
  202.         else
  203.         {
  204.             $dpath = "$dest/$this";
  205.             $spath = "$src/$this";
  206.         }
  207.  
  208.         # See that the dest directory exists.
  209.         if ( -d $dpath )
  210.         {
  211.             0; # Do nothing
  212.         }
  213.         elsif ( -e $dpath )
  214.         {
  215.             print STDERR "Cannot create directory $dpath, ";
  216.             print STDERR "as it already exists\n";
  217.             next;
  218.         }
  219.         else
  220.         {
  221.             if ( mkdir($dpath,(0777 & ~ $umask)) == 0 )
  222.             {
  223.                 print STDERR "Unable to create $dpath:\n$!\n";
  224.                 next;
  225.             }
  226.         }
  227.  
  228.         # Copy everything in the src directory to the dest directory,
  229.         # except for . and ..
  230.         if ( opendir(DIR,$spath) eq "" )
  231.         {
  232.             print STDERR "Unable to read directory $spath:\n$!\n";
  233.             next;
  234.         }
  235.         while ( ( $name = readdir(DIR) ) ne "" )
  236.         {
  237.             if ( ( $name eq '.' ) ||
  238.                  ( $name eq '..' ) )
  239.             {
  240.                 next;
  241.             }
  242.  
  243.             # Remove . from paths.  They look bad when the copy
  244.             # of regular files are really symbolic links.
  245.             if ( $this eq '.' )
  246.             {
  247.                 $spath = "$src/$name";
  248.                 $dpath = "$dest/$name";
  249.             }
  250.             else
  251.             {
  252.                 $spath = "$src/$this/$name";
  253.                 $dpath = "$dest/$this/$name";
  254.             }
  255.             if ( -d $spath )
  256.             {
  257.                 # Src is a directory, add it to the directory
  258.                 # list for later processing.
  259.                 if ( $this eq '.' )
  260.                 {
  261.                     unshift(@dirs,"$name");
  262.                 }
  263.                 else
  264.                 {
  265.                     unshift(@dirs,"$this/$name");
  266.                 }
  267.             }
  268.             else
  269.             {
  270.                 # Copy a regular file
  271.                 if ( $this eq '.' )
  272.                 {
  273.                     print "\t$name\n";
  274.                 }
  275.                 else
  276.                 {
  277.                     print "\t$this/$name\n";
  278.                 }
  279.  
  280.                 # Forced copy, unlink the destination file
  281.                 # if it already exists.
  282.                 if ( ( -e $dpath ) && ( $force ) )
  283.                 {
  284.                     unlink($dpath);
  285.                 }
  286.  
  287.                 # Copy the file, if the dest doesn't already
  288.                 # exist, and change ownership if needed.
  289.                 if ( ! -e $dpath )
  290.                 {
  291.                     ©File($how,$spath,$dpath);
  292.                     ( $s_dev,$s_ino,$s_mode ) =
  293.                         stat($dpath);
  294.                     chmod(($s_mode | 0200),$dpath);
  295.                     if ( $uid != $< )
  296.                     {
  297.                         chown($uid,$gid,$dpath);
  298.                     }
  299.                 }
  300.             }
  301.         }
  302.         closedir(DIR);
  303.     }
  304.  
  305.     # Change the ownership of the directory just processed.  This is
  306.     # done afterwards so that we have write permission into the directory
  307.     # for making copies.
  308.     if ( $uid != $< )
  309.     {
  310.         chown($uid,$gid,"$dest/$this");
  311.     }
  312. }
  313.  
  314. # This subroutine copies system files distributed with A/UX
  315.  
  316. sub appleStuff
  317. {
  318.     # Create subdirectories; copy or link files
  319.     print "Shared files ...\n";
  320.     ©Dir('/bin/ln -s $old $new',"$systemdir/shared",$mydir,1,
  321.              $p_uid,$p_gid);
  322.  
  323.     print "Private files ...\n";
  324.     ©Dir('/bin/cp $old $new',"$systemdir/private",$mydir,
  325.              $force,$p_uid,$p_gid);
  326.  
  327.     foreach $file ( "Desktop DF", "Desktop DB", ".fs_cache", ".fs_dirIDs" )
  328.     {
  329.         $spath = "$systemfolder/$file";
  330.         $dpath = "$mydir/$file";
  331.         if ( ( ! -f $dpath ) && ( -f $spath ) )
  332.         {
  333.             ©File('/bin/cp $old $new',$spath,$dpath);
  334.         }
  335.     }
  336. }
  337.  
  338. # This subroutine copies products installed locally for private system files.
  339.  
  340. sub localStuff
  341. {
  342.     # Copy products
  343.     if ( ( -d $products ) && ( opendir(PDIR,$products) ne "" ) )
  344.     {
  345.         # Scan each product
  346.         while ( ( $this = readdir(PDIR) ) ne "" )
  347.         {
  348.             # Skip if . or ..
  349.             if ( ( $this eq '.' ) || ( $this eq '..' ) )
  350.             {
  351.                 next;
  352.             }
  353.  
  354.             # Copy a specific product.  First create symlinks
  355.             # to the sharable files, then copy the ones that must
  356.             # be unique.
  357.             print "$this ...\n";
  358.             $spath = "$products/$this/shared";
  359.             if ( -d $spath )
  360.             {
  361.                 ©Dir('/bin/ln -s $old $new',$spath,
  362.                          $mydir,1,$p_uid,$p_gid);
  363.             }
  364.             $spath = "$products/$this/private";
  365.             if ( -d $spath )
  366.             {
  367.                 ©Dir('/bin/cp $old $new',$spath,
  368.                          $mydir,$force,$p_uid,$p_gid);
  369.             }
  370.         }
  371.         closedir(PDIR);
  372.     }
  373. }
  374.  
  375. # This subroutine spawns a child process and waits for it to finish.  The
  376. # command line is treated in an 8-bit clean fashion.
  377.  
  378. sub spawn
  379. {
  380.     local($forking);
  381.  
  382.     $forking = 1;
  383.     while ( $forking )
  384.     {
  385.         if ( $pid = fork )
  386.         {
  387.             waitpid($pid,0);
  388.             $forking = 0;
  389.         }
  390.         elsif ( defined $pid )
  391.         {
  392.             exec(@_);
  393.             print STDERR "Failed to exec \'@_'\n";
  394.             die;
  395.         }
  396.         elsif ( $! =~ /No more process/ )
  397.         {
  398.             sleep(5);
  399.         }
  400.         else
  401.         {
  402.             print "Failed to fork:  $!\n";
  403.             die;
  404.         }
  405.     }
  406. }
  407.  
  408. # This subroutine displays a usage message.
  409.  
  410. sub usage
  411. {
  412.     print 'usage: mksystem [-f] [-u user]\n';
  413.     print '       mksystem24 [-f] [-u user]\n';
  414.     exit 1;
  415. }
  416.  
  417. ### End of File ###
  418.  
  419.