Annotation of embedaddon/thttpd/extras/makeweb.c, revision 1.1

1.1     ! misho       1: /* makeweb.c - let a user create a web subdirectory
        !             2: **
        !             3: ** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
        !             4: ** All rights reserved.
        !             5: **
        !             6: ** Redistribution and use in source and binary forms, with or without
        !             7: ** modification, are permitted provided that the following conditions
        !             8: ** are met:
        !             9: ** 1. Redistributions of source code must retain the above copyright
        !            10: **    notice, this list of conditions and the following disclaimer.
        !            11: ** 2. Redistributions in binary form must reproduce the above copyright
        !            12: **    notice, this list of conditions and the following disclaimer in the
        !            13: **    documentation and/or other materials provided with the distribution.
        !            14: ** 
        !            15: ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            16: ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            17: ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            18: ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            19: ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            20: ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            21: ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22: ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            23: ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            24: ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            25: ** SUCH DAMAGE.
        !            26: */
        !            27: 
        !            28: /* This is intended to be installed setgid to a group that has
        !            29: ** write access to the system web directory.  It allows any user
        !            30: ** to create a subdirectory there.  It also makes a symbolic link
        !            31: ** in the user's home directory pointing at the new web subdir.
        !            32: */
        !            33: 
        !            34: 
        !            35: #include "../config.h"
        !            36: 
        !            37: #include <stdlib.h>
        !            38: #include <unistd.h>
        !            39: #include <stdio.h>
        !            40: #include <string.h>
        !            41: #include <pwd.h>
        !            42: #include <errno.h>
        !            43: #include <sys/types.h>
        !            44: #include <sys/stat.h>
        !            45: 
        !            46: 
        !            47: #define LINK "public_html"
        !            48: 
        !            49: static char* argv0;
        !            50: 
        !            51: 
        !            52: static void
        !            53: check_room( int size, int len )
        !            54:     {
        !            55:     if ( len > size )
        !            56:        {
        !            57:        (void) fprintf( stderr, "%s: internal error, out of room\n", argv0 );
        !            58:        exit( 1 );
        !            59:        }
        !            60:     }
        !            61: 
        !            62: 
        !            63: static void
        !            64: end_with_slash( char* str )
        !            65:     {
        !            66:     if ( str[strlen( str ) - 1] != '/' )
        !            67:        (void) strcat( str, "/" );
        !            68:     }
        !            69: 
        !            70: 
        !            71: static void
        !            72: check_dir( char* dirname, uid_t uid, gid_t gid )
        !            73:     {
        !            74:     struct stat sb;
        !            75: 
        !            76:     /* Check the directory. */
        !            77:     if ( stat( dirname, &sb ) < 0 )
        !            78:        {
        !            79:        if ( errno != ENOENT )
        !            80:            {
        !            81:            perror( dirname );
        !            82:            exit( 1 );
        !            83:            }
        !            84:        /* Doesn't exist.  Try to make it. */
        !            85:        if ( mkdir( dirname, 0755 ) < 0 )
        !            86:            {
        !            87:            if ( errno == ENOENT )
        !            88:                (void) printf( "\
        !            89: Some part of the path %s does not exist.\n\
        !            90: This is probably a configuration error.\n", dirname );
        !            91:            else
        !            92:                perror( dirname );
        !            93:            exit( 1 );
        !            94:            }
        !            95:        (void) printf( "Created web directory %s\n", dirname );
        !            96:        /* Try to change the group of the new dir to the user's group. */
        !            97:        (void) chown( dirname, -1, gid );
        !            98:        }
        !            99:     else
        !           100:        {
        !           101:        /* The directory already exists.  Well, check that it is in
        !           102:        ** fact a directory.
        !           103:        */
        !           104:        if ( ! S_ISDIR( sb.st_mode ) )
        !           105:            {
        !           106:            (void) printf(
        !           107:                "%s already exists but is not a directory!\n", dirname );
        !           108:            exit( 1 );
        !           109:            }
        !           110:        if ( sb.st_uid != uid )
        !           111:            {
        !           112:            (void) printf(
        !           113:                "%s already exists but you don't own it!\n", dirname );
        !           114:            exit( 1 );
        !           115:            }
        !           116:        (void) printf( "Web directory %s already existed.\n", dirname );
        !           117:        }
        !           118:     }
        !           119: 
        !           120: 
        !           121: int
        !           122: main( int argc, char** argv )
        !           123:     {
        !           124:     char* webdir;
        !           125:     char* prefix;
        !           126:     struct passwd* pwd;
        !           127:     char* username;
        !           128:     char* homedir;
        !           129:     char dirname[5000];
        !           130:     char linkname[5000];
        !           131:     char linkbuf[5000];
        !           132:     struct stat sb;
        !           133: 
        !           134:     argv0 = argv[0];
        !           135:     if ( argc != 1 )
        !           136:        {
        !           137:        (void) fprintf( stderr, "usage:  %s\n", argv0 );
        !           138:        exit( 1 );
        !           139:        }
        !           140: 
        !           141:     pwd = getpwuid( getuid() );
        !           142:     if ( pwd == (struct passwd*) 0 )
        !           143:        {
        !           144:        (void) fprintf( stderr, "%s: can't find your username\n", argv0 );
        !           145:        exit( 1 );
        !           146:        }
        !           147:     username = pwd->pw_name;
        !           148:     homedir = pwd->pw_dir;
        !           149: 
        !           150: #ifdef TILDE_MAP_2
        !           151: 
        !           152:     /* All we have to do for the TILDE_MAP_2 case is make sure there's
        !           153:     ** a public_html subdirectory.
        !           154:     */
        !           155:     check_room(
        !           156:        sizeof(dirname), strlen( homedir ) + strlen( TILDE_MAP_2 ) + 2 );
        !           157:     (void) strcpy( dirname, homedir );
        !           158:     end_with_slash( dirname );
        !           159:     (void) strcat( dirname, TILDE_MAP_2 );
        !           160: 
        !           161:     check_dir( dirname, pwd->pw_uid, pwd->pw_gid );
        !           162: 
        !           163: #else /* TILDE_MAP_2 */
        !           164: 
        !           165:     /* Gather the pieces. */
        !           166:     webdir = WEBDIR;
        !           167: #ifdef TILDE_MAP_1
        !           168:     prefix = TILDE_MAP_1;
        !           169: #else /* TILDE_MAP_1 */
        !           170:     prefix = "";
        !           171: #endif /* TILDE_MAP_1 */
        !           172: 
        !           173:     /* Assemble the directory name.  Be paranoid cause we're sgid. */
        !           174:     check_room(
        !           175:        sizeof(dirname),
        !           176:        strlen( webdir ) + strlen( prefix ) + strlen( username ) + 3 );
        !           177:     (void) strcpy( dirname, webdir );
        !           178:     end_with_slash( dirname );
        !           179:     if ( strlen( prefix ) != 0 )
        !           180:        {
        !           181:        (void) strcat( dirname, prefix );
        !           182:        end_with_slash( dirname );
        !           183:        }
        !           184:     (void) strcat( dirname, username );
        !           185: 
        !           186:     /* Assemble the link name. */
        !           187:     check_room( sizeof(linkname), strlen( homedir ) + strlen( LINK ) + 2 );
        !           188:     (void) strcpy( linkname, homedir );
        !           189:     end_with_slash( linkname );
        !           190:     (void) strcat( linkname, LINK );
        !           191: 
        !           192:     check_dir( dirname, pwd->pw_uid, pwd->pw_gid );
        !           193: 
        !           194:     /* Check the symlink. */
        !           195:     try_link_again: ;
        !           196:     if ( lstat( linkname, &sb ) < 0 )
        !           197:        {
        !           198:        if ( errno != ENOENT )
        !           199:            {
        !           200:            perror( linkname );
        !           201:            exit( 1 );
        !           202:            }
        !           203:        /* Doesn't exist.  Try to make it. */
        !           204:        if ( symlink( dirname, linkname ) < 0 )
        !           205:            {
        !           206:            if ( errno == ENOENT )
        !           207:                (void) printf( "\
        !           208: Some part of the path %s does not exist.\n\
        !           209: This is probably a configuration error.\n", linkname );
        !           210:            else
        !           211:                perror( linkname );
        !           212:            exit( 1 );
        !           213:            }
        !           214:        (void) printf( "Created symbolic link %s\n", linkname );
        !           215:        }
        !           216:     else
        !           217:        {
        !           218:        /* The link already exists.  Well, check that it is in
        !           219:        ** fact a link.
        !           220:        */
        !           221:        if ( ! S_ISLNK( sb.st_mode ) )
        !           222:            {
        !           223:            (void) printf( "\
        !           224: %s already exists but is not a\n\
        !           225: symbolic link!  Perhaps you have a real web subdirectory in your\n\
        !           226: home dir from a previous web server configuration?  You may have\n\
        !           227: to rename it, run %s again, and then copy in the old\n\
        !           228: contents.\n", linkname, argv0 );
        !           229:            exit( 1 );
        !           230:            }
        !           231:        /* Check the existing link's contents. */
        !           232:        if ( readlink( linkname, linkbuf, sizeof(linkbuf) ) < 0 )
        !           233:            {
        !           234:            perror( linkname );
        !           235:            exit( 1 );
        !           236:            }
        !           237:        if ( strcmp( dirname, linkbuf ) == 0 )
        !           238:            (void) printf( "Symbolic link %s already existed.\n", linkname );
        !           239:        else
        !           240:            {
        !           241:            (void) printf( "\
        !           242: Symbolic link %s already existed\n\
        !           243: but it points to the wrong place!  Attempting to remove and\n\
        !           244: recreate it.\n", linkname );
        !           245:            if ( unlink( linkname ) < 0 )
        !           246:                {
        !           247:                perror( linkname );
        !           248:                exit( 1 );
        !           249:                }
        !           250:            goto try_link_again;
        !           251:            }
        !           252:        }
        !           253: #endif /* TILDE_MAP_2 */
        !           254: 
        !           255:     exit( 0 );
        !           256:     }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>