Annotation of embedaddon/thttpd/extras/makeweb.c, revision 1.1.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>