ftpcount.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: ftpcount.c,v 1.20 1999/10/01 02:34:59 wuftpd Exp $
  25.  
  26. ****************************************************************************/
  27. #include "config.h"
  28. #ifdef TSOL
  29. #include <tsol/priv.h>
  30. #endif
  31. #include <stdio.h>
  32. #include <errno.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #ifdef HAVE_SYS_SYSLOG_H
  36. #include <sys/syslog.h>
  37. #endif
  38. #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
  39. #include <syslog.h>
  40. #endif
  41. #include <signal.h>
  42. #include <time.h>
  43. #include <ctype.h>
  44. #include <sys/types.h>
  45. #include <sys/stat.h>
  46. #include <sys/file.h>
  47. #include <sys/param.h>
  48. #ifdef HAVE_PATHS_H
  49. #include <paths.h>
  50. #endif
  51. #include "pathnames.h"
  52. #include "extensions.h"
  53. #if defined(HAVE_FCNTL_H)
  54. #include <fcntl.h>
  55. #endif
  56. struct c_list {
  57.     char *class;
  58.     struct c_list *next;
  59. };
  60. void print_copyright(void);
  61. char *progname;
  62. /*************************************************************************/
  63. /* FUNCTION  : parse_time                                                */
  64. /* PURPOSE   : Check a single valid-time-string against the current time */
  65. /*             and return whether or not a match occurs.                 */
  66. /* ARGUMENTS : a pointer to the time-string                              */
  67. /*************************************************************************/
  68. static int parsetime(char *whattime)
  69. {
  70.     static char *days[] =
  71.     {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Wk"};
  72.     time_t clock;
  73.     struct tm *curtime;
  74.     int wday, start, stop, ltime, validday, loop, match;
  75.     (void) time(&clock);
  76.     curtime = localtime(&clock);
  77.     wday = curtime->tm_wday;
  78.     validday = 0;
  79.     match = 1;
  80.     while (match && isalpha(*whattime) && isupper(*whattime)) {
  81. match = 0;
  82. for (loop = 0; loop < 8; loop++) {
  83.     if (strncmp(days[loop], whattime, 2) == 0) {
  84. whattime += 2;
  85. match = 1;
  86. if ((wday == loop) || ((loop == 7) && wday && (wday < 6)))
  87.     validday = 1;
  88.     }
  89. }
  90.     }
  91.     if (!validday) {
  92. if (strncmp(whattime, "Any", 3) == 0) {
  93.     validday = 1;
  94.     whattime += 3;
  95. }
  96. else
  97.     return (0);
  98.     }
  99.     if (sscanf(whattime, "%d-%d", &start, &stop) == 2) {
  100. ltime = curtime->tm_min + 100 * curtime->tm_hour;
  101. if ((start < stop) && ((ltime >= start) && ltime < stop))
  102.     return (1);
  103. if ((start > stop) && ((ltime >= start) || ltime < stop))
  104.     return (1);
  105.     }
  106.     else
  107. return (1);
  108.     return (0);
  109. }
  110. /*************************************************************************/
  111. /* FUNCTION  : validtime                                                 */
  112. /* PURPOSE   : Break apart a set of valid time-strings and pass them to  */
  113. /*             parse_time, returning whether or not ANY matches occurred */
  114. /* ARGUMENTS : a pointer to the time-string                              */
  115. /*************************************************************************/
  116. static int validtime(char *ptr)
  117. {
  118.     char *nextptr;
  119.     int good;
  120.     while (1) {
  121. nextptr = strchr(ptr, '|');
  122. if (strchr(ptr, '|') == NULL)
  123.     return (parsetime(ptr));
  124. *nextptr = '';
  125. good = parsetime(ptr);
  126. *nextptr++ = '|'; /* gotta restore the | or things get skipped! */
  127. if (good)
  128.     return (1);
  129. ptr = nextptr;
  130.     }
  131. }
  132. static int acl_getlimit(char *aclbuf, char *class)
  133. {
  134.     char *crptr, *ptr, linebuf[1024];
  135.     int limit;
  136.     while (*aclbuf != '') {
  137. if (strncasecmp(aclbuf, "limit", 5) == 0) {
  138.     for (crptr = aclbuf; *crptr++ != 'n';);
  139.     *--crptr = '';
  140.     strcpy(linebuf, aclbuf);
  141.     *crptr = 'n';
  142.     (void) strtok(linebuf, " t"); /* returns "limit" */
  143.     if ((ptr = strtok(NULL, " t")) && (strcmp(class, ptr) == 0)) {
  144. if ((ptr = strtok(NULL, " t"))) {
  145.     limit = atoi(ptr); /* returns limit <n> */
  146.     if ((ptr = strtok(NULL, " t")) && validtime(ptr))
  147. return (limit);
  148. }
  149.     }
  150. }
  151. while (*aclbuf && *aclbuf++ != 'n');
  152.     }
  153.     return (-1);
  154. }
  155. static int acl_countusers(char *class)
  156. {
  157.     int pidfd, count, stat, which;
  158.     char pidfile[1024];
  159.     char line[1024];
  160.     pid_t buf[MAXUSERS];
  161.     FILE *ZeFile;
  162. #ifndef HAVE_FLOCK
  163.     struct flock arg;
  164. #endif
  165. #ifdef TSOL
  166.     int retval;
  167. #endif
  168.     sprintf(pidfile, _PATH_PIDNAMES, class);
  169.     pidfd = open(pidfile, O_RDONLY);
  170.     if (pidfd == -1) {
  171. return (0);
  172.     }
  173. #ifdef HAVE_FLOCK
  174.     while (flock(pidfd, LOCK_EX)) {
  175. #ifndef NO_PID_SLEEP_MSGS
  176. syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");
  177. #endif
  178. #else
  179.     arg.l_type = F_RDLCK;
  180.     arg.l_whence = arg.l_start = arg.l_len = 0;
  181. #ifdef TSOL
  182.     if ((retval = set_effective_priv(PRIV_ON, 1, PRIV_FILE_LOCK)) != 0) {
  183. syslog(LOG_ERR, "Cannot add PRIV_FILE_LOCK to eff. priv. set");
  184.     }
  185. #endif
  186.     while (-1 == fcntl(pidfd, F_SETLK, &arg)) {
  187. #ifndef NO_PID_SLEEP_MSGS
  188. syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");
  189. #endif
  190. #endif /* HAVE_FLOCK */
  191. sleep(1);
  192.     }
  193. #ifndef HAVE_FLOCK
  194. #ifdef TSOL
  195.     if ((retval = set_effective_priv(PRIV_OFF, 1, PRIV_FILE_LOCK)) != 0) {
  196. syslog(LOG_ERR, "Cannot remove PRIV_FILE_LOCK from eff. priv. set");
  197.     }
  198. #endif
  199. #endif /* HAVE_FLOCK */
  200.     count = 0;
  201.     if (read(pidfd, (void *) buf, sizeof(buf)) == sizeof(buf)) {
  202. for (which = 0; which < MAXUSERS; which++)
  203.     if (buf[which]) {
  204. stat = kill(buf[which], SIGCONT);
  205. if (((stat == -1) && (errno == EPERM)) || !stat) {
  206.     if (strcmp(progname, "ftpcount")) {
  207. #if defined(SVR4)
  208. #ifdef AIX
  209. sprintf(line, "/bin/ps %d", buf[which]);
  210. #elif defined(sun)
  211. sprintf(line, "/usr/ucb/ps auxww %ld", buf[which]);
  212. #else
  213. #if defined (LINUX)
  214. sprintf(line, "/bin/ps axwww %d", buf[which]);
  215. #else
  216. sprintf(line, "/bin/ps -f -p %d", buf[which]);
  217. #endif
  218. #endif
  219. #elif defined(M_UNIX)
  220. sprintf(line, "/bin/ps -f -p %d", buf[which]);
  221. #else
  222. sprintf(line, "/bin/ps %d", buf[which]);
  223. #endif
  224. ZeFile = popen(line, "r");
  225. fgets(line, 1024, ZeFile);
  226. fgets(line, 1024, ZeFile);
  227. {
  228.     size_t i;
  229.     for (i = strlen(line); (i > 0) && ((line[i - 1] == ' ') || (line[i - 1] == 'n')); --i)
  230. line[i - 1] = '';
  231. }
  232. printf("%sn", line);
  233. pclose(ZeFile);
  234.     }
  235.     count++;
  236. }
  237.     }
  238.     }
  239. #ifdef HAVE_FLOCK
  240.     flock(pidfd, LOCK_UN);
  241. #else
  242.     arg.l_type = F_UNLCK;
  243.     arg.l_whence = arg.l_start = arg.l_len = 0;
  244. #ifdef TSOL
  245.     if ((retval = set_effective_priv(PRIV_ON, 1, PRIV_FILE_LOCK)) != 0) {
  246. syslog(LOG_ERR, "Cannot add PRIV_FILE_LOCK to eff. priv. set");
  247.     }
  248. #endif
  249.     fcntl(pidfd, F_SETLK, &arg);
  250. #ifdef TSOL
  251.     if ((retval = set_effective_priv(PRIV_OFF, 1, PRIV_FILE_LOCK)) != 0) {
  252. syslog(LOG_ERR, "Cannot remove PRIV_FILE_LOCK from eff. priv. set");
  253.     }
  254. #endif
  255. #endif /* HAVE_FLOCK */
  256.     close(pidfd);
  257.     return (count);
  258. }
  259. static void new_list(struct c_list **list)
  260. {
  261.     (*list) = (struct c_list *) malloc(sizeof(struct c_list));
  262.     if ((*list) == NULL) {
  263. perror("malloc error in new_list");
  264. exit(0);
  265.     }
  266.     (*list)->next = NULL;
  267. }
  268. static int add_list(char *class, struct c_list **list)
  269. {
  270.     struct c_list *cp;
  271.     for (cp = (*list)->next; cp; cp = cp->next) {
  272. if (!strcmp(cp->class, class))
  273.     return (-1);
  274.     }
  275.     cp = (struct c_list *) malloc(sizeof(struct c_list));
  276.     if (cp == NULL) {
  277. perror("malloc error in add_list");
  278. exit(0);
  279.     }
  280.     cp->class = (char *) malloc(strlen(class) + 1);
  281.     if (cp->class == NULL) {
  282. perror("malloc error in add_list");
  283. exit(0);
  284.     }
  285.     strcpy(cp->class, class);
  286.     cp->next = (*list)->next;
  287.     (*list)->next = cp;
  288.     return (1);
  289. }
  290. int main(int argc, char **argv)
  291. {
  292.     FILE *accessfile;
  293.     char class[80], linebuf[1024], *aclbuf, *myaclbuf, *crptr;
  294.     int limit, c;
  295.     struct stat finfo;
  296.     struct c_list *list;
  297. #ifdef TSOL
  298. /* Before anything, clear the effective privilege set */
  299.     int retval;
  300.     if ((retval = set_effective_priv(PRIV_SET, 0)) != 0) {
  301. syslog(LOG_ERR, "ftp[count|who] cannot clear effective privileges!");
  302. exit(1);
  303.     }
  304. #endif
  305.     if ((progname = strrchr(argv[0], '/')))
  306. ++progname;
  307.     else
  308. progname = argv[0];
  309.     if (argc > 1) {
  310. while ((c = getopt(argc, argv, "V")) != EOF) {
  311.     switch (c) {
  312.     case 'V':
  313. print_copyright();
  314. exit(0);
  315.     default:
  316. fprintf(stderr, "usage: %s [-V]n", progname);
  317. exit(1);
  318.     }
  319. }
  320.     }
  321.     if ((accessfile = fopen(_PATH_FTPACCESS, "r")) == NULL) {
  322. if (errno != ENOENT)
  323.     perror("ftpcount: could not open() access file");
  324. exit(1);
  325.     }
  326.     if (stat(_PATH_FTPACCESS, &finfo)) {
  327. perror("ftpcount: could not stat() access file");
  328. exit(1);
  329.     }
  330.     if (finfo.st_size == 0) {
  331. printf("%s: no service classes defined, no usage count keptn", progname);
  332. exit(0);
  333.     }
  334.     else {
  335. if (!(aclbuf = (char *) malloc((size_t) finfo.st_size + 1))) {
  336.     perror("ftpcount: could not malloc aclbuf");
  337.     exit(1);
  338. }
  339. fread(aclbuf, (size_t) finfo.st_size, 1, accessfile);
  340. *(aclbuf + (size_t) finfo.st_size) = '';
  341.     }
  342.     (void) new_list(&list);
  343.     myaclbuf = aclbuf;
  344.     while (*myaclbuf != '') {
  345. if (strncasecmp(myaclbuf, "class", 5) == 0) {
  346.     for (crptr = myaclbuf; *crptr++ != 'n';);
  347.     *--crptr = '';
  348.     strcpy(linebuf, myaclbuf);
  349.     *crptr = 'n';
  350.     (void) strtok(linebuf, " t"); /* returns "class" */
  351.     strcpy(class, strtok(NULL, " t")); /* returns class name */
  352.     if ((add_list(class, &list)) < 0) {
  353. /* we have a class with multiple "class..." lines so, only
  354.  * display one count... */
  355. ;
  356.     }
  357.     else {
  358. limit = acl_getlimit(myaclbuf, class);
  359. if (strcmp(progname, "ftpcount")) {
  360.     printf("Service class %s: n", class);
  361.     printf("   - %3d users ", acl_countusers(class));
  362. }
  363. else {
  364.     printf("Service class %-20.20s - %3d users ",
  365.    class, acl_countusers(class));
  366. }
  367. if (limit == -1)
  368.     printf("(no maximum)n");
  369. else
  370.     printf("(%3d maximum)n", limit);
  371.     }
  372. }
  373. while (*myaclbuf && *myaclbuf++ != 'n');
  374.     }
  375.     return (0);
  376. }