ftpshut.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:11k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /****************************************************************************  
  2.  
  3.   Copyright (c) 1999 WU-FTPD Development Group.  
  4.   All rights reserved.
  5.   
  6.   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
  7.     The Regents of the University of California.
  8.   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
  9.   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
  10.   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
  11.   Portions Copyright (c) 1998 Sendmail, Inc.
  12.   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
  13.   Portions Copyright (c) 1997 by Stan Barber.
  14.   Portions Copyright (c) 1997 by Kent Landfield.
  15.   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
  16.     Free Software Foundation, Inc.  
  17.  
  18.   Use and distribution of this software and its source code are governed 
  19.   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
  20.  
  21.   If you did not receive a copy of the license, it may be obtained online
  22.   at http://www.wu-ftpd.org/license.html.
  23.  
  24.   $Id: ftpshut.c,v 1.11 1999/09/19 19:21:24 wuftpd Exp $
  25.  
  26. ****************************************************************************/
  27. /* ftpshut 
  28.  * ======= 
  29.  * creates the ftpd shutdown file.
  30.  */
  31. #include "config.h"
  32. #include <errno.h>
  33. #include <pwd.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <ctype.h>
  37. #ifdef TIME_WITH_SYS_TIME
  38. #include <time.h>
  39. #include <sys/time.h>
  40. #else
  41. #ifdef HAVE_SYS_TIME_H
  42. #include <sys/time.h>
  43. #else
  44. #include <time.h>
  45. #endif
  46. #endif
  47. #include <sys/types.h>
  48. #include <sys/stat.h>
  49. #include <sys/file.h>
  50. #include <sys/param.h>
  51. #include "pathnames.h"
  52. #define  WIDTH  70
  53. int verbose = 0;
  54. int denyoffset = 10; /* default deny time   */
  55. int discoffset = 5; /* default disc time   */
  56. char *message = "System shutdown at %s"; /* default message     */
  57. struct tm *tp;
  58. #define MAXVIRTUALS 512
  59. char *msgfiles[MAXVIRTUALS];
  60. int numfiles = 0;
  61. #ifdef VIRTUAL
  62. extern int read_servers_line(FILE *, char *, char *);
  63. #endif
  64. void print_copyright(void);
  65. static int newfile(char *fpath)
  66. {
  67.     int i;
  68.     int fnd;
  69.     /*  
  70.        ** Check to see if the message file path has already been
  71.        ** seen. If so then there is no need to create it again.
  72.      */
  73.     fnd = 0;
  74.     for (i = 0; i < numfiles; i++) {
  75. if (strcmp(msgfiles[i], fpath) == 0) {
  76.     fnd = 1;
  77.     break;
  78. }
  79.     }
  80.     if (!fnd) {
  81. msgfiles[numfiles++] = strdup(fpath);
  82. return (1);
  83.     }
  84.     return (0);
  85. }
  86. static int shutdown_msgfile(char *filename, char *buffer)
  87. {
  88.     FILE *fp;
  89.     if ((fp = fopen(filename, "w")) == NULL) {
  90. perror("Couldn't open shutdown file");
  91. return (1);
  92.     }
  93.     fprintf(fp, "%.4d %.2d %.2d %.2d %.2d %.4d %.4dn",
  94.     (tp->tm_year) + 1900,
  95.     tp->tm_mon,
  96.     tp->tm_mday,
  97.     tp->tm_hour,
  98.     tp->tm_min,
  99.     denyoffset,
  100.     discoffset);
  101.     fprintf(fp, "%sn", buffer);
  102.     fclose(fp);
  103.     if (verbose)
  104. printf("%s createdn", filename);
  105.     return (0);
  106. }
  107. static void massage(char *buf)
  108. {
  109.     char *sp = NULL;
  110.     char *ptr;
  111.     int i = 0;
  112.     int j = 0;
  113.     ptr = buf;
  114.     while (*ptr++ != '') {
  115. ++i;
  116. /* if we have a space, keep track of where and at what "count" */
  117. if (*ptr == ' ') {
  118.     sp = ptr;
  119.     j = i;
  120. }
  121. /* magic cookies... */
  122. if (*ptr == '%') {
  123.     ++ptr;
  124.     switch (*ptr) {
  125.     case 'r':
  126.     case 's':
  127.     case 'd':
  128.     case 'T':
  129. i = i + 24;
  130. break;
  131.     case 'n':
  132. i = 0;
  133. break;
  134.     case 'C':
  135.     case 'R':
  136.     case 'L':
  137.     case 'U':
  138. i = i + 10;
  139. break;
  140.     case 'M':
  141.     case 'N':
  142. i = i + 3;
  143. break;
  144.     case '':
  145. return;
  146. /* break; */
  147.     default:
  148. i = i + 1;
  149. break;
  150.     }
  151. }
  152. /* break up the long lines... */
  153. if ((i >= WIDTH) && (sp != NULL)) {
  154.     *sp = 'n';
  155.     sp = NULL;
  156.     i = i - j;
  157. }
  158.     }
  159. }
  160. int main(int argc, char **argv)
  161. {
  162.     time_t c_time = 0;
  163.     char buf[BUFSIZ];
  164.     int c;
  165.     extern int optind;
  166.     extern char *optarg;
  167.     FILE *accessfile;
  168.     char *aclbuf, *myaclbuf, *crptr;
  169.     char *sp = NULL;
  170.     char linebuf[1024];
  171.     char shutmsg[BUFSIZ];
  172.     char anonpath[BUFSIZ];
  173.     struct stat finfo;
  174.     struct passwd *pwent;
  175. #ifdef VIRTUAL
  176.     char *cp = NULL;
  177.     FILE *svrfp;
  178.     char hostaddress[32];
  179.     char root[MAXPATHLEN];
  180.     char accesspath[MAXPATHLEN];
  181.     char configdir[MAXPATHLEN];
  182.     char altmsgpath[MAXPATHLEN];
  183. #endif
  184.     while ((c = getopt(argc, argv, "vVl:d:")) != EOF) {
  185. switch (c) {
  186. case 'v':
  187.     verbose++;
  188.     break;
  189. case 'l':
  190.     denyoffset = atoi(optarg);
  191.     break;
  192. case 'd':
  193.     discoffset = atoi(optarg);
  194.     break;
  195. case 'V':
  196.     print_copyright();
  197.     exit(0);
  198. default:
  199.     fprintf(stderr,
  200. "Usage: %s [-d min] [-l min] now ["message"]n", argv[0]);
  201.     fprintf(stderr,
  202. "       %s [-d min] [-l min] +dd ["message"]n", argv[0]);
  203.     fprintf(stderr,
  204.        "       %s [-d min] [-l min] HHMM ["message"]n", argv[0]);
  205.     exit(-1);
  206. }
  207.     }
  208.     if ((accessfile = fopen(_PATH_FTPACCESS, "r")) == NULL) {
  209. if (errno != ENOENT)
  210.     perror("ftpshut: could not open() access file");
  211. exit(1);
  212.     }
  213.     if (stat(_PATH_FTPACCESS, &finfo)) {
  214. perror("ftpshut: could not stat() access file");
  215. exit(1);
  216.     }
  217.     if (finfo.st_size == 0) {
  218. printf("ftpshut: no service shutdown path definedn");
  219. exit(0);
  220.     }
  221.     else {
  222. if (!(aclbuf = (char *) malloc(finfo.st_size + 1))) {
  223.     perror("ftpshut: could not malloc aclbuf");
  224.     exit(1);
  225. }
  226. fread(aclbuf, finfo.st_size, 1, accessfile);
  227. *(aclbuf + finfo.st_size) = '';
  228.     }
  229.     myaclbuf = aclbuf;
  230.     while (*myaclbuf != '') {
  231. if (strncasecmp(myaclbuf, "shutdown", 8) == 0) {
  232.     for (crptr = myaclbuf; *crptr++ != 'n';);
  233.     *--crptr = '';
  234.     strcpy(linebuf, myaclbuf);
  235.     *crptr = 'n';
  236.     (void) strtok(linebuf, " t"); /* returns "shutdown" */
  237.     sp = strtok(NULL, " t"); /* returns shutdown path */
  238.     strcpy(shutmsg, sp); /* save for future use */
  239. }
  240. while (*myaclbuf && *myaclbuf++ != 'n');
  241.     }
  242.     /* three cases 
  243.      * -- now 
  244.      * -- +ddd 
  245.      * -- HHMM 
  246.      */
  247.     c = -1;
  248.     if (optind < argc) {
  249. if (!strcasecmp(argv[optind], "now")) {
  250.     c_time = time(0);
  251.     tp = localtime(&c_time);
  252. }
  253. else if ((*(argv[optind])) == '+') {
  254.     c_time = time(0);
  255.     c_time += 60 * atoi(++(argv[optind]));
  256.     tp = localtime(&c_time);
  257. }
  258. else if ((c = atoi(argv[optind])) >= 0) {
  259.     c_time = time(0);
  260.     tp = localtime(&c_time);
  261.     tp->tm_hour = c / 100;
  262.     tp->tm_min = c % 100;
  263.     if ((tp->tm_hour > 23) || (tp->tm_min > 59)) {
  264. fprintf(stderr, "Illegal time format.n");
  265. return (1);
  266.     }
  267. }
  268.     }
  269.     if (c_time <= 0) {
  270. fprintf(stderr, "Usage: %s [-d min] [-l min] now ["message"]n",
  271. argv[0]);
  272. fprintf(stderr, "       %s [-d min] [-l min] +dd ["message"]n",
  273. argv[0]);
  274. fprintf(stderr, "       %s [-d min] [-l min] HHMM ["message"]n",
  275. argv[0]);
  276. exit(1);
  277.     }
  278.     if (sp == NULL) {
  279. fprintf(stderr, "No shutdown file defined in ftpaccess file.n");
  280. exit(1);
  281.     }
  282.     /* do we have a shutdown message? */
  283.     if (++optind < argc) {
  284. strncpy(buf, argv[optind++], sizeof(buf));
  285. buf[sizeof(buf) - 1] = '';
  286.     }
  287.     else
  288. strcpy(buf, message);
  289.     massage(buf);
  290.     /* 
  291.        ** Create the system shutdown message file at the location
  292.        ** specified in the ftpaccess 'shutdown' directive.  This
  293.        ** is for support of real system users.
  294.      */
  295.     c = shutdown_msgfile(shutmsg, buf);
  296.     msgfiles[numfiles++] = shutmsg;
  297.     /* 
  298.        ** Determine if the site supports anonymous ftp and if so, create
  299.        ** the shutdown message file in the anonymous ftp area as well
  300.        ** so that shutdown works appropriately for both real and guest 
  301.        ** accounts. Save in msgfiles array for later comparison.
  302.      */
  303.     if ((pwent = getpwnam("ftp")) != NULL) {
  304. sprintf(anonpath, "%s%s", pwent->pw_dir, shutmsg);
  305. if (newfile(anonpath))
  306.     c += shutdown_msgfile(anonpath, buf);
  307.     }
  308. #ifdef VIRTUAL
  309.     /*
  310.        ** Search the Master access file for virtual ftp servers.
  311.        ** If found, construct a path to the shutdown message file
  312.        ** under the virtual server's root.  Don't duplicate what
  313.        ** is specified in the "ftp" account directory information.
  314.      */
  315.     rewind(accessfile);
  316.     while (fgets(linebuf, sizeof(linebuf) - 1, accessfile) != NULL) {
  317. if (strncasecmp(linebuf, "virtual", 7) == 0) {
  318.     if ((sp = strstr(linebuf, "root")) != NULL) {
  319. if ((cp = strchr(sp, 'n')) != NULL)
  320.     *cp = ''; /* strip newline */
  321. sp += 4; /* skip past "root" keyword */
  322. while (*sp && isspace(*sp)) /* skip whitespace to root path */
  323.     sp++;
  324. cp = sp;
  325. while (*sp && !isspace(*sp))
  326.     sp++;
  327. *sp = ''; /* truncate blanks, comments etc. */
  328. sprintf(altmsgpath, "%s%s", cp, shutmsg);
  329. if (newfile(altmsgpath))
  330.     c += shutdown_msgfile(altmsgpath, buf);
  331.     }
  332. }
  333.     }
  334.     /*
  335.        ** Need to deal with the access files at the virtual domain directory
  336.        ** locations specified in the ftpservers file. 
  337.      */
  338.     if ((svrfp = fopen(_PATH_FTPSERVERS, "r")) != NULL) {
  339. while (read_servers_line(svrfp, hostaddress, configdir) == 1) {
  340.     /* get rid of any trailing slash */
  341.     sp = configdir + (strlen(configdir) - 1);
  342.     if (*sp == '/')
  343. *sp = '';
  344.     /* 
  345.        ** check to see that a valid directory value was
  346.        ** supplied and not something such as "INTERNAL"
  347.        **
  348.        ** It is valid to have a string such as "INTERNAL" in the
  349.        ** ftpservers entry. This is not an error. Silently ignore it.
  350.      */
  351.     if ((stat(configdir, &finfo) == 0) &&
  352. ((finfo.st_mode & S_IFMT) == S_IFDIR))
  353. sprintf(accesspath, "%s/ftpaccess", configdir);
  354.     else
  355. continue;
  356.     (void) fclose(accessfile);
  357.     if ((accessfile = fopen(accesspath, "r")) == NULL) {
  358. if (errno != ENOENT) {
  359.     fprintf(stderr, "%s: could not open %s accessfilen",
  360.     argv[0], accesspath);
  361.     continue;
  362. }
  363.     }
  364.     /* need to find the root path */
  365.     while (fgets(linebuf, sizeof(linebuf) - 1, accessfile) != NULL) {
  366. if ((sp = strstr(linebuf, "root")) != NULL) {
  367.     if ((cp = strchr(sp, 'n')) != NULL)
  368. *cp = ''; /* strip newline */
  369.     sp += 4; /* skip past "root" keyword */
  370.     while (*sp && isspace(*sp)) /* skip whitespace to path */
  371. sp++;
  372.     cp = sp;
  373.     while (*sp && !isspace(*sp))
  374. sp++;
  375.     *sp = ''; /* truncate blanks, comments etc. */
  376.     strcpy(root, cp);
  377.     break;
  378. }
  379.     }
  380.     /* need to find the shutdown message file path */
  381.     rewind(accessfile);
  382.     while (fgets(linebuf, sizeof(linebuf) - 1, accessfile) != NULL) {
  383. if ((sp = strstr(linebuf, "shutdown")) != NULL) {
  384.     if ((cp = strchr(sp, 'n')) != NULL)
  385. *cp = ''; /* strip newline */
  386.     sp += 8; /* skip past "root" keyword */
  387.     while (*sp && isspace(*sp)) /* skip whitespace to path */
  388. sp++;
  389.     cp = sp;
  390.     while (*sp && !isspace(*sp))
  391. sp++;
  392.     *sp = ''; /* truncate blanks, comments etc. */
  393.     break;
  394. }
  395.     }
  396.     /*
  397.        ** check to make sure the admin hasn't specified 
  398.        ** a complete path in the 'shutdown' directive.
  399.      */
  400.     if ((sp = strstr(cp, root)) == NULL)
  401. sprintf(altmsgpath, "%s%s", root, cp);
  402.     /*
  403.        ** Check to see if the message file has been created elsewhere.
  404.      */
  405.     if (newfile(altmsgpath))
  406. c += shutdown_msgfile(altmsgpath, buf);
  407. }
  408. fclose(svrfp);
  409.     }
  410. #endif
  411.     fclose(accessfile);
  412.     free(aclbuf);
  413.     return (c > 0 ? 1 : 0);
  414. }