# HG changeset patch # User Robert McIntyre # Date 1357645501 0 # Node ID d6bef198ae71788e613d067c8364dec2dfb12846 # Parent 0b7a589f6e9acfb2cfa903dc343c76bb645d660a add work by Matthias S. Benkmann which is the inspiration for this project. diff -r 0b7a589f6e9a -r d6bef198ae71 org/pkg.org --- a/org/pkg.org Tue Jan 08 10:59:30 2013 +0000 +++ b/org/pkg.org Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,56 @@ +The point of this system to to + +1. Determine the provenence of every file on my system. +2. Always have an "undo" button. + +These criteria have evolved from my frustrations +with my previous LFS system. + + +User expreience: + +Suppose I want to install emacs. + +here's a sample terminal session + +$ pkg emacs "a text editor" + > creating user emacs. + > cd /pkg/emacs + +$ wget http://emacs.com/emacs.tar.bz2 + > downloaded emacs.tar.bz2 + +$ unp emacs.tar.bz2; cd emacs; configure; + make install; + > install stuff.. + +$ hg st + > a bunch of files are added + +1. Say I don't want emacs after all. +$ hg purge; hg revert --all + +2. Complete emacs instilation + > hg addr; hg commit -m "emacs." + +(this commits as the emacs user) + +3. can examine provenance of information +$ pkg-examine emacs + > package emacs owns the following files: + > emacs + > man/emacs + > .... + +4. see all the commits that the "emacs" user made. +$ pkg-history emacs + > + +5. remove a package in its entirety +$ pkg-remove emacs + > removed + > + + + + diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_and_pkg_man.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_and_pkg_man.txt Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,1916 @@ + +AUTHOR: Matthias S. Benkmann
+ +DATE: 2007-10-20 + +LICENSE: Creative Commons Attribution-Share Alike 3.0 + (http://creativecommons.org/licenses/by-sa/3.0/) + +SYNOPSIS: More Control and Package Management using Package Users (v1.4) + +DESCRIPTION: +-You want to know which packages your files belong to ? +-You want to deinstall software that doesn't have make uninstall ? +-You are bothered by programs installed setuid root behind your back ? +-You don't like packages quietly overwriting files from other packages ? +-You don't like package managers like RPM ? +-YOU WANT TOTAL CONTROL USING ONLY UNIX BUILTINS ? + +ATTACHMENTS: +http://www.linuxfromscratch.org/hints/downloads/attachments/more_control_and_pkg_man/more_control_helpers.tar.bz2 + +PREREQUISITES: +For use with LFS book 6.2: Brain. +For use with LFS book later than 6.2: Brain (awake, good working condition). + +HINT: + +########################################################################### + Contents +########################################################################### + +1. Preface +2. Overview + +- PART 1: General Information - + +3. Package Users + 3.1 Introduction + 3.2 User Name + 3.3 Groups + 3.4 Home Directory +4. Common Problems + 4.1 Introduction + 4.2 General Procedure + 4.3 Permission Changes + 4.4 Ownership Changes + 4.5 Write to Non-Install Directory + 4.6 Delete or Overwrite File + 4.7 /sbin/ldconfig + 4.8 What Commands to Run as a Package User +5. The more_control_helpers Archive + 5.1 Overview + 5.2 The Wrappers + 5.3 add_package_user/install_package + 5.4 forall_direntries_from + 5.5 uninstall_package + 5.6 list_suspicious_files/list_suspicious_files_from + 5.7 list_package + 5.8 grep_all_regular_files_for + 5.9 The etc Directory + 5.10 Temporary Files + +- PART 2: LFS Specifics - + +6. Pre-Chroot Phase (Chapter 5) +7. Chroot Phase (Chapter 6) + 7.1 Preparations + 7.2 Walkthrough: Installing linux-libc-headers + 7.3 Known Issues with LFS Packages +8. Sanity Checks + 8.1 Suspicious Files + 8.2 References to Temporary Files + +- APPENDICES - + +A. Security Issues + A.1 NFS + A.2 Daemons +B. Package Categories +C. Acknowledgements and Changelog + + +########################################################################### + 1. Preface +########################################################################### + +Let's say I have written a program that you would like to use. To make it +easier for you I come over to install it for you. Would you give me the root +account and then leave the room ? No ? Then why do you give it to complete +strangers who you have never seen in your life, to install software packages +pulled from some Internet server, that come with no warranty and don't even +list their contents in the README, although they will happily spread them all +over your system ? + +It is a mystery why Unix admins who wouldn't even trust their employer with +more than a normal user account carelessly execute complex and incomprehensible +installation scripts with full root rights. + +Users and groups are the basic security principle in a Unix system. They have +been used successfully for a long time to monitor who has created a file and +to control who is allowed to delete or change it. But this control has only +been imposed on the files of ordinary users. What a waste! I suggest to extend +this control to all system files. + +The general idea is to create package users, i.e. user accounts with restricted +rights, to build and install software packages, rather than doing these tasks +as root. Not only does this give you more control over what build and install +scripts may or may not do, it can also serve as a quite useful package +management system. + + +############################################################################# + 2. Overview +############################################################################# + +This hint is divided into 3 parts. The first part contains general information +about the package user method. This part is the most important part of the +hint. Read it thoroughly. The second part explains how to apply the package +user method to the building of an LFS system. +Finally, part 3 of this hint is the Appendix with information that would not +fit anywhere else or that is not of general interest. + +It is inevitable that part 2 will become outdated with time as the LFS book +changes and new versions of the software packages used with LFS are released. +I make no attempt to track these changes. +When someone reports an issue with a package I will incorporate +it into the hint, but larger changes that might be required due to changes in +the LFS build methodology could take a long time to get included. The reason +for this (aside from lack of time) is that I consider part 2 as bonus material +that helps people get started but is not essential. Part 1 describes the +concepts, which are independent of package versions or the LFS book, and you +will have to rely on this information whenever part 2 fails. Don't forget +that part 2 only deals with the packages used by the LFS book. For all the +other packages you install on your system after that even an up-to-date +part 2 would offer no aid anyway. + +The previous paragraph might sound discouraging, and as you read more from the +hint it is possible that you get the impression that the package user +method is complicated, causes lots of difficult problems and is overall too +much trouble for anyone but a real hardcore admin with programming experience. +But you would be mistaken. +First of all, many things experienced as installation problems when working +with the package user system are in fact desirable features. +If `make install' fails for some package, because it attempts to install a +file with the same name as a pre-existing file from another package, you +should not curse the fact that you have to spend additional time to resolve +this issue. Instead you should be happy that you have been alerted of this +collision that, had it gone unnoticed, could have messed up your system in +more or less subtle ways. +Secondly, the package user system is not an all-or-nothing approach. It +works on a per-package basis. If a package gives you too much trouble, you +can always decide to chicken out and finish the installation as root. +Finally, the more_control_helpers archive provided with this hint contains +several useful scripts that automate many aspects of software installation +as a package user and, together with the tips given in this hint, add a lot +of value to the package user system. +So do not pass judgement until you have read at least the complete part 1, +including the description of the more_control_helpers. + + +---------------------- PART 1: General Information -------------------------- + + +############################################################################# + 3. Package Users +############################################################################# + + 3.1 Introduction + ---------------- + +The basic idea of this scheme is easily explained. Every package belongs to a +certain "package user". When you install a package, you build and install +the package as this package user, causing all files that are installed to be +owned by the package user. As a consequence all the usual package management +tasks can be comfortably achieved through the use of standard command line +utilities. A simple `ls -l ' will tell you, for instance, what package + belongs to and a `find -user ...' command allows you to perform an +operation on all the files belonging to a certain package, e.g. delete them +to uninstall the package. + +But package management is not all that package users are good for. Because +package users do not have root-rights, the installation of a package is +limited in what it can do. One thing that a package user is not allowed to do, +for example, is to overwrite files from a different package user. Clashes +between different packages that want to install a binary, library or header +file of the same name are more common than you might think. With package users +you never run the risk of package B's installation destroying files from +package A silently without you noticing. Every attempt of doing this during +package B's installation will cause a "Permission denied" or +"Operation not permitted" error so that you have the chance of taking +appropriate steps. +Another thing that package users are not allowed to do is install setuid root +binaries. The decision to make a binary setuid root is also something that a +prudent admin does not want to leave up to the creator of a software package. + +Usually package user accounts have no valid password so that only root can su +to a package user, which ensures that package users do not open an additional +way into the system and undermine security. But you *may* set passwords +anyway to allow a co-admin who you want to be able to install and maintain +certain software packages to do so without having access to the actual root +account. This co-admin could for instance install, delete, change additional +libraries which might be necessary for his workgroup. He would be unable, +though, to remove or modify libraries which don't belong to him/her, such as +libc. + + + 3.2 User Name + ------------- + +You don't need to drive yourself nuts trying to come up with 8 character +names for the package users. I always use the name of the package without +the version number, including dashes and possibly exceeding 8 characters in +length, e.g. "util-linux", and in the several years that I've been using this +scheme I have not encountered any problems, nor has anyone else reported +trouble. The 8-character limit on user names seems to be a thing of the past. + +TIP: + You can use bash's programmable completion feature to save yourself some + typing when entering commands that take a user name as an argument, such as + su, finger or pinky. The command + + complete -o default -o nospace -A user su finger pinky + + tells bash to tab-complete words as user names for the commands su, + finger and pinky. + With this in place you can simply type `su linux-li' and bash + will complete this to `su linux-libc-headers' (assuming that you have a + package user named "linux-libc-headers"). + "-o default" tells bash that if a suitable user name does not exist, the + default completion shall be attempted. + "-o nospace" prevents the addition of a space after the completed word. + + This is a very useful command to put into root's .bashrc and .bash_profile. + + BTW, at http://freshmeat.net/projects/bashcompletion/ + you can find a project that offers sophisticated completions for many + other commands. + + Or switch to zsh (http://freshmeat.net/projects/zsh/). It's more powerful + and less buggy than bash. + + + 3.3 Groups + ---------- + +Every package user belongs to at least 2 groups. One of these groups is +the "install" group, which all package users (and only package users) belong +to. All directories that packages are allowed to install stuff in belong to +the install group. This includes directories such as /bin and /usr/bin but +excludes directories like /root or /. +The directories owned by the install group are always group-writable. +This would be enough for the package management aspects, but without further +preparation this would not give added security or control because every +package could replace the files from a different package (the change would +be visible in the output from `ls -l', though). +For this reason all install directories get the sticky attribute. This +allows users to create new files and delete or modify their own files in +the directory, but files from other users can not be modified or removed. +In the rest of this hint, whenever the term "install directory" is used, it +refers to a directory that belongs to group install, is group-writable and +sticky. IOW, to turn into an install directory you would do + + chgrp install && chmod g+w,o+t + +Although the install group is crucial for the package user system, it is +implemented as a supplementary group, rather than as the primary group for +package users. This has at least 2 advantages. +One advantage is that this makes it easy to get a list of all packages +installed on the system with the command + + grep install /etc/group + +A more important point, however, is that the primary group is the +one that files created by the package user will belong to. So it will be +printed in the output of `ls -l' and is subject to find's "-group" test. +This makes it very useful for organizational purposes. +Following are some suggestions for how to use the primary group. + +1. group name = user name + + Under this scheme the package user for the bash package would be + bash:bash. `ls -l /bin/bash' would show something like this + + -rwxr-xr-x 1 bash bash 1731859 Feb 30 2005 /bin/bash + + An important advantage of this scheme is that the user information is + not lost when you make a file setuid root, which requires changing + the file's owner. Because of this advantage, this scheme is the one + recommended by this hint. However, the hint's instructions will work + fine if you choose a different scheme. + +2. group name = package category + + Under this scheme, you would have certain package categories, such as + games, system, net,... and bash, being a system program, would possibly + belong to the system group, so that `ls -l /bin/bash' would show something + like this + + -rwxr-xr-x 1 bash system 1731859 Jul 4 1776 /bin/bash + + This system is nice, but probably not as useful as #1 above, unless you + have a real use for this categorization. + For a possible categorization see Appendix B at the end of this hint. + +3. group name = identifier for a real group of people + + Under this scheme, the group would correspond to a real group of people in + meatspace, e.g. the group of admins responsible for the package. + If you need something like this you'll know best what it looks like and how + to implement it, so no further discussion of this method will be given here. + + + 3.4 Home Directory + ------------------ + +Although it is well possible not to have a valid home directory for package +users or to have just one home directory shared by all package users, that +would be a wasted opportunity. Having individual home directories for the +package users offers a nice way to organize tarballs, patches, build scripts, +notes and all the other per-package information that you accumulate with time. + +I suggest to use the home directory /usr/src/ for a package user +called with the contents detailed below. The more_control_helpers +archive contains scripts and skeleton files that implement this suggestion. + + .bash_profile: + You will usually want to have the same environment for all package + users, so it is a good idea to make .bash_profile a symbolic link + to a file in a central location. The more_control_helpers example + uses /etc/pkgusr/bash_profile for this purpose. + + .bashrc: + As for .bash_profile a symlink is a good idea for .bashrc. The + more_control_helpers example uses /etc/pkgusr/bashrc as link target. + Under normal circumstances package users are not + (and even can not be) used for logging into the system, so there + is little reason to distinguish between login and non-login shells + for package users. Therefore, the example bashrc from + more_control_helpers simply sources .bash_profile. + This makes sure that the same environment will be used, regardless + of whether `su ' or `su - ' is used to become + the package user. + + .project: + The contents of this file are printed by the commands + `finger -l ' and 'pinky -l ' so .project is a + good place for putting information about a package. You should + keep the contents of the .project files for your package users + up-to-date. + + source code: + The package user's home directory is the perfect place for storing + a package's source code. This includes tarballs for different + versions, CVS checkouts, unpacked source trees for building,... + + build script(s): + Package user installations require more careful examination of build + and install messages than installations done as root, because of + the package user-specific problems that can occur. Therefore it is + unwise to simply copy'n'paste installation instructions from the + LFS book. Build scripts allow you to use sophisticated output + redirection for logging purposes that is impractical for direct + entry on the command line. The build script skeleton included in + the more_control_helpers archive demonstrates this. + + +############################################################################ + 4. Common Problems +############################################################################ + + 4.1 Introduction + ---------------- + +Software installation is the crux of the package user system. Because +installation scripts are often written under the assumption that they will be +executed as root, they sometimes fail when executed by a package user. +Once this hurdle is passed and a package has been installed, there's usually no +difference to a root-installation. A few programs insist that certain +security-sensitive files be owned by root and will not execute otherwise, +but this is the rare exception. +This chapter presents some more or less common problems that you will +encounter when using package user accounts to install software, together with +guidelines on how to deal with these issues. +Although I've said it before I will say it again: Many of the problems you +encounter during a package user installation are desirable features of the +package user system. You want installation to fail rather than have +potentially dangerous actions performed behind your back with root rights. + + + 4.2 General Procedure + --------------------- + +When an installation fails it is almost always due to a "Permission denied" +or "Operation not permitted" error while executing a command during +`make install'. The first thing you have to do is identify the command that +is causing the problem. Usually you will find this in the make output right +before the error message. Once you have identified the culprit, you have to +decide whether the action that is attempted is illegitimate, partially +legitimate or completely legitimate. Illegitimate commands can simply be +removed from the Makefile. The other 2 possibilities are more difficult to +deal with. You either have to change the condition that makes the command fail +or you have to change or sometimes remove the command and make a note if your +change suppresses a legitimate action. + +After you've made changes to solve a certain problem, you reattempt the +installation and solve any remaining problems until the installation +succeeds. Once you've reached that point it is time to perform any remaining +legitimate actions that you've had to disable, such as make certain binaries +setuid root. + +Note that often Makefiles are generated during the configure step, sometimes +even later in the build process. If you want to apply changes before the +configure step you will usually have to edit files called "Makefile.in". + + + 4.3 Permission Changes + ---------------------- + +Some unsophisticated build systems that don't use the mkinstalldirs script to +create installation target directories are very poorly written. Instead of +testing whether a target directory exists, they simply attempt to create +it with default permissions. This problem usually manifests as a line such +as "install -d $(prefix)/bin" in the Makefile. In the common case where +prefix=/usr this would attempt to create the /usr/bin directory. If the target +directory already exists, as in this case, install will attempt to change its +permissions to the default permissions (or those passed on the command line). +Of course a package user is not allowed to change the permissions of +/usr/bin and so the command fails with a message like +"install: cannot change permissions of `/usr/bin': Operation not permitted" +This is an example of a completely illegitimate command. Just remove it from +the Makefile and everything's fine. + + + 4.4 Ownership Changes + --------------------- + +The most common situation when a package wants to change the ownership of +files during installation is when it wants to install setuid root binaries. +A common command to do this would be something like +"install -c -m 4755 -o root name /usr/bin/name" and the error message would +look like this: +"install: cannot change ownership of `name': Operation not permitted" +The change of ownership is hidden in the "-o root" switch to install, which +tells it to make the target file owned by root. +The command is at least partially legitimate, because you probably want the +binary to be installed. Whether you actually want it to be setuid root is +a different matter. The fact that a binary is commonly installed as setuid +root doesn't mean that you should make it so. You'll have to ask yourself if +normal users absolutely need to execute that binary. If you think they can +live without it you're better off not making it setuid root, because every +setuid root binary is a potential security hole. In any case you will +have to edit the Makefile and remove the offending switch, "-o root" in this +case, so that the installation can succeed. Note that this will cause the +binary to be installed setuid , which of course makes no sense at all. +If you don't intend to make the binary setuid root after the installation, it +is best to change the "-m 4755" to "-m 755", so that it won't be installed +setuid at all. + +TIP: + When you make a binary setuid root after the installation, use + `chown root /usr/bin/name' and not `chown root:root /usr/bin/name'. + This way you can keep original group of the file (i.e. the group of the + package user) intact. With the user name = group name scheme recommended for + package users this makes sure that you can identify the source package of + the binary even after making it setuid root. + Note that as a security measure chown resets the setuid bit, + so you will have to do `chmod u+s /usr/bin/name' after the chown. + + + 4.5 Write to Non-Install Directory + ---------------------------------- + +Sometimes packages want to create files or directories in non-install +directories. 3 situations have to be distinguished in this case. The 1st +possibility is that the target directory should be an install directory. +An example of this is /usr/share/aclocal. This directory is not among the +standard system directories created when building an LFS system. It will be +created by the first package that has files to install there and will be +owned by the corresponding package user. The next package that wants to write +in it will fail to install. The remedy is simple. Just make the directory an +install directory. You don't even need to be root to do it. The package user +that owns the directory has the rights to make that change. + +The 2nd possible reason for a package wanting to write to a non-install +directory is that the failing command is only partially legitimate, i.e. you +do want to have installed whatever it is meant to install, but you want it in +a different location. For example some packages install binaries that are not +meant to be called directly. The default location for these binaries is +sometimes called libexec and with prefix=/usr the package will attempt to +create /usr/libexec. In cases such as this you often don't have to change +any Makefiles. There is either a configure switch to change the directory in +question or it is just a matter of overriding a Makefile variable as in +`make libexecdir=/usr/lib install'. + +The 3rd possible reason for an attempt to write to a non-install directory is +that the command in question is illegitimate, i.e. you don't want to have +installed whatever the package wants to install. As usual with illegitimate +commands you can edit the Makefile and just remove them. In the case of +a whole directory whose installation you want to suppress it could be too +much effort to remove all of the offending commands that want to install +files there. In this case an approach similar to that from the previous +paragraph can be more effective. Either through configure switches or +overriding of variables you change the directory in question to something +like /foobar, where is the directory in which build +commands are run (i.e. usually the top of the unpackaged source +tree). This will cause the package to create the unwanted directory inside +the build tree, which doesn't cause any permission problems and has the nice +side effect that it'll be deleted together with the build directory when you +clean up after the build. + + + 4.6 Delete or Overwrite File + ---------------------------- + +In a perfect world one package should not mess with another package's files, +but in the real world conflicts do happen occasionally. While a normal +sysadmin installing as root won't notice this until it's too late, an admin +employing the package user system will have to deal with conflicts right away. +When a package tries to overwrite or delete a file or directory that is owned +by another package the attempt will fail. It will fail even inside install +directories because of the sticky bit. +Although sometimes difficult to implement, the solution to such a conflict is +easy to describe. You need to either remove (or rename) the old file or +directory before installing, or suppress the installation of the new file or +directory. The installation of individual binaries is sometimes easy to +prevent. If you find a line such as "PROGRAMS=foo bar fubar barfu" in the +Makefile and "foo" is the name of the conflicting binary, just try removing +it from that list. That may be sufficient to prevent it from being installed. + + + 4.7 /sbin/ldconfig + ------------------ + +Packages that install libraries sometimes run /sbin/ldconfig as part of their +installation so that the dynamic libraries are properly registered on the +system. Because a package user is not allowed to overwrite /etc/ld.so.cache +ldconfig fails. This failure is commonly ignored in Makefiles, but you should +take note of it anyway, because you need to run ldconfig as root after +the installation. Alternatively, the more_control_helpers contain a wrapper +program that calls /sbin/ldconfig and can be made setuid root. + + + 4.8 What Commands to Run as a Package User + ------------------------------------------ + +A common problem that new users of this hint have is to decide which commands +to run as a package user and which commands to run as root. The general rule +is that the only commands to run as a package user are those for building, +installing, removing and modifying the files that belong to *that* package +user's package. Everything else should be run as root as usual. +Some things you CAN/SHOULD NOT DO as a package user include + + - starting daemons + - running udevstart + - stripping /lib/* + + +############################################################################ + 5. The more_control_helpers Archive +############################################################################ + + 5.1 Overview + ------------ + +The more_control_helpers archive contains files to help you with building and +maintaining a system that uses the package user method. One thing that the +more_control_helpers archive contains are some LFS-specific temporary files +that are only needed for the building of your LFS system and will not remain +installed in a permanent location. Then there are the previously mentioned +example files that demonstrate the suggested use of the package user home +directories discussed earlier. Another group of files contained in the archive +is a set of scripts that help with package management aspects, such as +creating new package users and checking which files a particular package has +installed. Finally the more_control_helpers archive contains wrapper scripts +for some commands that handle many of the common problems discussed in the +previous chapter and make package user installations a lot easier. + + + 5.2 The Wrappers + ---------------- + +The previous chapter discussed some common problems encountered during +package user builds and how to solve them. The solution to an installation +failure usually requires editing of one or more Makefiles. Making such changes +manually is annoying, even if it happens only occasionally, and whenever you +reinstall a package you have to make the changes again. Sed scripts and patches +can help with the latter problem, but they still have to be custom fitted to +every package that needs them. There is a better solution, though. While there +exist countless ways to install files, only very few are commonly used by +packages. The 5 commands mkdir, chgrp, chown, chmod and install are responsible +for most of the problems that arise during an LFS installation. This +prompted me to write wrapper scripts for these 5 commands that recognize +certain problematic patterns and deal with them automatically. + +The instructions given in this hint in the LFS-specific part will instruct you +to install these wrappers in /usr/lib/pkgusr. If you do that and make sure +that this directory is the first entry in the PATH of every package user, then +they will save you a lot of time and effort in dealing with recurring issues. +Note that if you want to choose a directory other than /usr/lib/pkgusr for +the wrappers, you need to be careful. Some configure scripts ignore certain +locations. A subdirectory of /etc would not work, for instance, because /etc +is one of these locations. + +It is important that you understand the limitations of the wrapper scripts. +They can fix some problems without user intervention, such as turning +newly created directories in /usr/share/locale into install directories. +But other problems by their very nature require manual intervention. When a +program tries to install a setuid root binary, for instance, the wrapper +scripts will suppress the attempt to change ownership of an installed file to +root. While that allows `make install' to complete without error, it is only +a partial solution. The wrapper scripts can not (and should not) take away +your responsibility for deciding whether the program in question should be +setuid root and to make it so, if necessary. To account for this, the +wrapper scripts will output warning lines to standard error that start with +"***" whenever they encounter a situation that needs to be reviewed. +Following the "***" in the message will be the original command that the +installation attempted to perform. +You *must* check these "***" lines, examine the affected files or directories +and take appropriate action. Because of this it is imperative that you log +the messages output during a package installation and check these logs +religiously. The `build' script contained in the more_control_helpers archive +demonstrates some useful output redirection tricks to be used for this purpose. +The following 3 examples shall illustrate what kind of things you will have to +look for: + +Example 1: "*** install -c rsh -o root -m 4775 /usr/bin/rsh" + This message is output by the install wrapper during the installation of + inetutils. The package wants to install the rsh binary setuid root. The + install wrapper removes the "-o root" and changes the "-m 4775" to + "-m 755" before passing the command on to the real install program. + The important thing here is the "-m 4xxx", because this wants to set the + setuid bit. Some install scripts throw in a "-o root" for good measure + when installing an otherwise normal binary. In that case it's enough that + the install wrapper strips out the "-o root" and you don't have to take + further action. But when, as in the case of inetutils, the permissions + indicate an attempt to make a binary setuid or setgid, then you will have to + investigate. You need to decide if you want rsh to be setuid root and + if you decide you do, you need to become root and issue commands like this: + + chown root /usr/bin/rsh + chmod u+s /usr/bin/rsh + +TIP: + Be conservative with making binaries setuid. If you're unsure whether you + will ever use a program (as non-root), you probably don't want it to be + setuid root. Keep in mind that you can always make the change later when + you need it. When you apply this reasoning to rsh, for instance, you'll + probably end up not making it setuid root. + + +Example 2: "*** chgrp tty /usr/bin/write" + This is output by the chgrp wrapper during the util-linux installation. + The util-linux package wants to install the write program as setgid tty, + so that it is allowed to access other users' terminals. The chgrp wrapper + prevents the changing of the group and the chmod wrapper prevents the + setting of the setgid bit. You need to decide if you want the + program to be setgid and if you decide in favor of this, do as root + + chgrp tty /usr/bin/write + chmod g+s /usr/bin/write + + +Example 3: "*** install -d -m 755 /sbin" + This is also from the util-linux installation. Util-linux, for no good + reason, tries to recreate the /sbin directory. The install wrapper + prevents this and you don't have to take any further action. + + + 5.3 add_package_user/install_package + ------------------------------------ + +Whenever you install a new package on your system, you first have to create +a new user account, possibly create a new group and if you follow the advice +from this hint about making productive use of a package user's home directory, +you will have to set up that one, too. If you were to do all of this manually, +it would be a lot of work. The add_package_user and install_package scripts +in the more_control_helpers archive were written to automate this. + +The install_package script is the one you will normally use to prepare for +installing a new package. It takes 3 parameters: the description of the +package, the name of the package user account to create and the name of the +package user's primary group. So if you use the user=group scheme recommended +by this hint and are as creative with your package descriptions as I am, then +the command you'll use to prepare for installing package "foo" will be + + install_package foo foo foo + +This command does 2 things. First it calls the add_package_user script with +the provided name, group and description plus sensible default values for +add_package_user's other parameters. Then, after add_package_user has created +the package user account, install_package automatically uses the su-command +to switch to the newly created account. If the default .bashrc and +.bash_profile scripts you use for package users contain the command "cd" as do +the examples in the more_control_helpers archive, you will be put right into +your package user's home directory so that you can start installing right away. + +TIP: + The install_package script can be called with a single argument that will + be used as user name, group name and description. So instead of the above + command a simple `install_package foo' would have sufficed. + +The add_package_user script is responsible for the actual work of creating +a new package user account. Given a name, a group name and a description, it +will create a new user account with the provided primary group and the install +group as supplementary group. The groups will be created if necessary. +add_package_user takes several arguments that determine the numeric ranges from +which it will pick the new user's UID and the GIDs for groups it needs to +create. add_package_user does not only create the package user account. It +will set up a home directory for it, too. You can either specify the directory +or go with the default, which is /usr/src/, where is the name +provided for the new account. If the home directory already exists, its +ownership and that of any existing contents will be changed to the new user. +If it doesn't exist, it will be created. + +The contents of /etc/pkgusr/skel-package will be copied into the new package +user's home directory (without overwriting pre-existing files). +The more_control_helpers archive contains an example of a useful skel-package +directory. Note that symlinks are copied as symlinks, so skel-package is the +perfect place to put .bashrc and .bash_profile symlinks to a central location +that will ensure that all package user accounts have the same environment. +This is especially useful to make sure that all package users have the +wrappers directory in their PATH. + + + 5.4 forall_direntries_from + -------------------------- + +The forall_direntries_from script is a very useful tool for common package +management tasks. It can roughly be described as a shortcut for +"find / -user -or -group ", where is the +first parameter to forall_direntries_from and are the remaining +parameters. However, forall_direntries_from takes care of making sure that +only relevant filesystems are scanned and shields you from certain unpleasant +surprises such as "Oops, I forgot that -depth negates -prune and have +accidentally wiped out my home directory." or "Oops, I forgot to -prune /proc +and now I'm getting parity errors on my SCSI bus.". + +IMPORTANT NOTE: By default the forall_direntries_from script will only scan +the / filesystem and will not traverse other filesystems. If you have +relevant directories that need to be scanned on other filesystems, you will +need to edit the script and add the respective mount point(s) to the +fs_to_scan list at the beginning of the script. The most likely candidate for +addition is "/usr". + +Application examples: + +Example 1: Create a tar.gz archive of all files that belong to , e.g. + for installing on another machine without having to + recompile it there. + + forall_direntries_from -fprint0 /tmp/files.lst + tar --null -P -czf /tmp/archive.tar.gz --files-from=/tmp/files.lst + + +Example 2: Print out all setuid root binaries installed by . + (This only works if you use the user=group scheme.) + + forall_direntries_from -perm +u+s -print + + +Example 3: List all binaries in /bin and /usr/bin belonging to "me" (i.e. the + package user executing the command) in alphabetical order. + + forall_direntries_from $(whoami) -path "*/bin/*" -printf "%f\n" | sort + + +Example 4: Uninstall . + + See following section about the uninstall_package script. + + + 5.5 uninstall_package + --------------------- + +The uninstall_package script is basically a forall_direntries_from +application example in script form. The command `uninstall_package foo' +prints out the forall_direntries_from call that you have to use to delete +all the files of package "foo" (except for those in directories that +forall_direntries_from is instructed not to scan) together with some +explanations. So in order to delete the files from package foo, you would +execute `uninstall_package foo' and then copy'n'paste the command it prints +to the command line. As a safeguard the forall_direntries_from call has an +"echo" in front of the "rm" and "rmdir" calls, so if you execute it, the files +will not actually be deleted unless you remove both instances of "echo". +It is recommended that you execute the command once with the echos and check +the output to make sure that only the files you intend to be deleted are in +the list. After you've confirmed that, you can use the shell's history to +recall the command, edit out the instances of "echo" and remove the files +for real. + + + 5.6 list_suspicious_files/list_suspicious_files_from + ---------------------------------------------------- + +list_suspicious_files looks for filesystem entries that are out of the ordinary +in some way and prints a categorized list of them. Things that qualify as +suspicious include setuid and setgid binaries, world-writable files, symlinks +that are possibly broken, hard links, install directories with unusual +permissions and other stuff. You should run this script after you've finished +your new LFS system and in regular intervals after that. Investigate the +listing closely. + +TIP: + When you check the list of setuid and setgid files, don't forget to + look at the actual user or group ownership of the file. It's easy to forget + that, especially in the setuid case, because we often equate setuid with + setuid root since setuid is seldom used with other user accounts. + +list_suspicious_files_from takes a user or group name or a UID/GID as an +argument and reports suspicious entries only when they are owned by the given +user or group. Usually you would not call this script directly but instead +use list_package (described in the next section), whose output includes that +from list_suspicious_files_from. + +IMPORTANT NOTE: By default the list_suspicious_files script will only scan +the / filesystem and will not traverse other filesystems. If you have +relevant directories that need to be scanned on other filesystems, you will +need to edit the script and add the respective mount point(s) to the +fs_to_scan list at the beginning of the script. The most likely candidate for +addition is "/usr". + + + 5.7 list_package + ---------------- + +list_package tells you everything about a package's installed files. In +general you will want to execute something like + + list_package $(whoami) >pkg.lst + +right after installing a package and you can forget about the chronically +inaccurate content listings in the (B)LFS book. +The following (shortened) output for util-linux speaks for itself: + +PS1> list_package util-linux + +EXECUTABLES (in */bin or */sbin) + agetty, arch, blockdev, cal, cfdisk, [...] vidmode(->rdev), whereis, write + +EXECUTABLES WITH NO MANPAGE (in */bin or */sbin) + fsck.cramfs, mkfs.cramfs + +MANPAGE SUMMARIES OF EXECUTABLES (in */bin or */sbin) + agetty: alternative Linux getty + arch: print machine architecture + blockdev: call block device ioctls from the command line + cal: displays a calendar + cfdisk: Curses based disk partition table manipulator for Linux + chkdupexe: find duplicate executables + col: filter reverse line feeds from input + [...] + swapon: enable/disable devices and files for paging and swapping + tailf: follow the growth of a log file + tunelp: set various parameters for the lp device + ul: do underlining + umount: unmount file systems + vidmode: query/set image root device, RAM disk size, or video mode + whereis: locate the binary, source, and manual page files for a command + write: send a message to another user + +EXTRA MANPAGES + /usr/share/man/man5/fstab.5 + /usr/share/man/man5/nfs.5 + /usr/share/man/man8/sln.8 + +EXTRA EXECUTABLES (not in */bin or */sbin) + /usr/share/misc/getopt/getopt-parse.bash + /usr/share/misc/getopt/getopt-parse.tcsh + /usr/share/misc/getopt/getopt-test.bash + /usr/share/misc/getopt/getopt-test.tcsh + +ALL FILES + /etc/fdprm + /sbin/agetty + /sbin/blockdev + /sbin/cfdisk + /sbin/ctrlaltdel + /sbin/elvtune + /sbin/fdisk + /sbin/fsck.cramfs + /sbin/fsck.minix + /sbin/hwclock + /sbin/losetup + /sbin/mkfs + /sbin/mkfs.bfs + [...] + /usr/share/man/man8/rootflags.8 + /usr/share/man/man8/setfdprm.8 + /usr/share/man/man8/setsid.8 + /usr/share/man/man8/sfdisk.8 + /usr/share/man/man8/sln.8 + /usr/share/man/man8/swapoff.8 + /usr/share/man/man8/swapon.8 + /usr/share/man/man8/tunelp.8 + /usr/share/man/man8/umount.8 + /usr/share/man/man8/vidmode.8 + /usr/share/misc/getopt + /usr/share/misc/getopt/getopt-parse.bash + /usr/share/misc/getopt/getopt-parse.tcsh + /usr/share/misc/getopt/getopt-test.bash + /usr/share/misc/getopt/getopt-test.tcsh + +SETUID FILES + -rwsr-xr-x "/usr/bin/mount" root:util-linux + -rwsr-xr-x "/usr/bin/umount" root:util-linux + +SETGID FILES + -rwxr-sr-x "/usr/bin/write" util-linux:tty + +FILES WITH UNUSUAL PERMISSIONS + -rwsr-xr-x "/usr/bin/mount" root:util-linux + -rwsr-xr-x "/usr/bin/umount" root:util-linux + -rwxr-sr-x "/usr/bin/write" util-linux:tty + + +Note: list_package works regardless of the prefix you've installed the package + with, so you can for instance configure with --prefix=/opt/package and + list_package will work just fine (provided that /opt is on a + filesystem configured to be scanned by forall_direntries_from and + list_suspicious_files). + +Note: list_package only considers manpages actually owned by the package to + list. It will not consider manpages installed by another package. This + means that you may see executables identified as not having a manpage + although they do have one courtesy of another package + (usually man-pages). + + + 5.8 grep_all_regular_files_for + ------------------------------ + +This script is not really related to the package user system, but because of +its similarity to the other scripts I've included it anyway. The sole purpose +of this script is to identify files that store references to the build +environment, specifically the /tools directory. Such references may point out +problems, since the /tools directory is supposed to be transient. +Don't forget that results for unstripped binaries and libraries are not +reliable, because debugging information often includes references to the +build environment. These do not cause trouble (unless you're trying to debug +the objects in question after deleting /tools). + +IMPORTANT NOTE: By default the grep_all_regular_files_for script will only scan +the / filesystem and will not traverse other filesystems. If you have +relevant directories that need to be scanned on other filesystems, you will +need to edit the script and add the respective mount point(s) to the +fs_to_scan list at the beginning of the script. The most likely candidate for +addition is "/usr". + + + 5.9 The etc Directory + --------------------- + +If you follow the instructions provided in the LFS-specific part of this hint, +the contents of the etc directory will be installed in /etc/pkgusr. The +directory contains a bashrc and bash_profile for package users that takes +care of package user specific details such as putting the wrappers directory +at the beginning of the PATH and calling cd, so that `su ' will +put you right into the package user's home directory. Also contained in the +etc directory is a skel-package directory as used by +install_package/add_package_user to populate the home directories of newly +created package users. + + + 5.10 ldconfig.c + -------------------- + +A lot of packages contain libraries. Having to manually call /sbin/ldconfig +as root after installing these packages can become annoying. It would be +much easier if one could grant package users permission to use /sbin/ldconfig. +Making ldconfig setuid root would be a simple and effective solution, but +there are some pitfalls. First of all it is imperative that ordinary users +be prohibited from executing ldconfig with elevated privileges. Otherwise +an ordinary user can overwrite and possibly read arbitrary files on the +system. This can be prevented by making ldconfig owned by group install and +removing the o+x bit from the file mode. While this setup is no less secure +than running `make install' as root, one reason why we're using package users +is because we don't feel safe doing that. To protect against the (admittedly +very theoretical) danger of a malicious package user, the more_control_helpers +provide ldconfig.c. The only thing this program does is to call +`/sbin/ldconfig -v' with an empty environment. Because it doesn't evaluate +any user input and doesn't pass any user-provided data to ldconfig, it can +safely be made setuid root. + + + 5.11 Temporary Files + -------------------- + +3 files in the more_control_helpers archive are only used during the +installation of the base LFS system and are not installed permanently. +The first of them is the installdirs.lst file that contains a list of +directories that should be install directories. +The second file is sbin/useradd, which is a very primitive shell script that +adds a new entry to /etc/passwd. It allows us to add package users before +we have installed shadow, which provides a real useradd. +Finally there is groupadd, which is like useradd, only for /etc/group. +Both scripts, useradd as well as groupadd, do very little error checking and +only support the syntax needed by install_package/add_package_user. So don't +try anything funky with them. + + +------------------------ PART 2: LFS Specifics ------------------------------ + + +############################################################################# + 6. Pre-Chroot Phase (Chapter 5) +############################################################################# + +Build Chapter 5 explained by the LFS book with the following changes: + +coreutils: + After running `make install' for the coreutils + package, issue the following command (still from within the coreutils + build directory): + + cp src/su /tools/bin + + This installs the su binary. Coreutils doesn't install su when working as + non-root (which we do in Chapter 5), because su needs to be setuid root for + normal operation and a non-root user cannot install setuid root binaries. + But for our purposes (i.e. su'ing from root to a package user) a non-setuid + su is enough, so we just copy coreutils' su to /tools/bin without making it + setuid root. + +more_control_helpers: + When you have reached the end of Chapter 5, before you begin with Chapter 6 + you will need to install the helper scripts in the /tools directory so that + they are available once you've entered the chroot environment. Use the + following commands to install the more_control_helpers in /tools: + + cd /tools && + tar xjf /path/to/more_control_helpers.tar.bz2 && + cd more_control_helpers && + cp ./sbin/* /tools/bin + + Note that the target directory is "/tools/bin" in the cp command and + *not* "/tools/sbin", although the latter location would be more appropriate. + The reason for this is simply that the LFS instructions do not add + "/tools/sbin" to the PATH (and neither do the instructions in this hint). + + +############################################################################# + 7. Chroot Phase (Chapter 6) +############################################################################# + + 7.1 Preparations + ---------------- + +Enter the chroot environment and follow the instructions from the book up to +but *not* including the installation of the first package (which at the time of +this writing is linux-libc-headers). Now install the more_control_helpers +files in their proper locations on the new LFS system: + + cp -a /tools/more_control_helpers/etc /etc/pkgusr && + chown -R 0:0 /etc/pkgusr && + cp -a /tools/more_control_helpers/lib /usr/lib/pkgusr && + chown -R 0:0 /usr/lib/pkgusr && + cp /tools/more_control_helpers/bin/* /usr/bin && + cp /tools/more_control_helpers/sbin/* /usr/sbin && + rm /usr/sbin/{useradd,groupadd} + +Note that the useradd and groupadd scripts are not installed on the new LFS +system. These scripts are just temporary workarounds we will use as long as +the real useradd and groupadd are not available. Therefore they should only +be in /tools/bin. + +ATTENTION! If you decide to use a different directory than /usr/lib/pkgusr +for the wrappers, you have to be careful, because at least the glibc +configure script ignores certain directories when looking for programs. The +list of ignored directories for glibc includes, among others, everything that +starts with "/etc", "/usr/etc" and "/sbin". Wrappers put into a directory that +matches any of these patterns would be ineffective. + +Now it's time to create the install group: + + groupadd -g 9999 install + +The GID 9999 has been chosen because the default range used by +add_package_user for package user GIDs starts at 10000. Choose whatever number +you like. + +Once the install group has been created you have to turn all the directories +that packages will install files in into install directories. To make this +easier I have compiled a list of install directories that can be found in +the file /tools/more_control_helpers/installdirs.lst. The following command +uses this list to assign the necessary directories to the install group. +Note that you will get several error messages because of non-existent +directories. This is because the list contains some directories not created +by LFS. + + chown 0:9999 $(cat /tools/more_control_helpers/installdirs.lst) + +To be usable by package users, the directories will have to be group-writable +and should be sticky as has been explained in the beginning of this hint. +The following command sets the permissions appropriately. +You will get the same error messages as for the previous command. + + chmod ug=rwx,o=rxt $(cat /tools/more_control_helpers/installdirs.lst) + + + 7.2 Walkthrough: Installing linux-libc-headers + ---------------------------------------------- + +At this point everything has been set up for creating the first package +user. At the time of this writing the first package installed in the LFS +book is Linux-Libc-Headers, so this package will serve as an example for how +things are done. The command + + install_package 'Linux Headers' linux-libc-headers linux-libc-headers + +will create a package user with user and group name linux-libc-headers. +If you don't want to use the user=group scheme, change the last argument to +the desired group name. The description is arbitrary but needs to meet the +requirements for the description field of an /etc/passwd entry. + +TIP: + Remember that you can call install_package with just one argument, if you + want user name, group name and description to be the same. + +The directory /usr/src/linux-libc-headers will be set up as the home directory +for the package user, automatically populated with the contents of +/etc/pkgusr/skel-package. The install_package command also issues the command +`su - linux-libc-headers' to assume the identity of the newly created package +user. If you're using the bashrc and bash_profile scripts from the +more_control_helpers archive, you will be put straight into the directory +/usr/src/linux-libc-headers and your prompt will look like this + +package linux-libc-headers:/usr/src/linux-libc-headers> + +to show you that you're working as package user linux-libc-headers and +that your current working directory is /usr/src/linux-libc-headers. + +Use the command + + echo $PATH + +to verify that your PATH starts with "/usr/lib/pkgusr", the directory that +contains the wrappers, and ends with "/tools/bin". + +Now everything is prepared for installing the package according to the +instructions in the LFS book. Note that at the time of this writing the +LFS book tells you to execute a chown command to make sure that the headers +are owned by root. This is just because the packager has made a very common +mistake when creating the tarball for the headers: He has archived the files +with a non-root user/group assignment. When unpacking such a tarball as root, +the files end up being owned by some weird user/group combination, which may +open a security hole. When you're working as a package user this can not +happen and you don't want to chown the headers to root:root, because that +would defeat the whole point of installing the headers with a package user. +This is one of the small points on which you will have to deviate from the +standard LFS instructions when using package users. More package user related +issues with the current LFS book can be found in the next section. + +After you've installed the headers, simply issue the command + + exit + +to become root again. Now would be a good time to think about useful +customizations for /etc/pkgusr/{bash_profile,bashrc} and/or +/etc/pkgusr/skel-package, if you've not already customized them. +Once you're satisfied with your setup, install the rest of the packages. +The following section will help you with some problems that you will run into. + + + 7.3 Known Issues with LFS Packages + ---------------------------------- + +This section has details on the package user related problems you will face +when building your LFS system. You should copy the information from this +section to the INSTALL NOTES of the relevant .project files for the packages +concerned, together with any of your own notes. + +NOTE: If you're building by an LFS book later than 6.2 it is recommended that + you read this complete chapter before you start building any packages. + If your LFS version is 6.2 then it's fine to read this section package + by package as you progress with your build. + + +linux-libc-headers: + At the time of this writing the LFS book tells you to execute a chown + command to make sure that the headers are owned by root. This is just + because the packager has made a very common mistake when creating the + tarball for the headers: He has archived the files with a non-root + user/group assignment. When unpacking such a tarball as root, the files + end up being owned by some weird user/group combination, which may open + a security hole. When you're working as a package user this can not happen + and you don't want to chown the headers to root:root, because that would + defeat the whole point of installing the headers with a package user. + + There used to be another packaging error in the linux-libc-headers. + Version 2.6.12.0 (current as of this writing) doesn't have it anymore, + but older versions used to contain files with permissions set incorrectly. + All headers are supposed to be world-readable, but they weren't. More about + this later in the glibc notes. + + +man-pages: + If the name you use for the man-pages package user is not exactly + "man-pages", then you will have to change the variable "manpagesowner" + right at the beginning of the wrapper script `install'. + + Recent versions of man-pages contain POSIX manpages that the package + tries to install in /usr/share/man/man{0,1,3}p. There's also a manpage + that man-pages wants to install to /usr/share/man/man9. + As /usr/share/man is + not an install directory and the LFS book does not have instructions to + create these directories at the time of this writing, the installation + will fail and the respective man-pages will not be installed. + Possible remedies: + 1. Make /usr/share/man an install directory. + Consequence: All Packages will be able to create new subdirectories + in /usr/share/man. I find this undesirable because there are packages + that create directories for manpages in foreign languages that I + don't want. YMMV. + 2. Ignore the problem and live without the POSIX manpages. Unless + you are a developer (including script writer) who is interested + in writing portable programs/scripts this is a good solution. + 3. Create the directories /usr/share/man/man{0,1,3}p and man9 as root + prior to installing man-pages. You'll have to either chown them + to the man-pages package user or make them install directories. + This is my preferred solution. + + +glibc: + It is kind of unfortunate that the packaging error of libc-linux-headers + concerning the permissions doesn't exist in the current version. It + provided for a great learning experience. I've kept the following section + in the hint for this reason even though it doesn't apply anymore. Please + take the time to read it. + +--------------------- old stuff start ---------------------------------------- + Because of the error, the headers in /tools/include + are not world-readable. Unfortunately the LFS book (as of this writing) + does not correct this in Chapter 5 like it does in Chapter 6. For a + standard LFS build this is no problem, because glibc is built as root and + root can access everything regardless of permissions. + The glibc package user, however, does not have permission to access + these headers. This will cause several configure tests to fail, because + the respective test programs can not be compiled. + The end result is the error message "/lib/cpp fails sanity check", which + is completely nonsensical as we don't have a /lib/cpp. + + This is the perfect opportunity to introduce rule #1 of error diagnostics: + + NEVER TRUST DIAGNOSTIC MESSAGES ! + + There are 2 kinds of diagnostic messages: + + 1. Those that are unnecessary, because once you see which component has + failed, the source of the problem is obvious. + 2. Those that grossly misdiagnose the source of the problem and lead + you to draw the wrong conclusions. + + No, there is no other kind. Trust me ;-) + In this case, /lib/cpp has nothing to do with the problem. It doesn't + exist and that's fine. The message just wants to trick you into doing + something stupid such as create a symlink /lib/cpp -> /tools/bin/cpp. + But that would be totally wrong. Before you jump to any premature + conclusions you should always try to get as much *low-level* information + as you can. Diagnostic messages are *high-level* information. They + represent a filtered view of the problem, which is usually of little help. + Fortunately the message (the complete one, not the part quoted above) also + points at the source for the necessary low-level information. In this + case that is the file config.log (not to be confused with configure.log, + the file created by the build script included in the more_control_helpers + archive). + config.log is created by all autoconf-created configures (not just that + of glibc) and it contains, among other things, the test programs used by + configure and messages output while building and running them. Whenever a + configure script fails or gives weird results, check config.log. And + always remember rule #2 of error diagnostics + + ALWAYS START AT THE FIRST ERROR + + This seems pretty obvious, but nevertheless people commonly do the exact + opposite. It's just too tempting to start at the point of the final + failure and try to work backwards. In this case many people would open + config.log and scroll to the point of the failed /lib/cpp sanity check. + After all, that's what caused configure to abort and so that's what needs + to be fixed, right? WRONG! Someone who takes this approach just sees the + error message "/lib/cpp: No such file or directory" and is even more + convinced that a missing /lib/cpp symlink (or program) is the problem. + + The correct way to approach such a problem is to start at the beginning + of config.log, to scroll down to first error message and to check if it + is an issue that needs to be fixed (error messages in config.log are + not always signs for a problem). If the issue needs to be fixed, then + it needs to be fixed first, because all later errors could be rooted in + this issue (even if, no, *especially* if you don't believe this is the + case). + If we apply this advice to the problem at hand, we quickly get to the first + serious error in config.log: + + "/tools/include/linux/limits.h: Permission denied" + + A quick check with ls reveals that indeed the directory with the linux + headers is not world-readable, which is obviously wrong. The fix is + easy. Just make (as root) the header directories /tools/include/{linux,asm} + world-readable with commands similar to those the LFS book presents + in Chapter 6 for the installation of linux-libc-headers. + Once this change has been made, glibc's configure succeeds. +--------------------- old stuff end ----------------------------------------- + +TIP: + Even when configure completes successfully, you should still check the + output carefully to see if there is anything odd. E.g. if you're using + the wrappers, you should check that configure outputs the line + + checking for a BSD-compatible install... /usr/lib/pkgusr/install -c + + If configure detects a different install, such as /tools/bin/install, + something is wrong. Maybe there's a typo in the PATH for the package + user, or you've put the wrappers into a directory that is ignored by + configure. + + + With the wrappers the glibc build and install should work smoothly. + The wrapper script for install makes sure that the /usr/share/locale/* + directories become install directories so that other programs can install + their localized messages. + One thing that the wrappers do not take care of, + however, is the file /usr/share/info/dir. Because in the current LFS build + order glibc is the first package that installs info files, dir is owned by + and only writable by glibc. In order to allow other packages to install + info pages, execute the following commands as root: + + chown root:install /usr/share/info/dir && + chmod ug=rw,o=r /usr/share/info/dir + +NOTE: + glibc wants to install the program pt_chown as setuid root. If you install + as a package user, the program will get installed but not given root + privileges (because of the install wrapper). + The following info is from the glibc docs: + + One auxiliary program, `/usr/libexec/pt_chown', is installed setuid + `root'. This program is invoked by the `grantpt' function; it sets the + permissions on a pseudoterminal so it can be used by the calling + process. This means programs like `xterm' and `screen' do not have to + be setuid to get a pty. (There may be other reasons why they need + privileges.) If you are using a 2.1 or newer Linux kernel with the + `devptsfs' or `devfs' filesystems providing pty slaves, you don't need + this program; otherwise you do. The source for `pt_chown' is in + `login/programs/pt_chown.c'. + + So unless you're building a system that does not use devpts (which would + be quite unusual), this does not need to concern you. + +TIP: + In case you were wondering if you should create /etc/nsswitch.conf and + /etc/ld.so.conf as root or glibc, I recommend to assign all files that + you manually create or manually edit to the root account. That way you can + distinguish between those files that can be regenerated automatically and + those that can not. Assigning even automatically generated files to + root once you make the first manual edit, ensures that a later + reinstallation of a package won't silently do away with your manual tweaks. + +ldconfig: + Now that glibc has installed /sbin/ldconfig you can activate the ldconfig + wrapper if you want to. Perform the following steps as root + AFTER re-adjusting the toolchain, + just before starting with binutils: + + cd /usr/lib/pkgusr + gcc -O2 -W -Wall -o ldconfig ldconfig.c + chown root:install ldconfig + chmod u=rwxs,g=rxs,o= ldconfig + + These instructions make the ldconfig wrapper setuid root and setgid install + and prevent non-root users not in the install group from executing it. + The setuid root is required so that it can replace /etc/ld.so.cache. + The setgid install is not strictly required, but without it + /etc/ld.so.cache will end up with the group of the last package user that + touched it. If you use the user name=group name scheme this will cause the + more_control_helpers scripts to believe that /etc/ld.so.cache belongs to + the package in question which can be confusing. + +binutils: + Have you make /usr/share/info/dir group-writable as explained above in + the glibc notes? If you've missed that part, go back and do it now. + The installation of binutils should complete without problems. + It does however cause minor conflicts with autoconf (see later). + +NOTE: + At the time of this writing the version of bash used in the LFS book has + a bug that causes the list_package script to spit out errors and to list + all manpages of binutils (and other packages) as Broken. This bug is + already fixed by the bash patch used by the book but the patch is not + applied in chapter 5. Since the manpage summary functionality of + list_package requires man which is not installed until after bash is + rebuilt, this doesn't really matter, because while patching the + chapter 5 bash would get rid of the error messages, it wouldn't result + in usable manpage summaries. + + +gcc: + Because the /usr/lib/libgcc_s.so* symlinks created at the beginning of + Chapter 6 is owned by root, gcc's installation cannot remove it. + So you will have to remove it as root before `make install'. + Alternatively use + + chown -h gcc: /usr/lib/libgcc* + + to change ownership of the files in question after creating the gcc + package user. Note the -h option which has to be used to change + ownership of the symlinks themselves rather than their target files. + +db: + It should be obvious that you don't want to change the ownership of the + installed files. + + +coreutils: + Because the /bin/cat, /bin/pwd and /bin/stty symlinks are owned by root, + coreutils' installation cannot remove them. So you will have to remove + them manually before `make install'. Alternatively use the command + + chown -h coreutils: /bin/{cat,pwd,stty} + + after creating the coreutils package user. Note the -h switch that makes + chown change the ownership of the symlinks themselves rather than their + target files. + + The chapter 6 instructions move the coreutils binaries to /bin, including + the mv binary itself. You need to make sure that hashing is turned off + for this to work. The LFS book does this by putting `set +h' into the + LFS user's .bashrc. If you're following this hint, you're likely using + build scripts, so you need to put this command into the build script + before the mv commands. + +NOTE: + The man-pages package has already installed manpages for the binaries + from coreutils. The install wrapper will prevent coreutils from overwriting + those. This is done because the manpages from the man-pages package are + of superior quality (although not necessarily uptodate). + It also prevents errors during `make install' that + would otherwise occur because the coreutils package user cannot overwrite + manpages owned by another user. + If you don't like the above behaviour and would rather have the original + package manpages (because they are uptodate), you can set the variable + manpagesowner at the beginning of the install wrapper to a string that + doesn't correspond to a package user name (it must not be empty, though!). + If you do this, you will have to resolve manpage conflicts in another way. + The easiest way to handle this is probably to not install the man-pages + package at the beginning of Chapter 6 but at the end, after all the other + packages have already installed their manpages. Then you need only deal + with the conflicts once, when installing man-pages. + + +ncurses: + The installation of ncurses (like that of other packages that include + libraries) wants to run /sbin/ldconfig to update /etc/ld.so.cache. + This fails because the package user doesn't have permission to replace + /etc/ld.so.cache. + Making /etc/ld.so.cache group-writable by the install group doesn't help, + because the permissions would be reset on the next call to /sbin/ldconfig. + This error will usually not abort the installation and you can just + run /sbin/ldconfig manually as root afterwards. + Alternatively you can use the ldconfig wrapper as described earlier. + + +aclocal directory: + At the time of this writing the directory /usr/share/aclocal is + created during the bison installation. This directory contains + macros for autoconf. Other packages want to install + files into this directory, so you should make it writable by the install + group and sticky. + + +perl: + Before you do `make install', you will have to + `chown -h perl: /usr/bin/perl' so that the perl package user is allowed to + remove the /usr/bin/perl symlink. + + If you will install add-on packages for perl as their own package users + into /usr/lib/perl5/site_perl, then you will need to turn + /usr/lib/perl5/site_perl/ and its subdirectories into + install directories. You don't need to do this now as you'll notice it + anyway when installing a perl add-on fails. + + +autoconf: + The autoconf package wants to install its own copy of standards.info, + which fails because binutils has already installed this file. You can + either ignore the error or remove the binutils version of standards.info + before `make install'. + + +bash: + configure: + The bash configure script tests for the presence of the special devices + /dev/std* and /dev/fd/*. Unfortunately at the time of this writing the + test for /dev/fd/* is buggy (the test for /dev/stdin used to be broke, too + in bash-2.x, but has been fixed since). It ends up testing read access to + standard input, + which is the (pseudo)terminal you're building your system in. + Unfortunately su doesn't change ownership of the terminal device, so when + you're su'd to a package user account, the terminal still belongs to the + login user. As the package user doesn't have read access to the device, + the tests fail. + + There is a simple way to get around this. Simply run ./configure like this + + ./configure .... ' !) to refer to /dev/null. Unlike the terminal device, /dev/null is + world-readable and world-writable, so the tests succeed as they should. + If you don't like this trick, you can also chown the terminal device in + question (see `ls -la /dev/fd/0') to the package user before building + bash. + + make check: + When running the test suite as a package user, the test "run-test" will + fail with the output like this: + + 33d32 + < *** chmod g+s /tmp/test.setgid + 35c34 + < 1 + --- + > 0 + 64d62 + < *** chmod u+s /tmp/test.setuid + 66c64 + < 1 + --- + > 0 + 154c152 + < 1 + --- + > 0 + 160c158 + < 1 + --- + > 0 + + The first 2 failures are caused by the chmod wrapper which prevents the + test from setting the setuid and setgid bits and outputs the *** warning. + The failures are harmless. You can get rid of them by removing the wrappers + directory from the PATH before running the tests. + + The last 2 failures are not specific to package users but will occur + whenever you run the tests su'd to another user. The reasons are the same + as for the configure problem described earlier. The same solutions apply. + Either use chown (if you chowned before configure you're already + done, of course) or run make check like this + + make check now (i.e. start a login shell). + -build script now handles unpacking of tarballs and allows calling + the different stages individually. + -useradd uses the -s provided shell and no longer hardwires bash. + -chapter 6 bash notes now properly address the configure and + make check issues. + +2007-03-21 Matthias Benkmann + -changed forall_direntries_from to avoid warning message from find + when -depth is used. + -added 4.8 What Commands to Run as a Package User + +2005-12-22 Matthias Benkmann + -added advice on how to cope with the moving mv problem to + coreutils note. + +2005-11-13 Matthias Benkmann + -fixed list_suspicious_files and list_package to work with + recent more POSIX-conforming versions of GNU find + -released version 1.2 + +2005-01-01 Matthias Benkmann + -fixed bug in skel-package/build script that caused it to report + all steps as successful, even if they failed + -released version 1.1 + +2004-11-01 Matthias Benkmann + -capitalized title + -released version 1.0 + +2004-10-14 Matthias Benkmann + -started developing the more_control_helpers utilities + +2004-08-14 Matthias Benkmann + -started major rewrite (update for new LFS version, new hint + format, textual improvements,...) + +2002-04-20 Matthias Benkmann + -changed LFS VERSION header to be more conservative + -added
tags to the synopsis for the sake of the hints + index + -added group mmedia to the list of suggested groups + -submitted v0.8 + +2002-03-16 Matthias Benkmann + -added note, that on Linux make doesn't need to be setgid kmem + +2002-02-18 Matthias Benkmann + -added section "Security issues with NFS" + -submitted v0.7 + +2002-01-30 Matthias Benkmann + -added Changelog + -moved "chown 0.10000 `cat /tmp/installdirs`" command up (before + glibc package user is created) + -add_package_user: create home directory with "mkdir -p" + use $grpfile everywhere instead of /etc/group + -improved mammoth sentence in Introduction + -added note about possibility to have user name==group name + -source bashrc_basic in bashrc_package + -minor textual changes diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/README Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,4 @@ +These files are part of the hint +"More control and package management using package users (v1.4)" +You should be able to find it at +http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/bin/forall_direntries_from --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/bin/forall_direntries_from Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +#The following list should contain the mount points of all filesystems +#that are to be scanned as a space-separated list within parentheses. +#/ will usually be in this list and if you have /usr +#on a separate partition, it will also be in this list. Other non-special +#filesystems where package users could own files should also be put in this +#list. +#Mount points whose filesystems are special, such as procfs or sysfs must +#not be in this list. While a simple find on those special filesystems should +#be harmless, operations such as "-exec grep something" are NOT SAFE and may +#have HARMFUL SIDE-EFFECTS, especially when performed as root. +fs_to_scan=(/) + +#Files with a path prefix found in the following list are ignored. +#This list will usually contain the parent directory of your package users' +#home directories, because normally you don't want to scan those. You can +#also add other directories that will never contain package user files, such +#as /home. This reduces scan time. +#NOTE: The LFS-6.0 book uses a ramfs mounted on /dev and with that setup +#/dev does not need to be in the prune list. But since there is no requirement +#that /dev have its on filesystem it's better to prune it explicitly. +prune_prefixes=(/home /usr/src /dev /tools) #NO TRAILING SLASHES!!!! + +if [ $# -lt 1 -o "$1" = "--help" ]; then + echo 1>&2 + echo 1>&2 'USAGE: '"${0##*/}"' []' + echo 1>&2 + echo 1>&2 ' If contains no action other than -prune, -print will be' + echo 1>&2 ' executed for all matching files.' + echo 1>&2 ' Entries will be matched if group and/or user equals ' + echo 1>&2 ' (numeric UID/GID allowed).' + echo 1>&2 ' All matching entries will be acted on, including device special files, so' + echo 1>&2 ' you should be extra careful with the you provide!' + echo 1>&2 + exit 1 +fi + +#suppress ugly debug output from shell +trap ':' SIGPIPE + +ugname="$1" +shift 1 #remove user_or_group_name from argument list + +# Recent versions of find issue a warning if "-depth" is listed after a +# non-option argument. To prevent this warning if -depth is passed to +# this script, we pick up the "-depth" argument here to move it to the +# front later on. +depth="" +if [ "_$1" = "_-depth" ]; then + depth=-depth + shift 1 +fi + +ugmatcher=(-false) +#test if find accepts ugname as a user, and append to ugmatcher if it does +if find / -maxdepth 0 -user "$ugname" >/dev/null 2>&1 ; then + ugmatcher[${#ugmatcher[@]}]="-or" + ugmatcher[${#ugmatcher[@]}]="-user" + ugmatcher[${#ugmatcher[@]}]="$ugname" +fi +#test if find accepts ugname as a group, and append to ugmatcher if it does +if find / -maxdepth 0 -group "$ugname" >/dev/null 2>&1 ; then + ugmatcher[${#ugmatcher[@]}]="-or" + ugmatcher[${#ugmatcher[@]}]="-group" + ugmatcher[${#ugmatcher[@]}]="$ugname" +fi + +#if find accepted ugname as neither user nor group, then exit +if [ "${#ugmatcher[@]}" = 1 ]; then + echo 1>&2 'find does not accept `'"$ugname'"' as group or user name' + exit 1 +fi + +#construct find commands that match the prune_prefixes. Each prefix will be +#matched as -path -or -path /* +#so that the directory itself and all subdirectories are matched. +y=(\( -false) +for ((i=0; $i<${#prune_prefixes[@]}; i=$i+1)) +do + y[${#y[@]}]='-or' + y[${#y[@]}]=-path + y[${#y[@]}]="${prune_prefixes[$i]}" + y[${#y[@]}]='-or' + y[${#y[@]}]=-path + y[${#y[@]}]="${prune_prefixes[$i]}/*" +done +y[${#y[@]}]=')' + +#In the following find command, the part +# -not ( ( "${y[@]}" -prune ) -or "${y[@]}" ) +#is responsible for preventing the files that match prune_prefixes from +#being processed. The 2nd "${y[@]}" may seem redundant, but it isn't, because +#-prune has no effect and is always false when -depth is used. +#The -true before "$@" ensures that -depth can be passed as only parameter. +find "${fs_to_scan[@]}" $depth -xdev -noleaf \ + -not \( \( "${y[@]}" -prune \) -or "${y[@]}" \) \ + -and \( "${ugmatcher[@]}" \) -and \( -true "$@" \) diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/bin/grep_all_regular_files_for --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/bin/grep_all_regular_files_for Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,74 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +#The following list should contain the mount points of all filesystems +#that are to be scanned as a space-separated list within parentheses. +#/ will usually be in this list and if you have /usr +#on a separate partition, it will also be in this list. +#Mount points whose filesystems are special, such as procfs or sysfs must +#not be in this list. While a simple find on those special filesystems should +#be harmless, operations such as "-exec grep something" are NOT SAFE and may +#have HARMFUL SIDE-EFFECTS, especially when performed as root. +fs_to_scan=(/) + +#Files with a path prefix found in the following list are ignored. As the +#main function of this script is to help you find files that contain +#hardwired paths to /tools or other unwanted references to +#your build system, you will usually prune any directories that don't contain +#files of interest, such as /tools (whose files naturally refer to /tools) +#and your package users' home directories (which may also test positive if +#you have unpacked and configured sources lying around). +#NOTE: The LFS-6.0 book uses a ramfs mounted on /dev and with that setup +#/dev does not need to be in the prune list. But since there is no requirement +#that /dev have its on filesystem it's better to prune it explicitly. +prune_prefixes=(/home /usr/src /dev /tools) #NO TRAILING SLASHES!!! + +if [ $# -lt 1 -o "$1" = "--help" ]; then + echo 1>&2 + echo 1>&2 'USAGE: '"${0##*/}"' ' + echo 1>&2 + echo 1>&2 ' grep -l -- ' + echo 1>&2 ' will be executed for each *regular file* ' + echo 1>&2 ' ATTENTION! If you override the -l switch with a switch that makes grep' + echo 1>&2 ' output all individual matches rather than just the matching files,' + echo 1>&2 ' then DO NOT redirect output to a file that is in a directory that will be' + echo 1>&2 ' scanned, or you risk creating an endless loop that will cause your' + echo 1>&2 ' output file to grow till your disk is full.' + echo 1>&2 + exit 1 +fi + +#suppress ugly debug output from shell +trap ':' SIGPIPE + +#construct find commands that match the prune_prefixes. Each prefix will be +#matched as -path -or -path /* +#so that the directory itself and all subdirectories are matched. +y=(\( -false) +for ((i=0; $i<${#prune_prefixes[@]}; i=$i+1)) +do + y[${#y[@]}]='-or' + y[${#y[@]}]=-path + y[${#y[@]}]="${prune_prefixes[$i]}" + y[${#y[@]}]='-or' + y[${#y[@]}]=-path + y[${#y[@]}]="${prune_prefixes[$i]}/*" +done +y[${#y[@]}]=')' + +cmd_pre=(-type f -exec grep -l) +cmd_post=(-- {} \;) + +#In the following find command, the part +# -not ( ( "${y[@]}" -prune ) -or "${y[@]}" ) +#is responsible for preventing the files that match prune_prefixes from +#being processed. The 2nd "${y[@]}" may seem redundant, but it isn't, because +#-prune has no effect and is always false when -depth is used (which someone +#might do in the future). +#The -true before "$@" ensures that -depth can be passed as 1st parameter +#of $cmd_pre (should someone change it in the future). +find "${fs_to_scan[@]}" -xdev -noleaf \ + -not \( \( "${y[@]}" -prune \) -or "${y[@]}" \) \ + -and \( -true "${cmd_pre[@]}" "$@" "${cmd_post[@]}" \) diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/bin/list_package --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/bin/list_package Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,291 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +if [ $# -lt 1 -o \( $# -gt 1 -a "z$1" != "z:man" -a "z$1" != "z:mani" -a "z$1" != "z:lib" \) -o "$1" = "--help" ]; then + echo 1>&2 + echo 1>&2 'USAGE: '"${0##*/}"' ' + echo 1>&2 + echo 1>&2 ' Entries will be matched if group and/or user equals ' + echo 1>&2 ' (numeric UID/GID allowed).' + echo 1>&2 ' This script uses `forall_direntries_from'"'"' and `list_suspicious_files_from'"'." + echo 1>&2 + echo 1>&2 ' NOTE: Several minutes may pass before you see the first output.' + echo 1>&2 ' You should probably redirect output to a file for later reference.' + echo 1>&2 + echo 1>&2 ' WARNING! This program is for listing files from package users only!' + echo 1>&2 ' Do NOT use it to list files from untrusted users!' + echo 1>&2 ' An untrusted user could set up a manipulated manpage to exploit' + echo 1>&2 ' a bug in man when it is used to extract the summary!' + exit 1 +fi + +# KNOWN BUGS: +# - when extracting summaries from manpages, candidate manpages are considered +# in alphabetic order rather than the order used by the man command. +# The problem with this is that section 8, which contains manpages for +# admin commands, will be considered after lower-numbered sections. +# In the rare case that an admin command has the same name as a topic from +# a lower-numbered manpage installed by the same package, the summary will +# be taken from the wrong manpage. +# An example for such a clash are the faillog.5 and faillog.8 manpages from +# the shadow package. +# Because this problem is difficult to fix, rare and easily spotted (since +# the manpage that should have provided the summary will be listed under +# EXTRA MANPAGES) I won't fix it. + +ugname="$1" + +#suppress ugly debug output from shell +trap ':' SIGPIPE + +if [ $# -gt 1 ]; then + name="${2##*/}" + case "$1" in + :man) + name=${name%.gz} + name=${name%.bz2} + name=${name%.*} + echo $'command\2'"$name"$'\2man\2'"$2" ;; + :mani) + name=${name%.gz} + name=${name%.bz2} + name=${name%.*} + echo $'command\2'"$name"$'\2mani\2'"$2" ;; + :lib) + name=${name%.a} + name=${name%%.so*} + echo "lib $name" + ;; + esac + exit 0 +fi + +sanitize() { tr -c '[:print:]' '?' ; } + +# $1: +# $2: command\2\2cmd\2(->) +# $3: command\2\2man[i]\2 or +expand_command() +{ + sep=$'\2' + cmdname="$1" + cmdline="$2" + manline="$3" + linktarget="${cmdline##*${sep}}" + + if [ -z "$manline" ]; then + description='No manpage' + #the "l" at the beginning is just to make it sort after "lib" + echo -n "lmanlessbin $cmdname" | sanitize + echo + + else # if [ ! -z "$manline" ]; then + manpage=${manline##*${sep}} + manpagedir=${manpage%/*} + wsc='[[:space:],]\+' + # The cd $manpagedir is a workaround for a bug in man-db that causes it + # to attempt to resolve paths relative to cwd. + # The `t l;d;:l;n;b l' in the sed command is voodoo magic to make sed + # output only the first match but to keep eating up all input. I use this + # instead of `| head -n 1', because head breaks the pipe after doing + # its 1 line output, which (if it happens before sed has processed the + # complete input) freaks out man and causes it to emit a totally + # silly error message including "No such file or directory", which is + # annoying when you do testing without suppressing man's errors. + # The $'s/.\b\\(.\\)/\\1/g;s/\x1b[^m]\\+m//g' removes the backspace-based + # as well as ESC-based formatting from man's output. + description="$( { cd "$manpagedir/.." 2>/dev/null ; + COLUMNS=300 man "$manpage" 2>/dev/null || + echo " $name - Broken manpage" ; } | + sed $'s/.\b\\(.\\)/\\1/g;s/\x1b[^m]\\+m//g' | + sed -n "/^NAME/,/^[A-Z]/s/^.*${wsc}${cmdname}${wsc}.*-\+${wsc}\(.*\)/\1/p;t l;d;:l;n;b l" )" + if [ -z "$description" ]; then + description="$( cd "$manpagedir/.." 2>/dev/null ; + COLUMNS=300 man "$manpage" 2>/dev/null | + sed $'s/.\b\\(.\\)/\\1/g;s/\x1b[^m]\\+m//g' | + sed -n "s/^.*${wsc}..*${wsc}.*-\+${wsc}\(.*\)/\1/p;t l;d;:l;n;b l" )" + fi + test -z "$description" && description="Weird manpage" + fi + + echo -n "binexe $cmdname" | sanitize + test "$linktarget" != '(->)' && echo -n "$linktarget" | sanitize + echo + #the "lx" in "lxdescription" is just to make sure it sorts after "lmanlessbin" + echo -n "lxdescription $cmdname: $description" | sanitize + echo +} + +# NOTE: The -path and -lname stuff at the beginning of the following is +# there to make sure that none of the lines output by find contains +# a) \n or \r, because that would mess up post-processing the output +# line-by-line. +# b) \x7f, because this character triggers one of the nastier bash-bugs +# wrt string handling +# c) \2, because I use this as separator within the lines +# (Why \2 and not \0 or \1 ? Because bash can't cope with \0 at all and has +# bugs related to \1.) +# +# Because of this, having the final section called "ALL FILES" is technically +# a lie, because files with a path containing one of the abovementioned +# characters will not appear in output. +# However, a) no sane package contains such files +# b) they will be listed in the output from list_suspicious_files +cmd=(\( -path $'*\n*' -or -path $'*\r*' -or -path $'*\x7f*' + -or -path $'*\2*' + -or -lname $'*\n*' -or -lname $'*\r*' -or -lname $'*\x7f*' + -or -lname $'*\2*' + \) + -or + \( + \( -printf "zall %p\n" \) , + \( + \( -type f -or -xtype f \) -and + \( + \( -perm -u+x \( -path "*/bin/*" -or -path "*/sbin/*" \) -printf 'command\2%f\2cmd\2(->%l)\n' \) + -or \( -path "*/man/man*/*" -exec "$0" ":man" {} \; \) + -or \( -path "*/man/*/man*/*" -exec "$0" ":mani" {} \; \) + -or \( \( -name "lib*.so" -or -name "lib*.a" -or -name "lib*.so.*" \) -path "*/lib/*" -exec "$0" ":lib" {} \; \) + -or \( -type f -perm -u+x -not \( \( -name "lib*.so" -or -name "lib*.a" -or -name "lib*.so.*" \) -path "*/lib/*" \) -printf "nobinexe %p\n" \) + \) + \) + \) + ) + +forall_direntries_from "$ugname" "${cmd[@]}" | sort -u | +{ + sep=$'\2' + hold='' + for((;;)) + do + if [ -z "$hold" ]; then + read -r line || break + else + line="$hold" + hold='' + fi + + case "z$line" in + zcommand${sep}*${sep}cmd${sep}*) + cmdname=${line#command${sep}} + cmdname=${cmdname%%${sep}*} + read -r hold + case "z$hold" in + zcommand${sep}${cmdname}${sep}man${sep}*|zcommand${sep}${cmdname}${sep}mani${sep}*) + expand_command "$cmdname" "$line" "$hold" + hold='' + ;; + + z*) + expand_command "$cmdname" "$line" "" + ;; + esac + ;; + + zcommand${sep}*${sep}man${sep}*|command${sep}*${sep}mani${sep}*) + + echo -n "manextra ${line##*${sep}}" | sanitize + echo + ;; + + z*) + echo -n "$line" | sanitize + echo + ;; + esac + + done +} | sort | #no -u here, bc. the above processing may equalize different files +{ +# (1) binexe: Executables (in *bin/) +# (2) lib: Libraries (in *lib/*) +# (3) lmanlessbin: Executables (in *bin/) without manpages +# (4) lxdescription: Summaries for executables (in *bin/) +# (5) manextra: Extra manpages +# full paths, no perms +# (6) nobinexe: Executables not in *bin/ (excluding *lib/*.so and *lib/*.so.*) +# full paths, no perms +# (7) zall: All files +# full paths, no perms + + curstate='' + while read -r line + do + newstate="${line%% *}" + if [ "$newstate" != "$curstate" ]; then + curstate="$newstate" + case "$curstate" in + binexe) + echo 'EXECUTABLES (in */bin or */sbin)' + echo -n " ${line#binexe }" + ;; + lib) + echo + echo + echo 'LIBRARIES (lib*.a or lib*.so)' + echo -n " ${line#lib }" + ;; + lmanlessbin) + echo + echo + echo 'EXECUTABLES WITH NO MANPAGE (in */bin or */sbin)' + echo -n " ${line#lmanlessbin }" + ;; + lxdescription) + echo + echo + echo 'MANPAGE SUMMARIES OF EXECUTABLES (in */bin or */sbin)' + echo " ${line#lxdescription }" + ;; + manextra) + echo + echo 'EXTRA MANPAGES' + echo " ${line#manextra }" + ;; + nobinexe) + echo + echo 'EXTRA EXECUTABLES (not in */bin or */sbin)' + echo " ${line#nobinexe }" + ;; + zall) + echo + echo 'ALL FILES' + echo " ${line#zall }" + ;; + *) + echo + echo + echo 'UNEXPECTED LINE' + echo " $line" + ;; + + esac + else + case "$curstate" in + binexe) echo -n ", ${line#binexe }" + ;; + lib) echo -n ", ${line#lib }" + ;; + lmanlessbin) echo -n ", ${line#lmanlessbin }" + ;; + lxdescription) echo " ${line#lxdescription }" + ;; + manextra) echo " ${line#manextra }" + ;; + nobinexe) echo " ${line#nobinexe }" + ;; + zall) echo " ${line#zall }" + ;; + *) + echo + echo 'UNEXPECTED LINE' + echo " $line" + ;; + esac + fi + done +} + +list_suspicious_files_from "$ugname" diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/bin/list_suspicious_files --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/bin/list_suspicious_files Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,218 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +#The following list should contain the mount points of all filesystems +#that are to be scanned as a space-separated list within parentheses. +#/ will usually be in this list and if you have /usr +#on a separate partition, it will also be in this list. Other non-special +#filesystems where suspicious files could be located should also be put in +#this list. +#Mount points whose filesystems are special, such as procfs or sysfs should +#not be in this list. +fs_to_scan=(/) + +#Files with a path prefix found in the following list are ignored. +#DO !!!!NOT!!! PUT /usr/src OR WHATEVER THE HOME DIRECTORY prefix is for your +#package users into this list!!! You DO want to scan those directories in +#order to spot e.g. world-writable tarballs and other abominations that +#may have crept in. +#Ideally, this list should be empty. +prune_prefixes=() #NO TRAILING SLASHES!!! + +#If the following variable is set to "yes", then files that contain +#control characters or other non-printable characters (except for space) +#will be reported as suspicious. +#This test slows down the search considerably! +enable_illchars=yes + + +#suppress ugly debug output from shell +trap ':' SIGPIPE + +#"-false" as 1st argument is used when called by list_suspicious_files_from +if [ $# -ge 1 -a "$1" != "-false" ]; then + echo 1>&2 + echo 1>&2 "USAGE: ${0##*/}" + echo 1>&2 + echo 1>&2 ' Outputs a categorized list of files and directories with properties' + echo 1>&2 ' that could mean trouble and should be investigated.' + echo 1>&2 + exit 1 +fi + + +usergroupmatch=(-true) +if [ "$1" = "-false" ]; then + usergroupmatch=(\( "$@" \)) +fi + +#construct find commands that match the prune_prefixes. Each prefix will be +#matched as -path -or -path /* +#so that the directory itself and all subdirectories are matched. +y=(\( -false) +for ((i=0; $i<${#prune_prefixes[@]}; i=$i+1)) +do + y[${#y[@]}]='-or' + y[${#y[@]}]=-path + y[${#y[@]}]="${prune_prefixes[$i]}" + y[${#y[@]}]='-or' + y[${#y[@]}]=-path + y[${#y[@]}]="${prune_prefixes[$i]}/*" +done +y[${#y[@]}]=')' + +illchars=( $'\x1' $'\x2' $'\x3' $'\x4' $'\x5' $'\x6' $'\x7' $'\x8' + $'\x9' $'\xA' $'\xB' $'\xC' $'\xD' $'\xE' $'\xF' $'\x10' $'\x11' + $'\x12' $'\x13' $'\x14' $'\x15' $'\x16' $'\x17' $'\x18' $'\x19' + $'\x1A' $'\x1B' $'\x1C' $'\x1D' $'\x1E' $'\x1F' $'\x7f' $'\x80' + $'\x81' $'\x82' $'\x83' $'\x84' $'\x85' $'\x86' $'\x87' $'\x88' + $'\x89' $'\x8A' $'\x8B' $'\x8C' $'\x8D' $'\x8E' $'\x8F' $'\x90' + $'\x91' $'\x92' $'\x93' $'\x94' $'\x95' $'\x96' $'\x97' $'\x98' + $'\x99' $'\x9A' $'\x9B' $'\x9C' $'\x9D' $'\x9E' $'\x9F' ) + + +if [ "$enable_illchars" = yes ]; then + + illname=(\( -false) + for ((i=0; $i<${#illchars[@]}; i=$i+1)) + do + #handle bash \x7f error + if [ "*${illchars[$i]}*" = "**" ]; then + illchars[$i]=$'\x80' #' + fi + illname[${#illname[@]}]='-or' + illname[${#illname[@]}]=-name + illname[${#illname[@]}]="*${illchars[$i]}*" + done + illname[${#illname[@]}]=')' + + illlink=(\( -false) + for ((i=0; $i<${#illchars[@]}; i=$i+1)) + do + illlink[${#illlink[@]}]='-or' + illlink[${#illlink[@]}]=-lname + illlink[${#illlink[@]}]="*${illchars[$i]}*" + done + illlink[${#illlink[@]}]=')' +else #if [ "$enable_illchars" = no ] + illlink=(-false) + illname=(-false) +fi + +# $1=section heading +# $2=inode message +report() +{ + echo -printf "increment_code_here" + echo -printf + echo "1 ${1}\\n" | sed 's/ /\\040/g' + echo -printf "insert_code_here" + + if [ -n "$2" ]; then + echo -printf + echo "2 %i 1 ${2}\\n" | sed 's/ /\\040/g' + echo -printf "insert_code_here" + echo -printf + echo "2 %i 2 " | sed 's/ /\\040/g' + else + echo -printf "2\\040" + fi + + echo -exec ls -T 0 -ladQ {} \; +} + + +filegoodperm=(\( -perm 644 -or -perm 755 -or -perm 555 -or -perm 444 -or -perm 600 -or -perm 700 -or -perm 640 \)) +dirgoodperm=(\( -perm 755 -or -perm 555 -or -perm 700 -or -perm 750 \)) + +good=( \( + -not \( -not -type d -links +1 \) + -not -nouser -not -nogroup + -not \( "${illname[@]}" \) + -not \( "${illlink[@]}" \) + \) + -and +\( + \( -type f -not -group install "${filegoodperm[@]}" \) + -or \( -type d -not -group install "${dirgoodperm[@]}" \) + -or \( -type d -group install \( -perm 1775 \) \) + -or \( -type d -group root -user root -path "/tmp" \( -perm 1777 \) \) + -or \( -type d -group root -user root -path "/var/tmp" \( -perm 1777 \) \) + -or \( -not -type d -not -type f -not -type l -path "/dev/*" \) + -or \( -type l \( -xtype b -or -xtype c -or -xtype d -or -xtype p -or -xtype f \) \) +\) +) + +bad=( + \( "${illname[@]}" $(report "NON-PRINTABLE CHAR IN NAME") \) + OP \( "${illlink[@]}" $(report "NON-PRINTABLE-CHAR IN LINK-TARGET") \) + OP \( -type f -perm -4000 $(report "SETUID FILES") \) + OP \( -type f -perm -2000 $(report "SETGID FILES") \) + OP \( -type f -perm -1000 $(report "STICKY FILES") \) + OP \( -type d -perm -2000 $(report "GROUP-KEEPING DIRECTORIES") \) + OP \( -type d -not -group install -perm -1000 $(report "STICKY DIRECTORIES") \) + OP \( -type f -perm -g+w $(report "GROUP-WRITABLE FILES") \) + OP \( -type f -perm -o+w $(report "WORLD-WRITABLE FILES") \) + OP \( -type d -perm -g+w $(report "GROUP-WRITABLE DIRECTORIES") \) + OP \( -type d -perm -o+w $(report "WORLD-WRITABLE DIRECTORIES") \) + OP \( -not \( -type f -or -type l -or -type d \) -not -path "/dev/*" $(report "SPECIAL FILES OUTSIDE /dev") \) + OP \( -type d -group install -not -perm 1755 $(report "INSTALL DIRECTORIES WITH UNUSUAL PERMISSIONS") \) + OP \( -type f -group install $(report "FILES ASSIGNED TO GROUP INSTALL") \) + OP \( -type l -not \( -xtype b -or -xtype c -or -xtype d -or -xtype p -or -xtype f \) $(report "SYMLINKS POSSIBLY BROKEN OR LOOP") \) + OP \( -not -type d -links +1 $(report "HARDLINKED FILES" "Inode %i is shared by %n files, including") \) + OP \( -nouser $(report "THINGS HAVING UID WITH NO ASSIGNED USER NAME") \) + OP \( -nogroup $(report "THINGS HAVING GID WITH NO ASSIGNED GROUP NAME") \) + OP \( -type f -not -group install -not "${filegoodperm[@]}" $(report "FILES WITH UNUSUAL PERMISSIONS") \) + OP \( -type d -not -group install -not "${dirgoodperm[@]}" $(report "DIRECTORIES WITH UNUSUAL PERMISSIONS") \) +) + +#insert unique codes for the messages +code=100 +for ((i=0; $i<${#bad[@]}; i=$i+1)) +do + if [ "${bad[$i]}" = "increment_code_here" ]; then + code=$(($code + 1)) + bad[$i]=$code + elif [ "${bad[$i]}" = "insert_code_here" ]; then + bad[$i]=$code + fi +done + +allbad=() #all bad matches are reported +onebad=() #only the first bad match is reported +for ((i=0; $i<${#bad[@]}; i=$i+1)) +do + if [ "${bad[$i]}" = "OP" ]; then + allbad[$i]="," + onebad[$i]="-or" + else + allbad[$i]="${bad[$i]}" + onebad[$i]="${bad[$i]}" + fi +done + +#Add a default case to onebad. +#This should never be hit, because the explicit cases should catch all +#files, but just in case I've missed something, this will catch it. +onebad=("${onebad[@]}" -or $(report "WEIRD SHIT") ) + +#make allbad always return false +allbad=("${allbad[@]}" , -false) + +cmd=( "${usergroupmatch[@]}" -and + \( \( "${good[@]}" \) -or \( "${allbad[@]}" \) -or \( "${onebad[@]}" \) \) + ) + +#In the following find command, the part +# -not ( ( "${y[@]}" -prune ) -or "${y[@]}" ) +#is responsible for preventing the files that match prune_prefixes from +#being processed. The 2nd "${y[@]}" may seem redundant, but it isn't, because +#-prune has no effect and is always false when -depth is used. +find "${fs_to_scan[@]}" -xdev -noleaf \ + -not \( \( "${y[@]}" -prune \) -or "${y[@]}" \) \ + -and \( "${cmd[@]}" \) | +sed 's/^\(...2\) \([0-9]\+ 2 \)\?\([^ ]\+\) \+[^ ]\+ \+\([^ ]\+\) \+\([^ ]\+\) \+[^"]\+\(".\+\)/\1 \2\3 \6 \4:\5/' | +sort -u | +sed 's/^...1 /\'$'\n''/;s/^...2 [0-9]\+ 1 /\'$'\n'' /;s/^...2 [0-9]\+ 2 / /;s/^...2 / /' diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/bin/list_suspicious_files_from --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/bin/list_suspicious_files_from Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +if [ $# != 1 -o "$1" = "--help" ]; then + echo 1>&2 + echo 1>&2 'USAGE: '"${0##*/}"' ' + echo 1>&2 + echo 1>&2 ' Outputs a categorized list of files and directories with properties' + echo 1>&2 ' that could mean trouble and should be investigated.' + echo 1>&2 ' Suspicious objects will be reported only if group and/or user equals' + echo 1>&2 ' (numeric UID/GID allowed).' + echo 1>&2 ' This script calls `'"${0%_*}'"' for the real work.' + echo 1>&2 + exit 1 +fi + +ugname="$1" + +ugmatcher=(-false) +#test if find accepts ugname as a user, and append to ugmatcher if it does +if find / -maxdepth 0 -user "$ugname" >/dev/null 2>&1 ; then + ugmatcher[${#ugmatcher[@]}]="-or" + ugmatcher[${#ugmatcher[@]}]="-user" + ugmatcher[${#ugmatcher[@]}]="$ugname" +fi +#test if find accepts ugname as a group, and append to ugmatcher if it does +if find / -maxdepth 0 -group "$ugname" >/dev/null 2>&1 ; then + ugmatcher[${#ugmatcher[@]}]="-or" + ugmatcher[${#ugmatcher[@]}]="-group" + ugmatcher[${#ugmatcher[@]}]="$ugname" +fi + +#if find accepted ugname as neither user nor group, then exit +if [ "${#ugmatcher[@]}" = 1 ]; then + echo 1>&2 'find does not accept `'"$ugname'"' as group or user name' + exit 1 +fi + +"${0%_*}" "${ugmatcher[@]}" diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/bin/uninstall_package --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/bin/uninstall_package Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +if [ $# != 1 -o "$1" = '--help' ]; then + echo 1>&2 'USAGE: uninstall_package ' + exit 1 +fi +echo +echo '# If package '"$1"' has setuid root binaries, then you need to be' +echo '# root for the following to work.' +echo '# Otherwise, you can do it as user '"$1"'.' +echo +echo 'forall_direntries_from "'"$1"'" -depth \( -type d -exec echo rmdir {} \; \) -or \( -not -type d -exec echo rm -f {} \; \)' +echo +echo '# After successfully deleting all files, you may want to remove the' +echo '# package user '"$1"'. But remember that if you do that you need to' +echo '# remove or change ownership of '"$(eval echo ~"$1")"'. Unless you are' +echo '# certain that you will never re-install '"$1"', it is probably better to' +echo '# just keep the package user '"$1"' and its home directory around.' +echo '# Anyway, if you want to delete the account, you can use the following' +echo '# command:' +echo +echo 'userdel "'"$1"'"' +echo +echo '# If your /etc/login.defs has USERGROUPS_ENAB set to "yes" (the default),' +echo '# then userdel will automatically delete the package user'"'"'s group if' +echo '# its name is identical to the user name. Otherwise, if you want to delete' +echo '# the package user'"'"'s group, you will need to use the `groupdel'"'"' command.' +echo diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/bash_profile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/bash_profile Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,10 @@ +# The wrappers directory must be the first entry in the PATH. +# The /tools/bin directory must be the last entry in the PATH and can be +# removed at the end of Chapter 6. +export PATH=/usr/lib/pkgusr:/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin + +# Make prompt reflect that we are a package user. +export PROMPT_COMMAND='PS1="package \u:"`pwd`"> "' + +# Go to the home directory whenever we su to a package user. +cd diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/bashrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/bashrc Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,3 @@ +#Use the same environment regardless of whether we use +#`su ' or 'su - ' to become the package user. +source ~/.bash_profile diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/build --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/build Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,178 @@ +#!/bin/bash +# Copyright (c) 2000-2006 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +# This script will build a package based on the commands in $HOME/build.conf +# It can be called with the following parameters that +# will cause it to execute the respective *_commands() functions. If it is +# called with no parameter, that is equivalent to +# build unpack patch configure make check install clean +# +# It will create 8 log files in the $HOME directory: +# configure.log: All messages output during configure +# configure.err: Just the errors output during configure +# check.log: All messages output during checking +# check.err: Just the errors output during checking +# make.log: All messages output during make +# make.err: Just the errors output during make +# install.log: All messages output during make install +# install.err: Just the errors output during make install +# +# After running the script you should check the *.err files to see +# if any problems have occurred. If that is the case, use the corresponding +# *.log files to see the error messages in context. + +build_script="$(readlink -f "$0")" + +cd # go HOME + +source "$HOME"/build.conf + +if [ "_$(whoami)" != _root ]; then + export PACKAGE_OWNER="$(whoami)" +fi + + + # This function auto-extracts tarballs based on PATTERNS (see build.conf) inside + # the directory $HOME/xxxbuild and + # cds into the fist directory created by the first tarball. This is also + # stored in the variable $srcdir. +unpack_commands() +{ : + export srcdir="" + rm -rf "$HOME/xxxbuild" + mkdir -p "$HOME/xxxbuild" + cd "$HOME/xxxbuild" || return 1 + + for p in $PATTERNS ; do + for archive in "$HOME"/*"$p"* ; do + dir="" + if [ -f "$archive" ]; then + case z"$archive" in + z*.tar.bz2) dir=$(tar tjf "$archive" | grep / | head -n 1) ; tar xjf "$archive" ;; + z*.tar.gz) dir=$(tar tzf "$archive" | grep / | head -n 1) ; tar xzf "$archive" ;; + esac + fi + dir=${dir##./} + test -z "$dir" && echo 1>&2 "Error extracting $archive" + test -z "$srcdir" && srcdir=${dir%%/*} + done + done + + test -z "$srcdir" && { echo 1>&2 "Source directory not found" ; return 1 ; } + ln -s "$srcdir" yyysrc +} + +clean_commands() +{ + rm -rf "$HOME/xxxbuild" +} + +test_pipe() +{ + for i in "${PIPESTATUS[@]}" + do + test $i != 0 && { echo FAILED! ; exit 1 ; } + done + echo successful! + return 0 +} + +if [ $# -eq 0 ]; then + set -- unpack patch configure make check root_pre_install install root_post_install clean +fi + +while [ -n "$1" ]; do + case "_$1" in + _all) + shift 1 + set -- dummy unpack patch configure make check root_pre_install install root_post_install clean "$@" + ;; + + _unpack) + echo -n Unpacking... + + unpack_commands # no logging for unpack necessary + test_pipe + ;; + + _patch) + cd "$HOME/xxxbuild/yyysrc" && srcdir="$(pwd)" || exit 1 + patch_commands # no logging for patch necessary + #test_pipe + ;; + + _configure) + cd "$HOME/xxxbuild/yyysrc" && srcdir="$(pwd)" || exit 1 + echo -n Configuring... + + { configure_commands 3>&1 1>&2 2>&3 | tee "$HOME/configure.err" ;} &>"$HOME/configure.log" + test_pipe + # NOTE: Simply using && instead of test_pipe would not work, because && + # only tests the exit status of the last command in the pipe, which is tee. + ;; + + _make) + cd "$HOME/xxxbuild/yyysrc" && srcdir="$(pwd)" || exit 1 + echo -n Building... + + { make_commands 3>&1 1>&2 2>&3 | tee "$HOME/make.err" ;} &>"$HOME/make.log" + test_pipe + ;; + + _check) + cd "$HOME/xxxbuild/yyysrc" && srcdir="$(pwd)" || exit 1 + echo -n Checking... + + { check_commands 3>&1 1>&2 2>&3 | tee "$HOME/check.err" ;} &>"$HOME/check.log" + test_pipe + ;; + + _root_pre_install) + if type root_pre_install_commands &>/dev/null ; then + if [ _$(whoami) != _root ]; then + su --preserve-environment root -c "HOME='$HOME' '$build_script' root_pre_install" || exit 1 + else + echo -n "Preparing for install(root)..." + + { root_pre_install_commands 3>&1 1>&2 2>&3 | tee "$HOME/preinstall.err" ;} &>"$HOME/preinstall.log" + test_pipe + fi + fi + ;; + + _install) + cd "$HOME/xxxbuild/yyysrc" && srcdir="$(pwd)" || exit 1 + echo -n Installing... + + { install_commands 3>&1 1>&2 2>&3 | tee "$HOME/install.err" ;} &>"$HOME/install.log" + test_pipe + ;; + + _root_post_install) + if type root_post_install_commands &>/dev/null ; then + if [ _$(whoami) != _root ]; then + su --preserve-environment root -c "HOME='$HOME' '$build_script' root_post_install" || exit 1 + else + echo -n "Finishing install(root)..." + + { root_post_install_commands 3>&1 1>&2 2>&3 | tee "$HOME/postinstall.err" ;} &>"$HOME/postinstall.log" + test_pipe + fi + fi + ;; + + _clean) + cd "$HOME" + echo -n Cleaning... + clean_commands + echo done! + ;; + *) + echo 1>&2 "Unknown command '$1'" + exit 1 + ;; + esac + shift 1 +done diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/skel-package/.bash_profile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/skel-package/.bash_profile Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,1 @@ +/etc/pkgusr/bash_profile \ No newline at end of file diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/skel-package/.bashrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/skel-package/.bashrc Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,1 @@ +/etc/pkgusr/bashrc \ No newline at end of file diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/skel-package/.project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/skel-package/.project Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,14 @@ +DESCRIPTION: + bogus package +CONTENTS: + see pkg.lst +LAST UPDATED: + 30 Feb 2007 +DOWNLOAD LOCATION: + ftp://ftp.gnu.org/gnu/foo/ +WEB SITE: + +INSTALL NOTES: + +GENERAL NOTES: + diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/skel-package/build --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/skel-package/build Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,1 @@ +/etc/pkgusr/build \ No newline at end of file diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/etc/skel-package/build.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/etc/skel-package/build.conf Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,53 @@ +# +# Build instructions for +# +# This file is sourced by the /etc/pkguser/build script. + +# Note: the ":;" before the "}" in *_commands() is a no-op that makes sure +# that the function remains syntactically valid, even if you remove its +# contents (e.g. remove the "configure" line, because there's nothing to +# configure for the package). + +# ATTENTION! All functions are called with $HOME/xxxbuild/yyysrc as current +# working directory (except for clean_commands which has $HOME as cwd +# and unpack_commands which starts in $HOME when the +# script is called). This directory is created by unpack_commands. +# This means that a cd in configure_commands will NOT +# carry over into make_commands, so if you're building in a different +# directory than the one with the extracted source, then a cd has to be +# inserted at the beginning of EVERY function. + +# The unpack_commands() function in the build script will automatically extract +# .tar.gz and .tar.bz2 archives that match any of the space-separated +# patterns in this list. +# If a package has multiple archives, use patterns that make sure the +# archives are extracted in the correct order, because the archive +# extracted first will be the one in whose directory the build commands +# will be executed. Example for bash: "bash-3.1.tar doc-3.1.tar" +PATTERNS='4.3.2.tar' + +patch_commands() +{ : + #patch -Np1 -i "$HOME"/package.patch +} + +configure_commands() +{ : + "$srcdir"/configure --prefix=/usr --sysconfdir=/etc --disable-nls +} + +make_commands() +{ : + make +} + +check_commands() +{ : + #make check +} + +install_commands() +{ : + make install +} + diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/installdirs.lst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/installdirs.lst Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,86 @@ +/usr/bin +/usr/sbin +/usr/include +/usr/lib +/usr/man/man1 +/usr/man/man2 +/usr/man/man3 +/usr/man/man4 +/usr/man/man5 +/usr/man/man6 +/usr/man/man7 +/usr/man/man8 +/usr/doc +/usr/info +/usr/local/man/man1 +/usr/local/man/man2 +/usr/local/man/man3 +/usr/local/man/man4 +/usr/local/man/man5 +/usr/local/man/man6 +/usr/local/man/man7 +/usr/local/man/man8 +/usr/local/doc +/usr/local/info +/usr/share +/usr/share/dict +/usr/share/doc +/usr/share/info +/usr/share/locale +/usr/share/man/man1 +/usr/share/man/man2 +/usr/share/man/man3 +/usr/share/man/man4 +/usr/share/man/man5 +/usr/share/man/man6 +/usr/share/man/man7 +/usr/share/man/man8 +/usr/share/nls +/usr/share/misc +/usr/share/terminfo +/usr/share/zoneinfo +/usr/share/i18n +/usr/share/aclocal +/usr/local/bin +/usr/local/etc +/usr/local/include +/usr/local/lib +/usr/local/sbin +/usr/local/share +/usr/local/share/dict +/usr/local/share/doc +/usr/local/share/info +/usr/local/share/locale +/usr/local/share/man/man1 +/usr/local/share/man/man2 +/usr/local/share/man/man3 +/usr/local/share/man/man4 +/usr/local/share/man/man5 +/usr/local/share/man/man6 +/usr/local/share/man/man7 +/usr/local/share/man/man8 +/usr/local/share/nls +/usr/local/share/misc +/usr/local/share/terminfo +/usr/local/share/zoneinfo +/opt +/opt/doc +/opt/info +/opt/bin +/opt/include +/opt/lib +/opt/man/man1 +/opt/man/man2 +/opt/man/man3 +/opt/man/man4 +/opt/man/man5 +/opt/man/man6 +/opt/man/man7 +/opt/man/man8 +/var/lib +/var/opt +/etc +/etc/opt +/sbin +/bin +/lib diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/lib/chgrp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/lib/chgrp Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright (c) 2000,2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +DAISY_CHAIN="" + +for p in $(type -ap chgrp) ; do + if [ ! $p -ef $0 ]; then DAISY_CHAIN=$p ; break ; fi +done + +if [ ! -n "$DAISY_CHAIN" ]; then + echo Cannot find real ${0##*/} command + exit 1 +fi + +if [ $UID == 0 ]; then + exec $DAISY_CHAIN "$@" +fi + +if [ "$1" == "tty" ]; then + echo 1>&2 '***' chgrp "$@" +else + $DAISY_CHAIN "$@" || exit $? +fi + +exit 0 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/lib/chmod --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/lib/chmod Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +DAISY_CHAIN="" + +for p in $(type -ap chmod) ; do + if [ ! $p -ef $0 ]; then DAISY_CHAIN=$p ; break ; fi +done + +if [ ! -n "$DAISY_CHAIN" ]; then + echo Cannot find real ${0##*/} command + exit 1 +fi + +if [ $UID == 0 ]; then + exec $DAISY_CHAIN "$@" +fi + +report=0 +doit=1 +reportmsg="*** chmod $@" + +set -- "$@" eND_ofLisT +while true ; do + arg="$1" + shift 1 + case "_$arg" in + _eND_ofLisT) break ;; + _g+s|_u+s) report=1; doit=0 ;; + _4755) arg=755 ; report=1; doit=1 ;; + _4555) arg=555 ; report=1; doit=1 ;; + *) ;; + esac + set -- "$@" "$arg" +done + +if [ "$report" = 1 ]; then echo 1>&2 "$reportmsg" ; fi + +if [ "$doit" = 1 ]; then + exec $DAISY_CHAIN "$@" +fi + +exit 0 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/lib/chown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/lib/chown Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (c) 2000,2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +DAISY_CHAIN="" + +for p in $(type -ap chown) ; do + if [ ! $p -ef $0 ]; then DAISY_CHAIN=$p ; break ; fi +done + +if [ ! -n "$DAISY_CHAIN" ]; then + echo Cannot find real ${0##*/} command + exit 1 +fi + +if [ $UID == 0 ]; then + exec $DAISY_CHAIN "$@" +fi + +# Package users can't chown anything at all, so +# having the script test for specific parameters +# is pointless. +#if [ "$1" == "root.root" ]; then + echo 1>&2 '***' chown "$@" +#else +# $DAISY_CHAIN "$@" || exit $? +#fi + +exit 0 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/lib/install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/lib/install Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,127 @@ +#!/bin/bash +# Copyright (c) 2000,2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +manpagesowner=man-pages +localedir=/usr/share/locale +cmdline="$@" + +DAISY_CHAIN="" + +for p in $(type -ap install) ; do + if [ ! $p -ef $0 ]; then DAISY_CHAIN=$p ; break ; fi +done + +if [ ! -n "$DAISY_CHAIN" ]; then + echo Cannot find real ${0##*/} command + exit 1 +fi + +if [ $UID == 0 ]; then + exec $DAISY_CHAIN "$@" +fi + +#kill unused -c parameter if we get it +if [ z"$1" = z"-c" ]; then shift 1 ; fi + + #********** test if we create directories ******************** +if [ \( z"$1" = z"-d" \) -o \( z"$1" = z"-m" -a z"$3" = z"-d" \) ]; then + locdirs="" + notify=0 + havedir=0 + for((i=$#; $i>0; )) + do + a="$1" + shift 1; i=$(($i-1)) + case "$a" in + -o|-g|--owner|--group) notify=1 + shift 1; i=$(($i-1)) + set -- "$@" + ;; + $localedir/*) if [ ! -d "$a" ]; then + locdirs="$locdirs ""`expr $a : "$localedir/\(.*\)"`" + set -- "$@" "$a" + havedir=1 + else + notify=1 + set -- "$@" + fi + ;; + */*|/sbin) if [ ! -d "$a" ]; then + set -- "$@" "$a" + havedir=1 + else + notify=1 + set -- "$@" + fi + ;; + *) set -- "$@" "$a" ;; + esac + done + + test $notify -eq 1 -o z"$locdirs" != z && \ + echo 1>&2 '***' install "$cmdline" + + test $havedir -eq 0 && exit 0 + + $DAISY_CHAIN "$@" || exit $? + + test z"$locdirs" != z && + for dir in $locdirs ; do + cumuldir="" + for d in `echo $locdirs | sed 's#/# #g' -` ; do + cumuldir=$cumuldir$d/ + if [ -d $localedir/$cumuldir ]; then + chgrp install $localedir/$cumuldir + chmod g+w,o+t $localedir/$cumuldir + fi + done + done + +else #if "$1" != "-d" ,i.e. we do not create directories ***************** + notify=0 + for((i=$# ; $i>0; )) + do + a="$1" + shift 1; i=$(($i-1)) + case "$a" in + -m) set -- "$@" "$a" + a="$1" + shift 1; i=$(($i-1)) + case "$a" in + 4755) notify=1 ; set -- "$@" "755" ;; + 4775) notify=1 ; set -- "$@" "755" ;; + 4711) notify=1 ; set -- "$@" "711" ;; + *) set -- "$@" "$a" ;; + esac + ;; + -m4755) notify=1 ; set -- "$@" "-m755" ;; + -m4775) notify=1 ; set -- "$@" "-m755" ;; + -m4711) notify=1 ; set -- "$@" "-m711" ;; + -o|-g|--owner|--group) notify=1 + shift 1; i=$(($i-1)) + set -- "$@" + ;; + */man/man?/*) + if [ -e "$a" -a ! -O "$a" ]; then + if [ `find "$a" -printf \%u` = $manpagesowner ]; then + notify=1 + set -- "$@" not_installed + else + set -- "$@" "$a" + fi + else + set -- "$@" "$a" + fi + ;; + *) set -- "$@" "$a" ;; + esac + done + + test $notify -eq 1 && echo 1>&2 '***' install "$cmdline" + + $DAISY_CHAIN "$@" || exit $? +fi + +exit 0 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/lib/ldconfig.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/lib/ldconfig.c Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,8 @@ +#include + +int main() +{ + char* const argv[] = {"/sbin/ldconfig", "-v", NULL, NULL}; + char* const env[] = {NULL, NULL}; + return execve(argv[0], argv, env); +} diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/lib/mkdir --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/lib/mkdir Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright (c) 2000 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +watchdir=/usr/share/locale + +DAISY_CHAIN="" + +for p in $(type -ap mkdir) ; do + if [ ! $p -ef $0 ]; then DAISY_CHAIN=$p ; break ; fi +done + +if [ ! -n "$DAISY_CHAIN" ]; then + echo Cannot find real ${0##*/} command + exit 1 +fi + +if [ $UID == 0 ]; then + exec $DAISY_CHAIN "$@" +fi + +cmdline="$@" + +dirs="" +for((i=$#; $i>0;)) +do + a="$1" + shift 1; i=$(($i-1)) + case "$a" in + $watchdir/*) dirs="$dirs ""`expr $a : "$watchdir/\(.*\)"`" + set -- "$@" "$a" + ;; + *) set -- "$@" "$a" ;; + esac +done + +$DAISY_CHAIN "$@" || exit $? + +test z"$dirs" != z && +echo 1>&2 '***' mkdir "$cmdline" +for dir in $dirs ; do + cumuldir="" + for d in `echo $dirs | sed 's#/# #g' -` ; do + cumuldir=$cumuldir$d/ + chgrp install $watchdir/$cumuldir + test -k $watchdir/$cumuldir || chmod g+w,o+t $watchdir/$cumuldir + done +done +exit 0 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/sbin/add_package_user --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/sbin/add_package_user Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,239 @@ +#!/bin/bash +# Copyright (c) 2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +#Package user home directories will be located under this directory +homebase=/usr/src + +#Contents of following directory are copied into home directory when creating +#a new package user (existing files will not be overwritten) +skel=/etc/pkgusr/skel-package + +if [ $# -lt 7 ]; then + echo 1>&2 'USAGE: ' + echo 1>&2 'add_package_user \' + echo 1>&2 ' [-d ]' + echo 1>&2 + echo 1>&2 'If a user account called exists, a message will be printed and' + echo 1>&2 'everything will be left as-is. If a user account called does not' + echo 1>&2 'exist, one will be created.' + echo 1>&2 'The account'"'"'s primary group will be and the /etc/passwd' + echo 1>&2 'description field will be set to . If a group called ' + echo 1>&2 'does not already exist, one will be created.' + echo 1>&2 'The new account will get the "install" group as a supplementary group. If' + echo 1>&2 'a group named "install" does not exist, one will be created.' + echo 1>&2 + echo 1>&2 ' needs to be a valid string for the /etc/passwd description' + echo 1>&2 ' field. This means, among other things, that it must not contain ":".' + echo 1>&2 ' Don'"'"'t forget to properly quote if it contains spaces or' + echo 1>&2 ' other characters interpreted by the shell!' + echo 1>&2 + echo 1>&2 '(incl.) and (excl.) determine the numeric range from which' + echo 1>&2 ' the new account'"'"'s UID will be picked in the following way:' + echo 1>&2 + echo 1>&2 ' 1. If the range contains no unused UID => Exit with error.' + echo 1>&2 ' 2. If -1 is still unused, find the greatest UID from the range' + echo 1>&2 ' that is used and pick the number after that.' + echo 1>&2 ' 3. If -1 is in use, pick the first unused number from the range.' + echo 1>&2 + echo 1>&2 '(incl.) and (excl.) determine the numeric range from which' + echo 1>&2 ' to pick the GID for group and/or group "install", if it needs to be' + echo 1>&2 ' created. The process for picking the GID is the same as that for the UID.' + echo 1>&2 '' + echo 1>&2 ' specifies the new user'"'"'s home directory. If it is not provided,' + echo 1>&2 ' it will default to '"$homebase/ ." + echo 1>&2 ' If the home directory does not exist yet it will be created, otherwise' + echo 1>&2 ' the existing directory will be recursively chown'"'"'ed to the new user.' + echo 1>&2 ' The home directory will be populated with a copy of the contents of' + echo 1>&2 " $skel, but pre-existing files in the home directory" + echo 1>&2 ' will not be overwritten. Note that symlinks will be copied as symlinks!' + echo 1>&2 '' + exit 1 +fi + +grpfile=/etc/group +passwd=/etc/passwd + + + +description=$1 +name=$2 +minuid=$3 +maxuid=$4 +gname=$5 +mingid=$6 +maxgid=$7 +home=$homebase/$name + +set -- "$@" _eNd_OF_lisT_ +while [ "$1" != "_eNd_OF_lisT_" ]; do + case "$1" in + -d) shift 1 + if [ "$1" = "_eNd_OF_lisT_" ]; then + echo 1>&2 "-d directory name missing!" + exit 1 + fi + home="$1" + shift 1 + ;; + *) temp="$1" + shift 1 + set -- "$@" "$temp" + ;; + esac +done +shift 1 #throw away _eNd_OF_lisT_ + +if [ $UID -ne 0 ]; then echo Please run this script as root. ; exit 1; fi + +#test if user already exists +grep "^$name:.*" $passwd +if [ $? -eq 0 ]; then + echo 'Package user does already exist! Do su '$name' to do maintenance work.' + exit 1 +fi + +#test if minuid, maxuid, mingid and maxgid are integers, otherwise error +error=0 +expr ${minuid} + 1 2>/dev/null 1>&2 || error=1 +expr ${maxuid} + 1 2>/dev/null 1>&2 || error=1 +expr ${mingid} + 1 2>/dev/null 1>&2 || error=1 +expr ${maxgid} + 1 2>/dev/null 1>&2 || error=1 + +if [ $error -eq 1 ]; then + echo Error: Illegal numeric value! + exit 1 +fi + +if [ $minuid -ge $maxuid ]; then + echo 'Error: minuid must be less than maxuid !' + exit 1 +fi + +if [ $mingid -ge $maxgid ]; then + echo 'Error: mingid must be less than maxgid !' + exit 1 +fi + + +uidlist=`cut -d : -f 3 $passwd | sort -n` + +#find last used UID within range +u=0 +for i in $uidlist +do + if [ $i -ge $maxuid ]; then break; fi + if [ $i -ge $minuid ]; then u=$i; fi +done + +#if no UID from the range is used, pick the first, otherwise pick the one +#immediately following the last UID in use. +if [ $u -eq 0 ]; then u=$minuid; else u=`expr $u + 1`; fi + +#if the UID determined above is >= maxuid (i.e. illegal) +#then we look for the first unused uid in the range. +if [ $u -ge $maxuid ]; then + u=$minuid + for i in $uidlist + do + if [ $u -eq $i ]; then u=`expr $u + 1` ; fi + if [ $i -ge $maxuid ]; then break; fi + done + + if [ $u -ge $maxuid ]; then + echo Error: UID range is full! + exit 1 + fi +fi + +echo Will create user $name with uid: $u + +unset uidlist + +############################################################################# +# group +############################################################################# + +#execute the following for gname and "install" to get gids for those 2 groups + +g=0 +creategroup=0 +for group in install $gname +do + oldg=$g #save gid from previous run + createinstall=$creategroup + creategroup=0 + + #test if group already exists and extract gid if so + g=`grep ^${group}:.\* $grpfile | cut -d : -f 3 -` + + #if group does not exist, then check range for a free gid + if [ z$g = z ]; then + creategroup=1 + + gidlist=`cut -d : -f 3 $grpfile | sort -n` + + #find last used GID within range + g=0 + for i in $gidlist + do + if [ $i -ge $maxgid ]; then break; fi + if [ $i -ge $mingid ]; then g=$i; fi + done + + #if no GID from the range is used, pick the first, otherwise pick the one + #immediately following the last GID in use. + if [ $g -eq 0 ]; then g=$mingid; else g=`expr $g + 1`; fi + + #don't reuse gid from previous run + if [ $g -eq $oldg ]; then g=`expr $g + 1`; fi + + #if the GID determined above is >= maxgid (i.e. illegal) + #then we look for the first unused gid in the range. + if [ $g -ge $maxgid ]; then + g=$mingid + for i in $gidlist + do + if [ $g -eq $i ]; then g=`expr $g + 1` ; fi + if [ $g -eq $oldg ]; then g=`expr $g + 1` ; fi + if [ $i -ge $maxgid ]; then break; fi + done + + if [ $g -ge $maxgid ]; then + echo Error: GID range is full! + exit 1 + fi + fi + fi +done + +unset gidlist + +if [ $createinstall -eq 1 ]; then + echo Creating group install with gid $oldg + groupadd -g $oldg install || exit 1 +else + echo Group install has gid $oldg +fi +if [ $creategroup -eq 1 ]; then + echo Creating group $gname with gid $g + groupadd -g $g $gname || exit 1 +else + echo Group $gname has gid $g +fi + + + +useradd -c "${description}" -d ${home} -g ${gname} -G install \ + -s /bin/bash -u ${u} ${name} || exit 1 + +mkdir -p $home || exit 1 + +yes n|cp -ai -R ${skel}/{[^.],.[^.],..?}* ${home} 2>/dev/null >/dev/null + +cd ${home} +chown --recursive ${u}:${g} . + + +exit 0 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/sbin/groupadd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/sbin/groupadd Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright (c) 2000,2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +# +# This is a primitive script to serve as groupadd until the real groupadd +# has been installed. It has little error checking, so don't pass it anything +# stupid or it'll mess up your /etc/group file. +# + +if [ $# -ne 3 -o z$1 != z-g ]; then +echo 1>&2 USAGE: groupadd -g gid groupname +exit 1 +fi + +#test if group already exists +grep "^${3}:.*" /etc/group +if [ $? -eq 0 ]; then + echo 1>&2 $0: Group does already exist + exit 1 +fi + +cp /etc/group /tmp/group123456 +echo ${3}:x:${2}: | sort -t : -k3,3n -m /tmp/group123456 - > /etc/group + diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/sbin/install_package --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/sbin/install_package Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright (c) 2000,2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +if [ $# -eq 1 ]; then + set -- "$1" "$1" "$1" +fi + +if [ $# -ne 3 ]; then + echo 1>&2 + echo 1>&2 'USAGE 1: install_package ' + echo 1>&2 'USAGE 2: install_package ' + echo 1>&2 + echo 1>&2 'Creates a new package user called with primary group ' + echo 1>&2 'and description .' + echo 1>&2 'If the user account has been created successfully, `su - '"'"' will be' + echo 1>&2 'executed so that you can start working with the new account right away.' + echo 1>&2 + echo 1>&2 ' needs to be a valid string for the /etc/passwd description' + echo 1>&2 ' field. This means, among other things, that it must not contain ":".' + echo 1>&2 ' Don'"'"'t forget to properly quote if it contains spaces or' + echo 1>&2 ' other characters interpreted by the shell!' + echo 1>&2 + echo 1>&2 'This script leaves the actual creation of the new account to the' + echo 1>&2 'add_package_user script. Check out its documentation for details.' + echo 1>&2 + echo 1>&2 'When called with just one argument, that argument will be used as' + echo 1>&2 ', and ' + exit 1 +fi + +if [ $UID -ne 0 ]; then echo Please run this script as root. ; exit 1; fi +add_package_user "${1}" $2 10000 20000 $3 10000 20000 || exit 1 +su - $2 diff -r 0b7a589f6e9a -r d6bef198ae71 previous-work/more_control_helpers/sbin/useradd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/previous-work/more_control_helpers/sbin/useradd Tue Jan 08 11:45:01 2013 +0000 @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2000,2004 Matthias S. Benkmann
+# You may do everything with this code except misrepresent its origin. +# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! + +# +# This is a primitive script to serve as useradd until the real useradd +# has been installed. It has little error checking, so don't pass it anything +# stupid or it'll mess up your /etc/passwd and/or /etc/group file. +# + +if [ $# -ne 13 -o z$1 != z-c -o z$3 != z-d -o z$5 != z-g -o z$7 != z-G -o z$9 != z-s -o z${11} != z-u ]; then +echo 1>&2 USAGE: useradd -c description -d home -g maingroup -G addgroup -s shell -u uid login +exit 1 +fi + +#test if user already exists +grep "^${13}:.*" /etc/passwd +if [ $? -eq 0 ]; then + echo 1>&2 $0: User does already exist + exit 1 +fi + +g=`grep ^${6}:.\* /etc/group | cut -d : -f 3 -` +if [ z${g} = z ]; then + echo 1>&2 $0: Group ${6} does not exist! + exit 1 +fi + +grep ^${8}:.\* /etc/group >/dev/null || \ +{ + echo 1>&2 $0: Group ${8} does not exist! + exit 1 +} + + +cp /etc/passwd /tmp/passwd123456 +echo "${13}:x:${12}:$g:$2:$4:${10}" \ +| sort -t : -k3,3n -m /tmp/passwd123456 - > /etc/passwd + + +cp /etc/group /tmp/group123456 +sed -e 's/^\('"${8}"':[^:]*:[0-9]*:..*\)$/\1,'"${13}"'/' \ + -e 's/^\('"${8}"':[^:]*:[0-9]*\):$/\1:'"${13}"'/' \ + /tmp/group123456 >/etc/group