home *** CD-ROM | disk | FTP | other *** search
-
- #ifdef SCCSID
- static sccsid[] = "@(#) ichk.c 1.5 91/02/01 04:01:47";
- #endif
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/statfs.h>
- #include <sys/signal.h>
-
- /* this program checks vital parameters on the file system it is invoked
- ** against and when a problem is found, runs a specified program that
- ** remedies the problem (hopefully).
- **
- ** This program must be setuid root and/or run from root
- */
-
- struct statfs buf;
- long inode_trigger = 200L;
- long block_trigger = 1000L;
- long ratio = 5L;
- int i;
- char file_sys[256];
- char action[256];
- char c;
- int verbose=0;
- int snooze=10;
- long i_ratio;
- int talk=0;
-
- extern int optind;
- extern char *optarg;
- extern int errno;
- extern void usage();
- extern void take_action();
- extern char *decimalize();
- extern void terminator();
-
- main(argc,argv)
- int argc;
- char **argv;
- {
-
- #ifdef DAEMON
- /* do NOT do this if you run ichk from init. Init gets real pissed */
- /* with processes that try to daemonize themselves */
- if (fork())
- exit(0);
- #endif
-
- setpgrp(); /* make us a little bit independent */
-
-
- signal(SIGTERM,terminator);
- signal(SIGINT,terminator);
- signal(SIGHUP,terminator);
-
- action[0] = '\0';
-
- if (argc < 2) {
- usage();
- }
-
- if ( setuid(0) ) {
- fprintf(stderr,"*** ERROR: Setuid root failed");
- sleep(5);
- exit(2);
- }
-
- if ( setgid(0) ) {
- fprintf(stderr,"*** ERROR: Setgid root failed");
- sleep(5);
- exit(3);
- }
-
- while ( (c = getopt(argc, argv, "a:b:i:r:s:vt")) != -1 ) {
- switch (c) {
- case 'a': /* specifies the action to take */
- strcpy(action,optarg);
- break;
- case 'b': /* low block count threshold */
- block_trigger = atol(optarg);
- if (block_trigger == 0L)
- usage();
- break;
- case 'i':
- inode_trigger=atol(optarg);
- if (inode_trigger == 0L)
- usage();
- break;
- case 'r':
- ratio=atol(optarg);
- if (ratio == 0L)
- usage();
- break;
- case 'v':
- verbose=1;
- break;
- case 's':
- snooze = atoi(optarg);
- if (snooze == 0 )
- usage();
- break;
- case 't': /* give a report only or (t)alk */
- talk=1;
- break;
- case '?':
- usage();
- break;
- }
- }
- if (talk) verbose = 0;
-
- strcpy(file_sys,argv[optind]);
-
- if (verbose)
- printf("pid = %d\n", getpid());
-
- errno=0;
- if ( statfs(file_sys, &buf, sizeof(struct statfs), 0) == -1) {
- fprintf(stderr,"*** ERROR: statfs() failed, errno = %d\n",errno);
- fprintf(stderr,"file_sys = <%s>\n", file_sys);
- fprintf(stderr,"sizeof(struct statfs) = %d \n", sizeof(struct statfs));
- sleep(10); /* keeps init happy */
- exit(4);
- }
-
- if (talk) {
- printf("%s %ld %ld ", buf.f_fname, buf.f_blocks, buf.f_bfree);
- printf("%ld %ld %s\n", buf.f_files, buf.f_ffree,
- decimalize((buf.f_bfree*10L) / (buf.f_ffree)));
- exit(0);
-
- }
-
-
- if (verbose) {
- printf("File system type = %d\n", buf.f_fstyp);
- printf("Total blocks = %ld\n", buf.f_blocks);
- printf("Free blocks = %ld\n", buf.f_bfree);
- printf("Total inodes = %ld\n", buf.f_files);
- printf("Free inodes = %ld\n", buf.f_ffree);
- printf("Volume name = %s\n", buf.f_fname);
- }
-
- while (1) {
-
- if (statfs(file_sys, &buf, sizeof(struct statfs), 0) == -1) {
- /* maybe the problem will go away, nothing to do anyway*/
- sleep(10);
- continue;
- }
-
- i_ratio = (buf.f_bfree*10L) / buf.f_ffree;
- /* preserving one decimal place of rounding */
-
- /* ratio of blocks to inodes will go UP when the system starts losing
- inodes */
- if ( i_ratio >= (ratio*10L) ) {
- if (verbose)
- printf("Block to Inode ratio %s is too high\n", decimalize(i_ratio));
- take_action("ratio");
- goto slumber;
- } else {
- if (verbose)
- printf("Block to Inode ratio is %s\n", decimalize(i_ratio));
- }
-
- if (buf.f_ffree < inode_trigger) {
- if (verbose)
- printf("Inodes low threshold triggered at %ld inodes\n",
- buf.f_ffree);
- take_action("inode");
- goto slumber;
- } else {
- if (verbose)
- printf("Inodes = %ld\n",
- buf.f_ffree);
- }
-
- if (buf.f_bfree < block_trigger) {
- if (verbose)
- printf("Blocks low threshold triggered at %ld blocks\n",
- buf.f_bfree);
- take_action("block");
- goto slumber;
- } else {
- if (verbose)
- printf("Blocks = %ld\n",
- buf.f_bfree);
- }
-
- slumber:
- sleep(snooze);
-
- } /* for (;;) */
-
- /* NOTREACHED */
- sleep(5);
- exit(0);
- } /* main */
-
- void
- take_action(x)
- char x[]; /* problem to be remedied */
- {
- char buff[256];
-
- if (!strlen(action))
- return;
-
- sprintf(buff,"%s %s %s", action, file_sys, x);
- if (verbose)
- printf("Action taken: Command line to system()\n\t%s\n",buff);
-
- system(buff);
- return;
- }
-
- char *
- decimalize(x)
- long x;
- {
- static char buff[256];
- int len;
-
- memset(buff,'\0',256);
-
- sprintf(buff,"%ld", x);
- len = strlen(buff);
-
- buff[len] = buff[len-1]; /* move last char over one to the right*/
- buff[len-1] = '.';
-
- return(buff);
- }
-
- void
- usage()
- {
-
- fprintf(stderr,
- "\nUsage:\n\nichk <-a action>\n <-i inode_trig>\n <-r ratio>\n <-v>\n");
- fprintf(stderr,
- " <-s sleep_secs>\n <-b block_count_trigger>\n <-t>\n file_system_name\n");
- fprintf(stderr,
- "\nThe defaults are %ld inodes, %ld:1 block_to_inodes_ratio,\n",
- inode_trigger, ratio);
- fprintf(stderr,
- "%ld blocks, action = nothing and %d seconds between checks.\n",
- block_trigger, snooze);
- fprintf(stderr,
- "\nWhen the <action> program is invoked, the program is passed the\n");
- fprintf(stderr,
- "following arguments:\nargv[1] == the file system\nargv[2] == the problem\n");
- fprintf(stderr,
- "\nargv[2] can be:\nratio = ratio of blocks to inodes exceeded.\n");
- fprintf(stderr,
- "inode = the low inode threshold exceeded.\n");
- fprintf(stderr,
- "block = the low block threshold exceeded.\n");
- fprintf(stderr,
- "If the -t (talk) flag is specified, all other options are ignored and\n");
- fprintf(stderr,
- "ichk reports the status of the file system in the form:\n fs_name ");
- fprintf(stderr,
- "block_count blocks_free inode_count inodes_free ratio_blocks_2_inodes\n");
-
- sleep(5);
- exit(1);
- }
- void
- terminator(x)
- int x;
- {
- fprintf(stderr,"Signal caught: ichk going down on signal %d\n", x);
- exit(0);
- }
-