2021-10-11 18:37:13 -03:00

327 lines
5.7 KiB
C

/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)acctdusg.c 1.1 94/10/31 SMI" /* from S5R3 acct:acctdusg.c 1.4 */
/*
* disk [-u file] [-p file] > dtmp-file
* -u file for names of files not charged to anyone
* -p get password info from file
* reads input (normally from find / -print)
* and compute disk resource consumption by login
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#define NAMESZ 8
struct disk{
char dsk_name[NAMESZ]; /* login name */
unsigned dsk_uid; /* user id of login name */
int dsk_dirsz; /* # letters in pathname of login directory */
char *dsk_logdir; /* ptr to path name of login directory */
int dsk_ns; /* no of slashes in path name */
long dsk_du; /* disk usage */
struct disk *dsk_np; /* ptr to next struct */
};
char *pfile = NULL;
char *afile, *nfile;
struct disk *Dp; /* ptr to 1st entry in dirlist */
struct stat statb;
FILE *pswd, *nchrg;
FILE *names ={stdin};
FILE *acct ={stdout};
char fbuf[BUFSIZ];
char *calloc();
struct passwd *getpwent(), *fgetpwent();
main(argc, argv)
char **argv;
{
register struct passwd *pw;
while(--argc > 0){
++argv;
if(**argv == '-') switch((*argv)[1]) {
case 'u':
if (--argc <= 0)
break;
if ((nchrg = fopen(*(++argv),"w")) == NULL)
openerr(*argv);
chmod(*argv, 0644);
continue;
case 'p':
if (--argc <= 0)
break;
pfile = *(++argv);
continue;
}
fprintf(stderr,"Invalid argument: %s\n", *argv);
exit(1);
}
if (pfile != NULL) {
if ((pswd = fopen(pfile, "r")) == NULL)
openerr(pfile);
}
while ((pw = (pfile == NULL ? getpwent() : fgetpwent(pswd))) != NULL) {
makdlst(pw); /* make a list of home directory names
for every entry in password file */
}
if (pfile != NULL)
fclose(pswd);
dsort();
while( fgets(fbuf, sizeof fbuf, names) != NULL) {
fbuf[strndx(fbuf, '\n') ] = '\0';
clean(fbuf);
charge(fbuf);
}
if (names != stdin)
fclose(names);
output();
if (acct != stdout)
fclose(acct);
if (nchrg)
fclose(nchrg);
#ifdef DEBUG
pdisk();
#endif
exit(0);
}
openerr(file)
char *file;
{
fprintf(stderr, "Cannot open %s\n", file);
exit(1);
}
output()
{
register struct disk *dp;
for(dp = Dp; dp != NULL; dp=dp->dsk_np) {
if(dp->dsk_du)
fprintf(acct,
"%05u\t%-8.8s\t%7lu\n",
dp->dsk_uid,
dp->dsk_name,
dp->dsk_du);
}
}
strndx(str, chr)
register char *str;
register char chr;
{
register index;
for (index=0; *str; str++,index++)
if (*str == chr)
return index;
return -1;
}
/*
* make a list of home directory names
* for every entry in password file
*/
makdlst(pw)
register struct passwd *pw;
{
static struct disk *dl = {NULL};
struct disk *dp;
int i;
if( (dp = (struct disk *)calloc(sizeof(struct disk), 1)) == NULL) {
nocore:
fprintf(stderr, "out of core\n");
exit(2);
}
strncpy(dp->dsk_name, pw->pw_name, NAMESZ);
dp->dsk_uid = pw->pw_uid;
dp->dsk_dirsz = strlen(pw->pw_dir); /* length of path name */
if((dp->dsk_logdir = calloc(dp->dsk_dirsz + 1, 1)) == NULL)
goto nocore;
strcpy(dp->dsk_logdir, pw->pw_dir, dp->dsk_dirsz);
if(stat(dp->dsk_logdir,&statb)== -1 ||
(statb.st_mode & S_IFMT) != S_IFDIR) {
cfree(dp->dsk_logdir);
cfree(dp);
return;
}
for(i=0; dp->dsk_logdir[i]; i++)
if(dp->dsk_logdir[i] == '/')
dp->dsk_ns++; /* count # of slashes */
if(dl == NULL) { /* link ptrs */
Dp = dl = dp;
} else {
dl->dsk_np = dp;
dl = dp;
}
return;
}
/*
* sort by decreasing # of levels in login
* pathname and then by increasing uid
*/
dsort()
{
register struct disk *dp1, *dp2, *pdp;
int change;
if(Dp == NULL || Dp->dsk_np == NULL)
return;
change = 0;
pdp = NULL;
for(dp1 = Dp; ;) {
if((dp2 = dp1->dsk_np) == NULL) {
if(!change)
break;
dp1 = Dp;
pdp = NULL;
change = 0;
continue;
}
if((dp1->dsk_ns < dp2->dsk_ns) ||
(dp1->dsk_ns==dp2->dsk_ns && dp1->dsk_uid > dp2->dsk_uid)) {
swapd(pdp, dp1, dp2);
change = 1;
dp1 = dp2;
continue;
}
pdp = dp1;
dp1 = dp2;
}
}
swapd(p,d1,d2)
register struct disk *p, *d1, *d2;
{
struct disk *t;
if (p != NULL) {
p->dsk_np = d2;
t = d2->dsk_np;
d2->dsk_np = d1;
d1->dsk_np = t;
} else {
t = d2->dsk_np;
d2->dsk_np = d1;
d1->dsk_np = t;
Dp = d2;
}
}
charge(n)
register char *n;
{
register struct disk *dp;
register i;
long blks;
if(stat(n,&statb) == -1)
return;
i = strlen(n);
for(dp = Dp; dp != NULL; dp = dp->dsk_np) {
if(i < dp->dsk_dirsz)
continue;
if(strncmp(dp->dsk_logdir, n, dp->dsk_dirsz) == 0 &&
(n[dp->dsk_dirsz] == '/' || n[dp->dsk_dirsz] == '\0'))
break;
}
blks = statb.st_blocks;
if(dp == NULL) {
if(nchrg && (statb.st_size) &&
(statb.st_mode&S_IFMT) == S_IFDIR)
fprintf(nchrg, "%5u\t%7lu\t%s\n",
statb.st_uid, blks, n);
return;
}
dp->dsk_du += (statb.st_mode&S_IFMT) == S_IFDIR ? blks
:((statb.st_mode&S_IFMT)==S_IFREG ?
(blks / statb.st_nlink) : 0L);
}
#ifdef DEBUG
pdisk()
{
register struct disk *dp;
for(dp=Dp; dp!=NULL; dp=dp->dsk_np)
printf("%.8s\t%5u\t%7lu\t%5u\t%5u\t%s\n",
dp->dsk_name,
dp->dsk_uid,
dp->dsk_du,
dp->dsk_dirsz,
dp->dsk_ns,
dp->dsk_logdir);
}
#endif
clean(p)
register char *p;
{
register char *s1, *s2;
for(s1=p; *s1; ) {
s2 = s1;
while(*s1 == '/')
s1++;
s1 = s1<= s2 ? s2 : s1-1;
if(s1 != s2) {
strcpy(s2,s1);
s1 = s2;
}
if(*++s2 == '.')
switch(*++s2) {
case '/':
strcpy(s1,s2);
continue;
case '.':
if(*++s2 != '/')
break;
if(s1 > p)
while(*--s1 != '/' && s1 > p)
;
strcpy(s1,s2);
continue;
}
while(*s2 && *++s2 != '/')
;
s1 = s2;
}
return;
}