root/extras/makeweb.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_room
  2. end_with_slash
  3. check_dir
  4. main

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

/* [previous][next][first][last][top][bottom][index][help] */