File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / thttpd / extras / makeweb.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:21:13 2012 UTC (13 years, 1 month ago) by misho
Branches: thttpd, MAIN
CVS tags: v2_25b, HEAD
thttpd

    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>