/*
 *     Mount.c  (Program to perform 'safe' file system mount/umount
 *               operations without requiring super user permissions.)
 *     Copyright (C) 1992  Don Trimmer, Delta Microsystems, Inc.
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 1, or (at your option)
 *     any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     This notice was shamelessly copied from the GNU General Public
 *     License.  That license is included in it's entirety at the end
 *     of this listing.  Please note that GNU grants permission to copy
 *     their license statement as long as it is complete and unmodified.
 * 
 */

/*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 *** Program:   Mount (Umount)

 *** Purpose:   Allow anybody to mount/umount file systems from
                specified devices, while preventing anybody but 'root'
                from performing other mount/umount operations.

 *** Usage:     Mount  args
                Umount args
                       args:   The arguments normally given to mount
                               or umount.

 *** Notes:     Use the following shell script to build executable:

                #!/bin/csh
                #
                #  The following two lines build a test version.  To
                #    build the real version, comment out the next two
                #    lines and remove the leading '# ' from the
                #    following two commands:
                #
                echo "Compiling test version (echo mount arguments)"
                cc -DTEST -o Mount Mount.c
                # echo "Compiling and loading Mount"
                # cc -o Mount Mount.c

                echo "Changing Mount ownership and permissions"
                chown root Mount
                chmod 4555 Mount

                echo "Linking Umount to Mount"
                /bin/rm Umount | echo -n ""
                ln Mount Umount
                /bin/ls -l Mount Umount

                echo "Done!"

 *** History:   04/08/91:  Under development--D. Trimmer
                04/08/91:  Tested--D. Trimmer
                10/19/91:  cdrom and pcfs added by W. Kennedy
                03/03/92:  Removed references to 'smo', added
                           'uflop' and improved security --D. Trimmer

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <errno.h>

#define CLEAR           0
#define SET             1
#define REEXPLEN        80
#define NEWMOUNTCOM     "Mount"
#define NEWUMOUNTCOM    "Umount"

#ifdef  TEST
#       define MOUNTCOM         "echo"
#       define UMOUNTCOM        "echo"
#       define MOUNTPATH        "/bin/"
#       define UMOUNTPATH       "/bin/"
#else   TEST
#       define MOUNTCOM         "mount"
#       define UMOUNTCOM        "umount"
#       define MOUNTPATH        "/usr/etc/"
#       define UMOUNTPATH       "/usr/etc/"
#endif  TEST

/*
 *  "devices" is an array of strings.  Each string is a regular
 *    expression which matches a device or directory.  If a device
 *    is specified, then the directory on which the device should
 *    be mounted should also be specified:
 *
 *      Mount /dev/sd3c /tmp
 *
 *    If only the directory is specified, then the file /etc/fstab
 *    is referenced to determine what file system is normally
 *    mounted on that directory:
 *
 *      Line in /etc/fstab:  /dev/sd3c /tmp 4.2 rw,noauto 0 0
 *      Mount /tmp
 */

char  devices[][REEXPLEN] = {
        /*
         *  Make entries in /etc/fstab for each of the following
         *    entries and create directories /cdrom, /pcfs and
         *    /uflop.
         */
        "/cdrom",
        "/pcfs",
        "/uflop",
        ""
};

