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

# User Rev Content
1 root 1.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     }