xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/in.ftpd/ftprestart.c (revision 0:68f95e015346)
1 /*
2  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /****************************************************************************
9 
10   Copyright (c) 1999,2000 WU-FTPD Development Group.
11   All rights reserved.
12 
13   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
14     The Regents of the University of California.
15   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
16   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
17   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
18   Portions Copyright (c) 1998 Sendmail, Inc.
19   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
20   Portions Copyright (c) 1997 by Stan Barber.
21   Portions Copyright (c) 1997 by Kent Landfield.
22   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
23     Free Software Foundation, Inc.
24 
25   Use and distribution of this software and its source code are governed
26   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
27 
28   If you did not receive a copy of the license, it may be obtained online
29   at http://www.wu-ftpd.org/license.html.
30 
31   $Id: ftprestart.c,v 1.7 2000/07/01 18:17:39 wuftpd Exp $
32 
33 ****************************************************************************/
34 /* ftprestart
35    **
36    ** removes the ftpd shutdown files.
37    **
38    **  In the previous versions of the wu-ftpd server it was recommended to
39    **  create a link in order for shutdown to work properly for real and
40    **  anonymous user, e.g.  If you use ftpshut, it will create a message
41    **  file at the location specified in the ftpaccess shutdown directive.
42    **  ln -s /etc/shutmsg  ~ftp/etc/shutmsg
43    **
44    **  When ftp service is to be restarted after an ftpshut, the shutdown
45    **  message files must be removed. This program reads the ftpaccess
46    **  file and finds the location of the system shutdown file.  It
47    **  then proceeds to construct a path to the anonymous ftp area with
48    **  information found in the "ftp" account.  If virtual ftp servers
49    **  are enabled, the shutdown message files within those directories
50    **  are also removed.
51    **
52    **  Initial Author: Kent Landfield
53  */
54 #include "config.h"
55 
56 #include <errno.h>
57 #include <stdio.h>
58 #include <string.h>
59 #include <ctype.h>
60 #include <sys/stat.h>
61 #include <sys/param.h>
62 #include <pwd.h>
63 #if defined(VIRTUAL) && defined(INET6)
64 #include <netinet/in.h>
65 #endif
66 
67 #include "pathnames.h"
68 
69 #define MAXVIRTUALS 512
70 
71 char *progname;
72 char *msgfiles[MAXVIRTUALS];
73 int numfiles = 0;
74 
75 #ifdef VIRTUAL
76 extern int read_servers_line(FILE *, char *, size_t, char *, size_t);
77 #endif
78 
79 void print_copyright(void);
80 
newfile(char * fpath)81 static int newfile(char *fpath)
82 {
83     int i;
84     int fnd;
85 
86     /*
87        ** Check to see if the message file path has already been
88        ** seen. If so then there is no need to create it again.
89      */
90 
91     fnd = 0;
92     for (i = 0; i < numfiles; i++) {
93 	if (strcmp(msgfiles[i], fpath) == 0) {
94 	    fnd = 1;
95 	    break;
96 	}
97     }
98     if (!fnd) {
99 	msgfiles[numfiles++] = strdup(fpath);
100 	return (1);
101     }
102     return (0);
103 }
104 
remove_shutdown_file(char * path)105 static int remove_shutdown_file(char *path)
106 {
107     struct stat stbuf;
108     int rc = 1;			/* guilty until proven innocent */
109 
110     fprintf(stderr, "%s: %s ", progname, path);
111 
112     if (stat(path, &stbuf) == 0) {
113 	if ((rc = unlink(path)) == 0)
114 	    fprintf(stderr, "removed.\n");
115 	else
116 	    perror(path);
117     }
118     else
119 	fprintf(stderr, "does not exist.\n");
120 
121     return (rc);
122 }
123 
main(int argc,char ** argv)124 int main(int argc, char **argv)
125 {
126     int c;
127 
128     char *p;
129     char *cp = NULL;
130     char linebuf[BUFSIZ];
131     char shutmsg[256];
132     char anonpath[MAXPATHLEN];
133     FILE *accessfile;
134     struct passwd *pw;
135 
136 #if defined(VIRTUAL)
137     FILE *svrfp;
138     char *sp;
139 #ifdef INET6
140     char hostaddress[INET6_ADDRSTRLEN];
141 #else
142     char hostaddress[32];
143 #endif
144     char root[MAXPATHLEN];
145     char configdir[MAXPATHLEN];
146     char accesspath[MAXPATHLEN];
147     char altmsgpath[MAXPATHLEN];
148     struct stat finfo;
149 #endif
150 
151     if ((progname = strrchr(argv[0], '/')))
152 	++progname;
153     else
154 	progname = argv[0];
155 
156     if (argc > 1) {
157 	while ((c = getopt(argc, argv, "V")) != EOF) {
158 	    switch (c) {
159 	    case 'V':
160 		print_copyright();
161 		exit(0);
162 	    default:
163 		fprintf(stderr, "usage: %s [-V]\n", progname);
164 		exit(1);
165 	    }
166 	}
167     }
168 
169     if ((accessfile = fopen(_PATH_FTPACCESS, "r")) == NULL) {
170 	if (errno != ENOENT)
171 	    fprintf(stderr, "%s: could not open access file %s: %s\n",
172 		    progname, _PATH_FTPACCESS, strerror(errno));
173 	exit(1);
174     }
175 
176     /*
177        ** Search the access file for the 'shutdown' directive.
178      */
179 
180     while (fgets(linebuf, BUFSIZ, accessfile) != NULL) {
181 	if (strncasecmp(linebuf, "shutdown", 8) == 0) {
182 	    (void) strtok(linebuf, " \t");
183 	    (void) strlcpy(shutmsg, strtok(NULL, " \t"), sizeof(shutmsg));
184 	    cp = shutmsg;
185 	    if ((p = strchr(cp, '\n')) != NULL)
186 		*p = '\0';
187 	}
188     }
189 
190     if (cp == NULL) {
191 	fprintf(stderr, "%s: no shutdown path defined in ftpaccess file %s.\n",
192                 progname, _PATH_FTPACCESS);
193 	exit(1);
194     }
195 
196     msgfiles[numfiles++] = shutmsg;
197 
198     /*
199        ** Get the location of the anonymous ftp area and check
200        ** to see if there is a file shutdown file there as well.
201        ** If so, remove it.
202      */
203     if ((pw = getpwnam("ftp")) != NULL) {
204 	(void) snprintf(anonpath, sizeof(anonpath), "%s%s", pw->pw_dir,
205 	    shutmsg);
206 	if (newfile(anonpath))
207 	    (void) remove_shutdown_file(anonpath);
208     }
209 
210 #ifdef VIRTUAL
211     /*
212        ** Search the access file for virtual ftp servers.
213        ** If found, check if there are links/shutdown
214        ** message files files in the virtual server areas.
215        ** If so, remove them.
216      */
217 
218     rewind(accessfile);
219 
220     while (fgets(linebuf, sizeof(linebuf) - 1, accessfile) != NULL) {
221 	if (strncasecmp(linebuf, "virtual", 7) == 0) {
222 	    if ((p = strstr(linebuf, "root")) != NULL) {
223 		p += 4;
224 
225 		if ((cp = strchr(linebuf, '\n')) != NULL)
226 		    *cp = '\0';
227 
228 		/* skip to the path */
229 
230 		while (*p && isspace(*p))
231 		    p++;
232 		cp = p;
233 		while (*p && isalnum(*p))
234 		    p++;
235 
236 		(void) snprintf(altmsgpath, sizeof(altmsgpath), "%s%s", cp,
237 		    shutmsg);
238 		if (newfile(altmsgpath))
239 		    (void) remove_shutdown_file(altmsgpath);
240 	    }
241 	}
242     }
243 
244 
245     /*
246        ** Need to deal with the access files at the virtual domain directory
247        ** locations specified in the ftpservers file.
248      */
249 
250     if ((svrfp = fopen(_PATH_FTPSERVERS, "r")) != NULL) {
251 	while (read_servers_line(svrfp, hostaddress, sizeof(hostaddress),
252 	       configdir, sizeof(configdir)) == 1) {
253 	    /* get rid of any trailing slash */
254 	    sp = configdir + (strlen(configdir) - 1);
255 	    if (*sp == '/')
256 		*sp = '\0';
257 
258 	    /*
259 	       ** check to see that a valid directory value was
260 	       ** supplied and not something such as "INTERNAL"
261 	       **
262 	       ** It is valid to have a string such as "INTERNAL" in the
263 	       ** ftpservers entry. This is not an error. Silently ignore it.
264 	     */
265 
266 	    if ((stat(configdir, &finfo) < 0) ||
267 		((finfo.st_mode & S_IFMT) != S_IFDIR))
268 		continue;
269 
270 	    (void) snprintf(accesspath, sizeof(accesspath), "%s/ftpaccess",
271 		configdir);
272 
273 	    (void) fclose(accessfile);
274 
275 	    if ((accessfile = fopen(accesspath, "r")) == NULL) {
276 		if (errno != ENOENT) {
277 		    fprintf(stderr, "%s: could not open access file %s: %s\n",
278 			    progname, accesspath, strerror(errno));
279 		    continue;
280 		}
281 	    }
282 
283 	    /* need to find the root path */
284 
285 	    while (fgets(linebuf, sizeof(linebuf) - 1, accessfile) != NULL) {
286 		if ((sp = strstr(linebuf, "root")) != NULL) {
287 		    if ((cp = strchr(sp, '\n')) != NULL)
288 			*cp = '\0';	/* strip newline */
289 		    sp += 4;	/* skip past "root" keyword */
290 
291 		    while (*sp && isspace(*sp))		/* skip whitespace to path */
292 			sp++;
293 		    cp = sp;
294 		    while (*sp && !isspace(*sp))
295 			sp++;
296 		    *sp = '\0';	/* truncate blanks, comments etc. */
297 		    (void) strlcpy(root, cp, sizeof(root));
298 		    break;
299 		}
300 	    }
301 
302 	    rewind(accessfile);
303 
304 	    /* need to find the shutdown message file path */
305 
306 	    while (fgets(linebuf, sizeof(linebuf) - 1, accessfile) != NULL) {
307 		if ((sp = strstr(linebuf, "shutdown")) != NULL) {
308 		    if ((cp = strchr(sp, '\n')) != NULL)
309 			*cp = '\0';	/* strip newline */
310 		    sp += 8;	/* skip past "root" keyword */
311 
312 		    while (*sp && isspace(*sp))		/* skip whitespace to path */
313 			sp++;
314 		    cp = sp;
315 		    while (*sp && !isspace(*sp))
316 			sp++;
317 		    *sp = '\0';	/* truncate blanks, comments etc. */
318 		    break;
319 		}
320 	    }
321 
322 	    /*
323 	       ** check to make sure the admin hasn't specified
324 	       ** a complete path in the 'shutdown' directive.
325 	     */
326 	    if ((sp = strstr(cp, root)) == NULL)
327 		(void) snprintf(altmsgpath, sizeof(altmsgpath), "%s%s", root,
328 		    cp);
329 
330 	    if (newfile(altmsgpath))
331 		(void) remove_shutdown_file(altmsgpath);
332 	}
333 	fclose(svrfp);
334     }
335 #endif /* VIRTUAL */
336 
337     fclose(accessfile);
338 
339     /*
340        ** Time to remove the system wide shutdown file.
341      */
342     return (remove_shutdown_file(shutmsg));
343 }
344