main(argc,argv)
int     argc;
char    *argv[];
{
        int     i,j,k;                  /* Index */
        int     ValidatedFlag=CLEAR;    /* OK to proceed flag */
        char    Path[MAXPATHLEN];       /* Path of mount/umount */
        char    Name[MAXPATHLEN];       /* mount or umount */
        struct  stat stbuf;             /* File status structure */

        if(getuid() && argc>1) {
                /* UID not root, so validate permission */
                for(i=0;devices[i][0] && !ValidatedFlag;i++) {
                        if(re_comp(devices[i])) {
                                fprintf(stderr,
                                  "%s %s (errno=%d)\n",
                                  "Can't compile regular expression",
                                  devices[i],errno);
                                exit(1);
                        }
                        for(j=1;j<argc;j++) {
                                if(re_exec(argv[j]) == 1) {
                                        /* Match found */
                                        ValidatedFlag = SET;
                                        break;
                                }
                        }
                }

                if(ValidatedFlag) {
                        /*
                         *  Check to make sure no other arguments are block
                         *    special files, 'NFS' file systems or dangerous
                         *    options in case someone is trying to fake us out.
                         */
                        for(k=1;k<argc;k++) {
                                if(k == j)
                                        continue;
                                if(!stat(argv[k],&stbuf)) {
#ifdef S_ISBLK
                                        if(S_ISBLK(stbuf.st_mode)) {
#else
                                        if(S_IFBLK & stbuf.st_mode) {
#endif
                                                /*
                                                 *  A block special device.
                                                 *    Probably a HACKER!!
                                                 */
                                                ValidatedFlag = CLEAR;
                                                break;
                                        } /* } */
                                } else if(index(argv[k],':')) {
                                        /*
                                         *  Probably NFS mount
                                         */
                                        ValidatedFlag = CLEAR;
                                        break;
                                } else if(!strcmp(argv[k],"-a") ||
                                   !strcmp(argv[k],"-h")) {
                                        /*
                                         *  -a and -h are dangerous options
                                         */
                                        ValidatedFlag = CLEAR;
                                        break;
                                }
                        }
                }

                if(!ValidatedFlag) {
                        fprintf(stderr,"Permission denied.\n");
                        exit(1);
                }
        }

        /*
         *  If we got here, OK to perform [u]mount.  Build mount/umount
         *    command and reset argv[0] to point at new command name
         */
        if(!strcmp(argv[0],NEWMOUNTCOM)) {
                strcpy(Name,MOUNTCOM);
                sprintf(Path,"%s%s",MOUNTPATH,MOUNTCOM);
        } else {
                strcpy(Name,UMOUNTCOM);
                sprintf(Path,"%s%s",UMOUNTPATH,UMOUNTCOM);
        }
        argv[0] = Name;

        execv(Path,argv);

        /*  Should never get here  */
        fprintf(stderr,"Error exec'ing command (errno=%d)\n",errno);
        exit(1);
}

/*
 *  ================================
 *  Compiling and installing 'Mount'
 *  ================================
 *  
 *  It is necessary to log in as 'root' to install 'Mount'.  After
 *  loging in as root, compile and load 'Mount.c', turn on the SUID
 *  bit and link 'Mount' with 'Umount':
 *  
 *      % cc -DTEST -o Mount Mount.c
 *      % chmod 4555 Mount
 *      % /bin/rm Umount   # Don't worry if this gives an error
 *      % ln Mount Umount
 *  
 *  The SUID bit allows the code to execute with the access priviledges
 *  of the owner of the program (root in this case).  The '-DTEST"
 *  flag on the compile line generates a program which will echo
 *  the actions it would normally take without actually performing
 *  them.  The user can use this mode to verify that the code is
 *  behaving as desired.  To generate a copy of 'Mount' which actually
 *  works, repeat the above steps but leave the '-DTEST' option out
 *  of the command line.
 *  
 *  ================================
 *  Additions to /etc/fstab:
 *  ================================
 *  
 *  # CD-ROM entry
 *  /dev/rd0        /cdrom        hsfs ro,noauto 0 0
 *  
 *  # Floppy entry for DOS disk
 *  /dev/fd0        /pcfs        pcfs rw,noauto 0 0
 *
 *  # Floppy entry for SunOS file system
 *  /dev/fd0        /uflop        4.2  rw,noauto 0 0
 *  
 *  
 *  hsfs:  Indicates that a CD-ROM file system is present.
 *         High Sierra and ISO 9660 file systems are supported.
 *  pcfs:  Indicates a DOS file system is present.
 *  4.2:   Indicates a standard SunOS file system is present.
 *  ro:    Read-only file system
 *  rw:    Read-write file system
 *  noauto:  Don't mount file system when 'mount -a' is executed.
 *  0:     First '0' indicates interval between 'dumps'
 *         Second '0' indicates file system check (fsck) won't be run
 *  
 *  If a floppy disk containing a DOS file system is to be mounted,
 *  then use:
 *  
 *      % Mount /pcfs
 *  
 *  If a floppy disk contains a standard SunOS file system, then the
 *  appropriate 'Mount' command is:
 *  
 *      % Mount /uflop
 *  
 *  ================================
 *  Creating directories:
 *  ================================
 *  
 *  Log in as root:
 *  % mkdir /cdrom /pcfs /uflop
 *  % chmod 777 /cdrom /pcfs /uflop
 * 
 * 
 *
 *
 * ================================================
 * GNU Copyright statement:
 * ================================================
 * 
 *                  GNU GENERAL PUBLIC LICENSE
 *                   Version 1, February 1989
 * 
 *  Copyright (C) 1989 Free Software Foundation, Inc.
 *                     675 Mass Ave, Cambridge, MA 02139, USA
 *  Everyone is permitted to copy and distribute verbatim copies
 *  of this license document, but changing it is not allowed.
 * 
 *                          Preamble
 * 
 *   The license agreements of most software companies try to keep users
 * at the mercy of those companies.  By contrast, our General Public
 * License is intended to guarantee your freedom to share and change free
 * software--to make sure the software is free for all its users.  The
 * General Public License applies to the Free Software Foundation's
 * software and to any other program whose authors commit to using it.
 * You can use it for your programs, too.
 * 
 *   When we speak of free software, we are referring to freedom, not
 * price.  Specifically, the General Public License is designed to make
 * sure that you have the freedom to give away or sell copies of free
 * software, that you receive source code or can get it if you want it,
 * that you can change the software or use pieces of it in new free
 * programs; and that you know you can do these things.
 * 
 *   To protect your rights, we need to make restrictions that forbid
 * anyone to deny you these rights or to ask you to surrender the rights.
 * These restrictions translate to certain responsibilities for you if you
 * distribute copies of the software, or if you modify it.
 * 
 *   For example, if you distribute copies of a such a program, whether
 * gratis or for a fee, you must give the recipients all the rights that
 * you have.  You must make sure that they, too, receive or can get the
 * source code.  And you must tell them their rights.
 * 
 *   We protect your rights with two steps: (1) copyright the software, and
 * (2) offer you this license which gives you legal permission to copy,
 * distribute and/or modify the software.
 * 
 *   Also, for each author's protection and ours, we want to make certain
 * that everyone understands that there is no warranty for this free
 * software.  If the software is modified by someone else and passed on, we
 * want its recipients to know that what they have is not the original, so
 * that any problems introduced by others will not reflect on the original
 * authors' reputations.
 * 
 *   The precise terms and conditions for copying, distribution and
 * modification follow.
 * 
 *                  GNU GENERAL PUBLIC LICENSE
 *    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 * 
 *   0. This License Agreement applies to any program or other work which
 * contains a notice placed by the copyright holder saying it may be
 * distributed under the terms of this General Public License.  The
 * "Program", below, refers to any such program or work, and a "work based
 * on the Program" means either the Program or any work containing the
 * Program or a portion of it, either verbatim or with modifications.  Each
 * licensee is addressed as "you".
 * 
 *   1. You may copy and distribute verbatim copies of the Program's source
 * code as you receive it, in any medium, provided that you conspicuously and
 * appropriately publish on each copy an appropriate copyright notice and
 * disclaimer of warranty; keep intact all the notices that refer to this
 * General Public License and to the absence of any warranty; and give any
 * other recipients of the Program a copy of this General Public License
 * along with the Program.  You may charge a fee for the physical act of
 * transferring a copy.
 * 
 *   2. You may modify your copy or copies of the Program or any portion of
 * it, and copy and distribute such modifications under the terms of Paragraph
 * 1 above, provided that you also do the following:
 * 
 *     a) cause the modified files to carry prominent notices stating that
 *     you changed the files and the date of any change; and
 * 
 *     b) cause the whole of any work that you distribute or publish, that
 *     in whole or in part contains the Program or any part thereof, either
 *     with or without modifications, to be licensed at no charge to all
 *     third parties under the terms of this General Public License (except
 *     that you may choose to grant warranty protection to some or all
 *     third parties, at your option).
 * 
 *     c) If the modified program normally reads commands interactively when
 *     run, you must cause it, when started running for such interactive use
 *     in the simplest and most usual way, to print or display an
 *     announcement including an appropriate copyright notice and a notice
 *     that there is no warranty (or else, saying that you provide a
 *     warranty) and that users may redistribute the program under these
 *     conditions, and telling the user how to view a copy of this General
 *     Public License.
 * 
 *     d) You may charge a fee for the physical act of transferring a
 *     copy, and you may at your option offer warranty protection in
 *     exchange for a fee.
 * 
 * Mere aggregation of another independent work with the Program (or its
 * derivative) on a volume of a storage or distribution medium does not bring
 * the other work under the scope of these terms.
 * 
 *   3. You may copy and distribute the Program (or a portion or derivative of
 * it, under Paragraph 2) in object code or executable form under the terms of
 * Paragraphs 1 and 2 above provided that you also do one of the following:
 * 
 *     a) accompany it with the complete corresponding machine-readable
 *     source code, which must be distributed under the terms of
 *     Paragraphs 1 and 2 above; or,
 * 
 *     b) accompany it with a written offer, valid for at least three
 *     years, to give any third party free (except for a nominal charge
 *     for the cost of distribution) a complete machine-readable copy of the
 *     corresponding source code, to be distributed under the terms of
 *     Paragraphs 1 and 2 above; or,
 * 
 *     c) accompany it with the information you received as to where the
 *     corresponding source code may be obtained.  (This alternative is
 *     allowed only for noncommercial distribution and only if you
 *     received the program in object code or executable form alone.)
 * 
 * Source code for a work means the preferred form of the work for making
 * modifications to it.  For an executable file, complete source code means
 * all the source code for all modules it contains; but, as a special
 * exception, it need not include source code for modules which are standard
 * libraries that accompany the operating system on which the executable
 * file runs, or for standard header files or definitions files that
 * accompany that operating system.
 * 
 *   4. You may not copy, modify, sublicense, distribute or transfer the
 * Program except as expressly provided under this General Public License.
 * Any attempt otherwise to copy, modify, sublicense, distribute or transfer
 * the Program is void, and will automatically terminate your rights to use
 * the Program under this License.  However, parties who have received
 * copies, or rights to use copies, from you under this General Public
 * License will not have their licenses terminated so long as such parties
 * remain in full compliance.
 * 
 *   5. By copying, distributing or modifying the Program (or any work based
 * on the Program) you indicate your acceptance of this license to do so,
 * and all its terms and conditions.
 * 
 *   6. Each time you redistribute the Program (or any work based on the
 * Program), the recipient automatically receives a license from the original
 * licensor to copy, distribute or modify the Program subject to these
 * terms and conditions.  You may not impose any further restrictions on the
 * recipients' exercise of the rights granted herein.
 * 
 *   7. The Free Software Foundation may publish revised and/or new versions
 * of the General Public License from time to time.  Such new versions will
 * be similar in spirit to the present version, but may differ in detail to
 * address new problems or concerns.
 * 
 * Each version is given a distinguishing version number.  If the Program
 * specifies a version number of the license which applies to it and "any
 * later version", you have the option of following the terms and conditions
 * either of that version or of any later version published by the Free
 * Software Foundation.  If the Program does not specify a version number of
 * the license, you may choose any version ever published by the Free Software
 * Foundation.
 * 
 *   8. If you wish to incorporate parts of the Program into other free
 * programs whose distribution conditions are different, write to the author
 * to ask for permission.  For software which is copyrighted by the Free
 * Software Foundation, write to the Free Software Foundation; we sometimes
 * make exceptions for this.  Our decision will be guided by the two goals
 * of preserving the free status of all derivatives of our free software and
 * of promoting the sharing and reuse of software generally.
 * 
 *                          NO WARRANTY
 * 
 *   9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 * FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 * PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 * TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 * PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 * REPAIR OR CORRECTION.
 * 
 *   10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 * REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 * INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 * OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 * TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 * YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 * PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 * 
 *                   END OF TERMS AND CONDITIONS
 * 
 *      Appendix: How to Apply These Terms to Your New Programs
 * 
 *   If you develop a new program, and you want it to be of the greatest
 * possible use to humanity, the best way to achieve this is to make it
 * free software which everyone can redistribute and change under these
 * terms.
 * 
 *   To do so, attach the following notices to the program.  It is safest to
 * attach them to the start of each source file to most effectively convey
 * the exclusion of warranty; and each file should have at least the
 * "copyright" line and a pointer to where the full notice is found.
 * 
 *     <one line to give the program's name and a brief idea of what it does.>
 *     Copyright (C) 19yy  <name of author>
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 1, or (at your option)
 *     any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 * Also add information on how to contact you by electronic and paper mail.
 * 
 * If the program is interactive, make it output a short notice like this
 * when it starts in an interactive mode:
 * 
 *     Gnomovision version 69, Copyright (C) 19xx name of author
 *     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 *     This is free software, and you are welcome to redistribute it
 *     under certain conditions; type `show c' for details.
 * 
 * The hypothetical commands `show w' and `show c' should show the
 * appropriate parts of the General Public License.  Of course, the
 * commands you use may be called something other than `show w' and `show
 * c'; they could even be mouse-clicks or menu items--whatever suits your
 * program.
 * 
 * You should also get your employer (if you work as a programmer) or your
 * school, if any, to sign a "copyright disclaimer" for the program, if
 * necessary.  Here a sample; alter the names:
 * 
 *   Yoyodyne, Inc., hereby disclaims all copyright interest in the
 *   program `Gnomovision' (a program to direct compilers to make passes
 *   at assemblers) written by James Hacker.
 * 
 *   <signature of Ty Coon>, 1 April 1989
 *   Ty Coon, President of Vice
 * 
 * That's all there is to it!
 */
