ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/thttpd/extras/makeweb.c
Revision: 1.1
Committed: Mon Jun 18 21:11:58 2001 UTC (25 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: mp_j, dp_j, cp_j, HEAD
Branch point for: connpatch, dirpatch, mmapppatch
Log Message:
*** empty log message ***

File Contents

# Content
1 /* makeweb.c - let a user create a web subdirectory
2 **
3 ** Copyright © 1995 by Jef Poskanzer <jef@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 <stdio.h>
38 #include <string.h>
39 #include <pwd.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45
46 #define LINK "public_html"
47
48 static char* argv0;
49
50
51 static void
52 check_room( int size, int len )
53 {
54 if ( len > size )
55 {
56 (void) fprintf( stderr, "%s: internal error, out of room\n", argv0 );
57 exit( 1 );
58 }
59 }
60
61
62 static void
63 end_with_slash( char* str )
64 {
65 if ( str[strlen( str ) - 1] != '/' )
66 (void) strcat( str, "/" );
67 }
68
69
70 static void
71 check_dir( char* dirname, uid_t uid, gid_t gid )
72 {
73 struct stat sb;
74
75 /* Check the directory. */
76 if ( stat( dirname, &sb ) < 0 )
77 {
78 if ( errno != ENOENT )
79 {
80 perror( dirname );
81 exit( 1 );
82 }
83 /* Doesn't exist. Try to make it. */
84 if ( mkdir( dirname, 0755 ) < 0 )
85 {
86 if ( errno == ENOENT )
87 (void) printf( "\
88 Some part of the path %s does not exist.\n\
89 This is probably a configuration error.\n", dirname );
90 else
91 perror( dirname );
92 exit( 1 );
93 }
94 (void) printf( "Created web directory %s\n", dirname );
95 /* Try to change the group of the new dir to the user's group. */
96 (void) chown( dirname, -1, gid );
97 }
98 else
99 {
100 /* The directory already exists. Well, check that it is in
101 ** fact a directory.
102 */
103 if ( ! S_ISDIR( sb.st_mode ) )
104 {
105 (void) printf(
106 "%s already exists but is not a directory!\n", dirname );
107 exit( 1 );
108 }
109 if ( sb.st_uid != uid )
110 {
111 (void) printf(
112 "%s already exists but you don't own it!\n", dirname );
113 exit( 1 );
114 }
115 (void) printf( "Web directory %s already existed.\n", dirname );
116 }
117 }
118
119
120 int
121 main( int argc, char** argv )
122 {
123 char* webdir;
124 char* prefix;
125 struct passwd* pwd;
126 char* username;
127 char* homedir;
128 char dirname[5000];
129 char linkname[5000];
130 char linkbuf[5000];
131 struct stat sb;
132
133 argv0 = argv[0];
134 if ( argc != 1 )
135 {
136 (void) fprintf( stderr, "usage: %s\n", argv0 );
137 exit( 1 );
138 }
139
140 pwd = getpwuid( getuid() );
141 if ( pwd == (struct passwd*) 0 )
142 {
143 (void) fprintf( stderr, "%s: can't find your username\n", argv0 );
144 exit( 1 );
145 }
146 username = pwd->pw_name;
147 homedir = pwd->pw_dir;
148
149 #ifdef TILDE_MAP_2
150
151 /* All we have to do for the TILDE_MAP_2 case is make sure there's
152 ** a public_html subdirectory.
153 */
154 check_room(
155 sizeof(dirname), strlen( homedir ) + strlen( TILDE_MAP_2 ) + 2 );
156 (void) strcpy( dirname, homedir );
157 end_with_slash( dirname );
158 (void) strcat( dirname, TILDE_MAP_2 );
159
160 check_dir( dirname, pwd->pw_uid, pwd->pw_gid );
161
162 #else /* TILDE_MAP_2 */
163
164 /* Gather the pieces. */
165 webdir = WEBDIR;
166 #ifdef TILDE_MAP_1
167 prefix = TILDE_MAP_1;
168 #else /* TILDE_MAP_1 */
169 prefix = "";
170 #endif /* TILDE_MAP_1 */
171
172 /* Assemble the directory name. Be paranoid cause we're sgid. */
173 check_room(
174 sizeof(dirname),
175 strlen( webdir ) + strlen( prefix ) + strlen( username ) + 3 );
176 (void) strcpy( dirname, webdir );
177 end_with_slash( dirname );
178 if ( strlen( prefix ) != 0 )
179 {
180 (void) strcat( dirname, prefix );
181 end_with_slash( dirname );
182 }
183 (void) strcat( dirname, username );
184
185 /* Assemble the link name. */
186 check_room( sizeof(linkname), strlen( homedir ) + strlen( LINK ) + 2 );
187 (void) strcpy( linkname, homedir );
188 end_with_slash( linkname );
189 (void) strcat( linkname, LINK );
190
191 check_dir( dirname, pwd->pw_uid, pwd->pw_gid );
192
193 /* Check the symlink. */
194 try_link_again: ;
195 if ( lstat( linkname, &sb ) < 0 )
196 {
197 if ( errno != ENOENT )
198 {
199 perror( linkname );
200 exit( 1 );
201 }
202 /* Doesn't exist. Try to make it. */
203 if ( symlink( dirname, linkname ) < 0 )
204 {
205 if ( errno == ENOENT )
206 (void) printf( "\
207 Some part of the path %s does not exist.\n\
208 This is probably a configuration error.\n", linkname );
209 else
210 perror( linkname );
211 exit( 1 );
212 }
213 (void) printf( "Created symbolic link %s\n", linkname );
214 }
215 else
216 {
217 /* The link already exists. Well, check that it is in
218 ** fact a link.
219 */
220 if ( ! S_ISLNK( sb.st_mode ) )
221 {
222 (void) printf( "\
223 %s already exists but is not a\n\
224 symbolic link! Perhaps you have a real web subdirectory in your\n\
225 home dir from a previous web server configuration? You may have\n\
226 to rename it, run %s again, and then copy in the old\n\
227 contents.\n", linkname, argv0 );
228 exit( 1 );
229 }
230 /* Check the existing link's contents. */
231 if ( readlink( linkname, linkbuf, sizeof(linkbuf) ) < 0 )
232 {
233 perror( linkname );
234 exit( 1 );
235 }
236 if ( strcmp( dirname, linkbuf ) == 0 )
237 (void) printf( "Symbolic link %s already existed.\n", linkname );
238 else
239 {
240 (void) printf( "\
241 Symbolic link %s already existed\n\
242 but it points to the wrong place! Attempting to remove and\n\
243 recreate it.\n", linkname );
244 if ( unlink( linkname ) < 0 )
245 {
246 perror( linkname );
247 exit( 1 );
248 }
249 goto try_link_again;
250 }
251 }
252 #endif /* TILDE_MAP_2 */
253
254 exit( 0 );
255 }