# 2.11BSD#431 - /usr/src/usr.sbin/accton/accton.c

##### Functions

    main              X
    usage             X

       1: /*
       2:  * Steven Schultz - sms@moe.2bsd.com
       3:  *
       4:  *	@(#)accton.c	1.1 (2.11BSD) 1999/5/5
       5:  *
       6:  * accton - enable/disable process accounting.
       7: */
       8:
       9: #include    <signal.h>
      10: #include    <stdio.h>
      11: #include    <errno.h>
      12: #include    <stdlib.h>
      13: #include    <sys/types.h>
      14: #include    <sys/acct.h>
      15: #include    <sys/stat.h>
      16:
      17: static  int Suspend = 2;    /* %free when accounting suspended */
      18: static  int Resume = 4; /* %free when accounting to be resumed */
      19: static  int Chkfreq = 30;   /* how often (seconds) to check disk space */
      20: static  char    *Acctfile;
      21: extern  char    *__progname;
      22:     void    usage();
      23:
      24: main(argc, argv)
      25:     int argc;
      26:     char    **argv;
      27:     {
      28:     int c;
      29:     pid_t   pid;
      30:     char    *cffile = _PATH_ACCTDCF;
      31:     char    *pidfile = _PATH_ACCTDPID;
      32:     char    *cp;
      33:     long    l;
      34:     register FILE   *fp;
      35:     int status;
      36:     struct  stat    st;
      37:
      38:     if  (getuid())
      39:         errx(1, "Only root can run this program");
      40: /*
      41:  * Handle the simple case of no arguments at all.  This turns off accounting
      42:  * completely by killing the accounting daemon 'acctd'.
      43: */
      44:     if  (argc == 1)
      45:         {
      46:         fp = fopen(pidfile, "r");
      47: /*
      48:  * Note: it is not fatal to fail opening the pid file.  The accounting daemon
      49:  * may not have been run on this system yet.
      50: */
      51:         if  (!fp)
      52:             exit(0);
      53:         if  (fscanf(fp, "%d\n", &pid) != 1)
      54:             errx(1, "%s corrupt/unparseable",
      55:                 pidfile);
      56:         if  (pid < 3 || pid > 30000) /* Paranoia */
      57:             errx(1, "%s content out of bound(30000>pid>3)",
      58:                 pidfile);
      59:         fclose(fp);
      60:         if  (kill(pid, SIGTERM) < 0)
      61:             {
      62: /*
      63:  * It is not an error to turn off accounting if it is already disabled.  Ignore
      64:  * the no such process error from kill.
      65: */
      66:             if  (errno != ESRCH)
      67:                 err(1, "kill(%d,SIGTERM)", pid);
      68:             }
      69:         exit(0);
      70:         }
      71:
      72:     while   ((c = getopt(argc, argv, "f:r:s:t:")) != EOF)
      73:         {
      74:         switch  (c)
      75:             {
      76:             case    'f':
      77:                 Acctfile = optarg;
      78:                 break;
      79:             case    'r':
      80:                 cp = NULL;
      81:                 l = strtol(optarg, &cp, 10);
      82:                 if  (l < 0 || l > 99 || (cp && *cp))
      83:                     errx(1, "bad -r value");
      84:                 Resume = (int)l;
      85:                 break;
      86:             case    's':
      87:                 cp = NULL;
      88:                 l = strtol(optarg, &cp, 10);
      89:                 if  (l < 0 || l > 99 || (cp && *cp))
      90:                     errx(1, "bad -s value");
      91:                 Suspend = (int)l;
      92:                 break;
      93:             case    't':
      94:                 cp = NULL;
      95:                 l = strtol(optarg, &cp, 10);
      96:                 if  (l < 5 || l > 3600 || (cp && *cp))
      97:                     errx(1, "bad -t value (3600>=t>=5");
      98:                 Chkfreq = (int)l;
      99:                 break;
     100:             case    '?':
     101:             default:
     102:                 usage();
     103:                 /* NOTREACHED */
     104:             }
     105:         }
     106:     argc -= optind;
     107:     argv += optind;
     108: /*
     109:  * If we have exactly one argument left then it must be a filename.  This
     110:  * preserves the historical practice of running "accton /usr/adm/acct" to
     111:  * enable accounting.  It is an error to have more than one argument at this
     112:  * point.
     113: */
     114:     if  (argc == 1)
     115:         {
     116:         if  (Acctfile)
     117:             warnx("'-f %s' being overridden by trailing '%s'",
     118:                 Acctfile, *argv);
     119:         Acctfile = *argv;
     120:         }
     121:     else if (argc != 0)
     122:         {
     123:         usage();
     124:         /* NOTREACHED */
     125:         }
     126: /*
     127:  * If after all of that we still don't have a file name then use the
     128:  * default one.
     129: */
     130:     if  (!Acctfile)
     131:         Acctfile = _PATH_ACCTFILE;
     132:
     133: /*
     134:  * Now open the conf file (creating it if it does not exist) and write out
     135:  * the parameters for the accounting daemon.  The conf file format is simple:
     136:  * "tag=value\n".  NO EXTRA WHITE SPACE or COMMENTS!
     137:  *
     138:  * IF the file already exists it must be owned by root and not writeable by
     139:  * group or other.  This is because the conf file contains a pathname that
     140:  * will be trusted by a daemon running as root.  The same check is made by
     141:  * 'acctd' to prevent believing bogus information.
     142: */
     143:     if  (stat(cffile, &st) == 0)
     144:         {
     145:         if  (st.st_uid != 0)
     146:             errx(1, "%s not owned by root", cffile);
     147:         if  (st.st_mode & (S_IWGRP|S_IWOTH))
     148:             errx(1, "%s writeable by group/other", cffile);
     149:         }
     150:     fp = fopen(cffile, "w");
     151:     if  (!fp)
     152:         errx(1, "fopen(%s,w)", cffile);
     153:     fprintf(fp, "suspend=%d\n", Suspend);
     154:     fprintf(fp, "resume=%d\n", Resume);
     155:     fprintf(fp, "chkfreq=%d\n", Chkfreq);
     156:     fprintf(fp, "acctfile=%s\n", Acctfile);
     157:     fclose(fp);
     158:
     159: /*
     160:  * After writing the conf file we need to send the current running 'acctd'
     161:  * process (if any) a SIGHUP.  If the pidfile can not be opened this may be
     162:  * the first time 'acctd' has ever been run.
     163: */
     164:     fp = fopen(pidfile, "r");
     165:     if  (fp)
     166:         {
     167:         if  (fscanf(fp, "%d\n", &pid) != 1)
     168:             errx(1, "%s corrupt/unparseable", pidfile);
     169:         if  (pid < 3 || pid > 30000) /* Paranoia */
     170:             errx(1, "%s content out of bound(30000>pid>3)",
     171:                 pidfile);
     172:         fclose(fp);
     173: /*
     174:  * If the signal can be successfully posted to the process then do not
     175:  * attempt to start another instance of acctd (it will fail but syslog
     176:  * an annoying error message).  If the signal can not be posted but the
     177:  * acctd process does not exist then go start it.  Otherwise complain.
     178: */
     179:         if  (kill(pid, SIGHUP) < 0)
     180:             {
     181:             if  (errno != ESRCH)
     182:                 err(1, "%d from %s bogus value", pid, pidfile);
     183:             /* process no longer exists, fall thru and start it */
     184:             }
     185:         else
     186:             exit(0);
     187:         }
     188:     pid = vfork();
     189:     switch  (pid)
     190:         {
     191:         case    -1:
     192:             err(1, "vfork");
     193:             /* NOTREACHED */
     194:         case    0:      /* Child process */
     195:             if  (execl(_PATH_ACCTD, "acctd", NULL) < 0)
     196:                 err(1, "execl %s", _PATH_ACCTD);
     197:             /* NOTREACHED */
     198:         default:        /* Parent */
     199:             break;
     200:         }
     201:     if  (waitpid(pid, &status, 0) < 0)
     202:         err(1, "waitpid for %d", pid);
     203:     exit(0);
     204:     }
     205:
     206: void
     207: usage()
     208:     {
     209:
     210:     errx(1,"Usage: %s [-f acctfile] [-s %suspend] [-r %resume] [-t chkfreq] [acctfile]", __progname);
     211:     /* NOTREACHED */
     212:     }

#### Defined functions

main defined in line 24; never used
usage defined in line 206; used 3 times

- in line 22, 102, 123

#### Defined variables

Acctfile defined in line 20; used 7 times

- in line 77, 116-119(3), 130-131(2), 156

Chkfreq defined in line 19; used 2 times

- in line 98, 155

Resume defined in line 18; used 2 times

- in line 84, 154

Suspend defined in line 17; used 2 times

- in line 91, 153

Last modified: 1999-05-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1494 |