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>