root/extras/makeweb.c
/*DEFINITIONS
This source file includes following definitions.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 }
/*