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

Defined variables

Acctfile defined in line 20; used 7 times
Chkfreq defined in line 19; used 2 times
Resume defined in line 18; used 2 times
Suspend defined in line 17; used 2 times
Last modified: 1999-05-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3826
Valid CSS Valid XHTML 1.0 Strict