home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume16 / ichk / patch1 / ichk.c next >
Encoding:
C/C++ Source or Header  |  1991-02-06  |  6.0 KB  |  279 lines

  1.  
  2. #ifdef SCCSID
  3. static sccsid[] = "@(#) ichk.c 1.5 91/02/01  04:01:47";  
  4. #endif
  5.  
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <sys/statfs.h>
  9. #include <sys/signal.h>
  10.  
  11. /* this program checks vital parameters on the file system it is invoked
  12. ** against and when a problem is found, runs a specified program that
  13. ** remedies the problem (hopefully).
  14. **
  15. ** This program must be setuid root and/or run from root 
  16. */
  17.  
  18. struct statfs buf;
  19. long inode_trigger = 200L;
  20. long block_trigger = 1000L;
  21. long ratio = 5L;
  22. int i;
  23. char file_sys[256];
  24. char action[256];
  25. char c;
  26. int verbose=0;
  27. int snooze=10;
  28. long i_ratio;
  29. int talk=0;
  30.  
  31. extern int optind;
  32. extern char *optarg;
  33. extern int errno;
  34. extern void usage();
  35. extern void take_action();
  36. extern char *decimalize();
  37. extern void terminator();
  38.  
  39. main(argc,argv)
  40. int argc;
  41. char **argv;
  42. {
  43.  
  44. #ifdef DAEMON
  45.     /* do NOT do this if you run ichk from init.  Init gets real pissed */
  46.     /* with processes that try to daemonize themselves */
  47.     if (fork())
  48.         exit(0);
  49. #endif
  50.  
  51.     setpgrp();    /* make us a little bit independent */
  52.  
  53.  
  54.     signal(SIGTERM,terminator);
  55.     signal(SIGINT,terminator);
  56.     signal(SIGHUP,terminator);
  57.  
  58.     action[0] = '\0';
  59.  
  60.     if (argc < 2) {
  61.         usage();
  62.     }
  63.  
  64.     if ( setuid(0) ) {
  65.         fprintf(stderr,"*** ERROR: Setuid root failed");
  66.         sleep(5);
  67.         exit(2);
  68.     }            
  69.     
  70.     if ( setgid(0) ) {
  71.         fprintf(stderr,"*** ERROR: Setgid root failed");
  72.         sleep(5);
  73.         exit(3);
  74.     }            
  75.  
  76.     while ( (c =  getopt(argc, argv, "a:b:i:r:s:vt")) != -1 ) {
  77.         switch (c) {
  78.             case 'a':    /* specifies the action to take */
  79.                 strcpy(action,optarg);
  80.                 break;
  81.             case 'b':    /* low block count threshold */
  82.                 block_trigger = atol(optarg);
  83.                 if (block_trigger == 0L)
  84.                     usage();
  85.                 break;
  86.             case 'i':
  87.                 inode_trigger=atol(optarg);
  88.                 if (inode_trigger == 0L)
  89.                     usage();
  90.                 break;
  91.             case 'r':
  92.                 ratio=atol(optarg);
  93.                 if (ratio == 0L) 
  94.                     usage();
  95.                 break;
  96.             case 'v':
  97.                 verbose=1;
  98.                 break;
  99.             case 's':
  100.                 snooze = atoi(optarg);
  101.                 if (snooze == 0 ) 
  102.                     usage();
  103.                 break;
  104.             case 't':    /* give a report only or (t)alk */
  105.                 talk=1;
  106.                 break;
  107.             case '?':
  108.                 usage();
  109.                 break;
  110.         }
  111.     }
  112.     if (talk) verbose = 0;
  113.  
  114.     strcpy(file_sys,argv[optind]);
  115.  
  116.     if (verbose)
  117.         printf("pid = %d\n", getpid());
  118.  
  119.     errno=0;
  120.     if ( statfs(file_sys, &buf, sizeof(struct statfs), 0) == -1) {
  121.         fprintf(stderr,"*** ERROR: statfs() failed, errno = %d\n",errno);
  122.         fprintf(stderr,"file_sys = <%s>\n", file_sys);
  123.         fprintf(stderr,"sizeof(struct statfs) = %d \n", sizeof(struct statfs));
  124.         sleep(10); /* keeps init happy */
  125.         exit(4);
  126.     }
  127.  
  128.     if (talk) {
  129.         printf("%s %ld %ld ", buf.f_fname, buf.f_blocks, buf.f_bfree);
  130.         printf("%ld %ld %s\n", buf.f_files, buf.f_ffree, 
  131.             decimalize((buf.f_bfree*10L) / (buf.f_ffree))); 
  132.         exit(0);
  133.  
  134.     }
  135.  
  136.  
  137.     if (verbose) {
  138.         printf("File system type =    %d\n", buf.f_fstyp);
  139.         printf("Total blocks =        %ld\n", buf.f_blocks);
  140.         printf("Free blocks =         %ld\n", buf.f_bfree);
  141.         printf("Total inodes =        %ld\n", buf.f_files);
  142.         printf("Free inodes =         %ld\n", buf.f_ffree);
  143.         printf("Volume name =         %s\n", buf.f_fname);
  144.     }
  145.  
  146.     while (1) {
  147.  
  148.         if (statfs(file_sys, &buf, sizeof(struct statfs), 0) == -1) {
  149.             /* maybe the problem will go away, nothing to do anyway*/
  150.             sleep(10);    
  151.             continue;
  152.         }
  153.  
  154.         i_ratio = (buf.f_bfree*10L) / buf.f_ffree;  
  155.         /* preserving one decimal place of rounding */
  156.  
  157.         /* ratio of blocks to inodes will go UP when the system starts losing
  158.             inodes */
  159.         if ( i_ratio >= (ratio*10L) ) {
  160.             if (verbose)
  161.                 printf("Block to Inode ratio %s is too high\n", decimalize(i_ratio));
  162.             take_action("ratio");
  163.             goto slumber;
  164.         } else {
  165.             if (verbose)
  166.                 printf("Block to Inode ratio is %s\n", decimalize(i_ratio));
  167.         }
  168.  
  169.         if (buf.f_ffree < inode_trigger) {
  170.             if (verbose)
  171.                 printf("Inodes low threshold triggered at %ld inodes\n", 
  172.                     buf.f_ffree);
  173.             take_action("inode");
  174.             goto slumber;
  175.         } else {
  176.             if (verbose)
  177.                 printf("Inodes = %ld\n", 
  178.                     buf.f_ffree);
  179.         }    
  180.  
  181.         if (buf.f_bfree < block_trigger) {
  182.             if (verbose)
  183.                 printf("Blocks low threshold triggered at %ld blocks\n", 
  184.                     buf.f_bfree);
  185.             take_action("block");
  186.             goto slumber;
  187.         } else {
  188.             if (verbose)
  189.                 printf("Blocks = %ld\n", 
  190.                     buf.f_bfree);
  191.         }    
  192.  
  193.     slumber:
  194.         sleep(snooze);
  195.  
  196.     } /* for (;;) */
  197.  
  198.     /* NOTREACHED */
  199.     sleep(5);
  200.     exit(0);
  201. } /* main */
  202.  
  203. void
  204. take_action(x)
  205. char x[]; /* problem to be remedied */
  206. {
  207.     char buff[256];
  208.  
  209.     if (!strlen(action)) 
  210.         return;
  211.  
  212.     sprintf(buff,"%s %s %s", action, file_sys, x);
  213.     if (verbose)
  214.         printf("Action taken:  Command line to system()\n\t%s\n",buff);
  215.  
  216.     system(buff);
  217.     return;
  218. }
  219.  
  220. char *
  221. decimalize(x)
  222. long x;
  223. {
  224.     static char buff[256];
  225.     int len;
  226.  
  227.     memset(buff,'\0',256);
  228.  
  229.     sprintf(buff,"%ld", x);
  230.     len = strlen(buff);
  231.  
  232.     buff[len] = buff[len-1]; /* move last char over one to the right*/
  233.     buff[len-1] = '.';
  234.  
  235.     return(buff);
  236. }
  237.  
  238. void
  239. usage()
  240. {
  241.  
  242.     fprintf(stderr,
  243.     "\nUsage:\n\nichk <-a action>\n  <-i inode_trig>\n  <-r ratio>\n  <-v>\n");
  244.     fprintf(stderr,
  245.     "  <-s sleep_secs>\n  <-b block_count_trigger>\n  <-t>\n file_system_name\n");
  246.     fprintf(stderr,
  247.        "\nThe defaults are %ld inodes, %ld:1 block_to_inodes_ratio,\n", 
  248.        inode_trigger, ratio);    
  249.     fprintf(stderr,
  250.        "%ld blocks, action = nothing and %d seconds between checks.\n", 
  251.        block_trigger, snooze);
  252.     fprintf(stderr,
  253.         "\nWhen the <action> program is invoked, the program is passed the\n");
  254.     fprintf(stderr,
  255.     "following arguments:\nargv[1] == the file system\nargv[2] == the problem\n");
  256.     fprintf(stderr,
  257.     "\nargv[2] can be:\nratio      = ratio of blocks to inodes exceeded.\n");
  258.     fprintf(stderr,
  259.     "inode      = the low inode threshold exceeded.\n");
  260.     fprintf(stderr,
  261.     "block      = the low block threshold exceeded.\n");
  262.     fprintf(stderr,
  263.     "If the -t (talk) flag is specified, all other options are ignored and\n");
  264.     fprintf(stderr,
  265.     "ichk reports the status of the file system in the form:\n fs_name ");
  266.     fprintf(stderr,
  267.     "block_count blocks_free inode_count inodes_free ratio_blocks_2_inodes\n");
  268.     
  269.     sleep(5);
  270.     exit(1);
  271. }
  272. void
  273. terminator(x)
  274. int x;
  275. {
  276.     fprintf(stderr,"Signal caught: ichk going down on signal %d\n", x);
  277.     exit(0);
  278. }
  279.