ent->permissions, ent->uid, ent->gid, pid);
ent->permissions, ent->uid, ent->gid); ent->flags |= CE_ROTATED;
char *missing_field __P((char *, char *));void dotrim __P((char *, int, int, int, uid_t, gid_t, pid_t));int log_trim __P((char *));void compress_log __P((char *));int sizefile __P((char *));int age_old_log __P((char *));char *sob __P((char *));char *son __P((char *));int isnumberstr __P((char *));void domonitor __P((char *, char *));FILE *openmail __P((void));void closemail __P((FILE *));void child_killer __P((int));intmain(argc, argv)        int argc;        char **argv;{        struct conf_entry *p, *q;	int status;                PRS(argc, argv);        if (needroot && getuid() && geteuid())		errx(1, "You must be root.");        p = q = parse_file();	signal(SIGCHLD, child_killer);        while (p) {                do_entry(p);                p = p->next;                free(q);                q = p;        }	/* Wait for children to finish, then exit */	while (waitpid(-1, &status, 0) != -1)		;        exit(0);}voiddo_entry(ent)        struct conf_entry       *ent;        {	int	modtime, size;	pid_t	pid;        char    line[BUFSIZ];        FILE    *f;        /* First find the pid to HUP */        pid = (pid_t)-1;        if ((f = fopen(ent->pidfile, "r")) != NULL) {        	if (fgets(line, sizeof(line), f))                	pid = atoi(line);		(void)fclose(f);	} else		warn("can't open %s", ent->pidfile);        	if (verbose)		printf("%s <%d%s>: ", ent->log, ent->numlogs,			(ent->flags & CE_COMPACT) ? "Z" : "");        size = sizefile(ent->log);        modtime = age_old_log(ent->log);        if (size < 0) {                if (verbose)                        printf("does not exist.\n");        } else {                if (verbose && (ent->size > 0))                        printf("size (Kb): %d [%d] ", size, ent->size);                if (verbose && (ent->hours > 0))                        printf(" age (hr): %d [%d] ", modtime, ent->hours);		if (monitor && ent->flags & CE_MONITOR)			domonitor(ent->log, ent->whom);                if (!monitor && (((ent->size > 0) && (size >= ent->size)) ||                    ((ent->hours > 0) && ((modtime >= ent->hours)                                        || (modtime < 0))))) {                        if (verbose)                                printf("--> trimming log....\n");			if (noaction && !verbose)				printf("%s <%d%s>: ", ent->log, ent->numlogs,					(ent->flags & CE_COMPACT) ? "Z" : "");                        dotrim(ent->log, ent->numlogs, ent->flags,                               ent->permissions, ent->uid, ent->gid, pid);                } else if (verbose)			printf("--> skipping\n");        }}voidPRS(argc, argv)        int argc;        char **argv;{        int     c;	char	*p;        timenow = time(NULL);        daytime = ctime(&timenow) + 4;        daytime[15] = '\0';        /* Let's get our hostname */        (void)gethostname(hostname, sizeof(hostname));	/* Truncate domain */	p = strchr(hostname, '.');	if (p)		*p = '\0';        optind = 1;             /* Start options parsing */        while ((c = getopt(argc, argv, "nrvmf:t:")) != -1) {                switch (c) {                case 'n':                        noaction++; /* This implies needroot as off */                        /* fall through */                case 'r':                        needroot = 0;                        break;                case 'v':                        verbose++;                        break;                case 'f':                        conf = optarg;                        break;		case 'm':			monitor++;			break;                default:                        usage();                }        }}voidusage(){	extern const char *__progname;	(void)fprintf(stderr, "usage: %s [-nrvm] [-f config-file]\n",	    __progname);	exit(1);}/* Parse a configuration file and return a linked list of all the logs * to process */struct conf_entry *parse_file(){        FILE    *f;        char    line[BUFSIZ], *parse, *q;        char    *errline, *group, *tmp;        struct conf_entry *first = NULL;        struct conf_entry *working;        struct passwd *pass;        struct group *grp;        if (strcmp(conf, "-") == 0)                f = stdin;	else {                if ((f = fopen(conf, "r")) == NULL)			err(1, "can't open %s", conf);	}        while (fgets(line, sizeof(line), f)) {                if ((line[0] == '\n') || (line[0] == '#'))                        continue;                errline = strdup(line);		if (errline == NULL)			err(1, "strdup");                if (!first) {                        working = (struct conf_entry *) malloc(sizeof(struct conf_entry));			if (working == NULL)				err(1, "malloc");                        first = working;                } else {                        working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry));			if (working->next == NULL)				err(1, "malloc");                        working = working->next;                }                q = parse = missing_field(sob(line), errline);                *(parse = son(line)) = '\0';                working->log = strdup(q);		if (working->log == NULL)			err(1, "strdup");                q = parse = missing_field(sob(++parse), errline);                *(parse = son(parse)) = '\0';		if ((group = strchr(q, '.')) != NULL) {			*group++ = '\0';			if (*q) {				if (!(isnumberstr(q))) {					if ((pass = getpwnam(q)) == NULL)						errx(1, "Error in config file; unknown user: %s", q);					working->uid = pass->pw_uid;				} else					working->uid = atoi(q);			} else				working->uid = NONE;						q = group;			if (*q) {				if (!(isnumberstr(q))) {					if ((grp = getgrnam(q)) == NULL)						errx(1, "Error in config file; unknown group: %s", q);					working->gid = grp->gr_gid;				} else					working->gid = atoi(q);			} else				working->gid = NONE;						q = parse = missing_field(sob(++parse), errline);			*(parse = son(parse)) = '\0';		} else 			working->uid = working->gid = NONE;                if (!sscanf(q, "%o", &working->permissions))			errx(1, "Error in config file; bad permissions: %s", q);                q = parse = missing_field(sob(++parse), errline);                *(parse = son(parse)) = '\0';                if (!sscanf(q, "%d", &working->numlogs) || working->numlogs < 0)			errx(1, "Error in config file; bad number: %s", q);                q = parse = missing_field(sob(++parse), errline);                *(parse = son(parse)) = '\0';                if (isdigit(*q))                        working->size = atoi(q);                else                        working->size = -1;                                q = parse = missing_field(sob(++parse), errline);                *(parse = son(parse)) = '\0';                if (isdigit(*q))                        working->hours = atoi(q);                else                        working->hours = -1;                q = parse = sob(++parse); /* Optional field */                *(parse = son(parse)) = '\0';                working->flags = 0;                while (q && *q && !isspace(*q)) {                        if ((*q == 'Z') || (*q == 'z'))                                working->flags |= CE_COMPACT;                        else if ((*q == 'B') || (*q == 'b'))                                working->flags |= CE_BINARY;			else if ((*q == 'M') || (*q == 'm'))				working->flags |= CE_MONITOR;                        else				errx(1, "Illegal flag in config file: %c", *q);                        q++;                }		working->whom = NULL;		if (working->flags & CE_MONITOR) {	/* Optional field */			q = parse = sob(++parse);			*(parse = son(parse)) = '\0';			working->whom = strdup(q);			if (working->log == NULL)				err(1, "strdup");		}		working->pidfile = PIDFILE;                q = parse = sob(++parse); /* Optional field */                *(parse = son(parse)) = '\0';		if (q && *q != '\0') {			if (strlen(q) >= MAXPATHLEN)				errx(1, "%s: pathname too long", q);			working->pidfile = strdup(q);			if (working->pidfile == NULL)				err(1, "strdup");		}		/* Make sure we can't oflow MAXPATHLEN */		if (asprintf(&tmp, "%s.%d%s", working->log, working->numlogs,		    COMPRESS_POSTFIX) >= MAXPATHLEN)			errx(1, "%s: pathname too long", working->log);                                free(tmp);                free(errline);        }        if (working)                working->next = NULL;        (void)fclose(f);        return(first);}char *missing_field(p, errline)        char    *p;	char    *errline;{        if (!p || !*p) {		warnx("Missing field in config file line:");                fputs(errline, stderr);                exit(1);        }        return(p);}