1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*0Sstevel@tonic-gate /* All Rights Reserved */ 24*0Sstevel@tonic-gate /* Copyright (c) 1999 by Sun Microsystems, Inc. */ 25*0Sstevel@tonic-gate /* All rights reserved. */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.18 */ 29*0Sstevel@tonic-gate #include <stdio.h> 30*0Sstevel@tonic-gate #include <sys/types.h> 31*0Sstevel@tonic-gate #include <sys/param.h> 32*0Sstevel@tonic-gate #include <sys/fs/s5ino.h> 33*0Sstevel@tonic-gate #include <sys/stat.h> 34*0Sstevel@tonic-gate #include <sys/fs/s5param.h> 35*0Sstevel@tonic-gate #include <sys/fs/s5filsys.h> 36*0Sstevel@tonic-gate #include <sys/fs/s5macros.h> 37*0Sstevel@tonic-gate #include <sys/sysmacros.h> 38*0Sstevel@tonic-gate #include <pwd.h> 39*0Sstevel@tonic-gate #include <fcntl.h> 40*0Sstevel@tonic-gate #include "acctdef.h" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #ifndef Fs2BLK 43*0Sstevel@tonic-gate #define Fs2BLK 0 44*0Sstevel@tonic-gate #endif 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #define BLOCK 512 /* Block size for reporting */ 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #define NINODE 2048 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate struct filsys sblock; 52*0Sstevel@tonic-gate struct dinode dinode[NINODE]; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate int VERBOSE = 0; 55*0Sstevel@tonic-gate FILE *ufd = 0; 56*0Sstevel@tonic-gate int index; 57*0Sstevel@tonic-gate unsigned ino, nfiles; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate struct acct { 60*0Sstevel@tonic-gate uid_t uid; 61*0Sstevel@tonic-gate long usage; 62*0Sstevel@tonic-gate char name [NSZ+1]; 63*0Sstevel@tonic-gate } userlist[MAXUSERS]; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate char *ignlist[MAXIGN]; 66*0Sstevel@tonic-gate int igncnt = {0}; 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate char *cmd; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate unsigned hash(); 71*0Sstevel@tonic-gate main(argc, argv) 72*0Sstevel@tonic-gate int argc; 73*0Sstevel@tonic-gate char **argv; 74*0Sstevel@tonic-gate { 75*0Sstevel@tonic-gate extern int optind; 76*0Sstevel@tonic-gate extern char *optarg; 77*0Sstevel@tonic-gate register c; 78*0Sstevel@tonic-gate register FILE *fd; 79*0Sstevel@tonic-gate register rfd; 80*0Sstevel@tonic-gate struct stat sb; 81*0Sstevel@tonic-gate int sflg = {FALSE}; 82*0Sstevel@tonic-gate char *pfile = NULL; 83*0Sstevel@tonic-gate int errfl = {FALSE}; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate cmd = argv[0]; 86*0Sstevel@tonic-gate while((c = getopt(argc, argv, "vu:p:si:")) != EOF) switch(c) { 87*0Sstevel@tonic-gate case 's': 88*0Sstevel@tonic-gate sflg = TRUE; 89*0Sstevel@tonic-gate break; 90*0Sstevel@tonic-gate case 'v': 91*0Sstevel@tonic-gate VERBOSE = 1; 92*0Sstevel@tonic-gate break; 93*0Sstevel@tonic-gate case 'i': 94*0Sstevel@tonic-gate ignore(optarg); 95*0Sstevel@tonic-gate break; 96*0Sstevel@tonic-gate case 'u': 97*0Sstevel@tonic-gate ufd = fopen(optarg, "a"); 98*0Sstevel@tonic-gate break; 99*0Sstevel@tonic-gate case 'p': 100*0Sstevel@tonic-gate pfile = optarg; 101*0Sstevel@tonic-gate break; 102*0Sstevel@tonic-gate case '?': 103*0Sstevel@tonic-gate errfl++; 104*0Sstevel@tonic-gate break; 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate if(errfl) { 107*0Sstevel@tonic-gate fprintf(stderr, "Usage: %s [-sv] [-p pw_file] [-u file] [-i ignlist] [file ...]\n", cmd); 108*0Sstevel@tonic-gate exit(10); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate hashinit(); 112*0Sstevel@tonic-gate if(sflg == TRUE) { 113*0Sstevel@tonic-gate if(optind == argc){ 114*0Sstevel@tonic-gate adduser(stdin); 115*0Sstevel@tonic-gate } else { 116*0Sstevel@tonic-gate for( ; optind < argc; optind++) { 117*0Sstevel@tonic-gate if( (fd = fopen(argv[optind], "r")) == NULL) { 118*0Sstevel@tonic-gate fprintf(stderr, "%s: Cannot open %s\n", cmd, argv[optind]); 119*0Sstevel@tonic-gate continue; 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate adduser(fd); 122*0Sstevel@tonic-gate fclose(fd); 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate else { 127*0Sstevel@tonic-gate setup(pfile); 128*0Sstevel@tonic-gate for( ; optind < argc; optind++) { 129*0Sstevel@tonic-gate if( (rfd = open(argv[optind], O_RDONLY)) < 0) { 130*0Sstevel@tonic-gate fprintf(stderr, "%s: Cannot open %s\n", cmd, argv[optind]); 131*0Sstevel@tonic-gate continue; 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate if(fstat(rfd, &sb) >= 0){ 134*0Sstevel@tonic-gate if ( (sb.st_mode & S_IFMT) == S_IFCHR || 135*0Sstevel@tonic-gate (sb.st_mode & S_IFMT) == S_IFBLK ) { 136*0Sstevel@tonic-gate ilist(argv[optind], rfd); 137*0Sstevel@tonic-gate } else { 138*0Sstevel@tonic-gate fprintf(stderr, "%s: %s is not a special file -- ignored\n", cmd, argv[optind]); 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate } else { 141*0Sstevel@tonic-gate fprintf(stderr, "%s: Cannot stat %s\n", cmd, argv[optind]); 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate close(rfd); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate output(); 147*0Sstevel@tonic-gate exit(0); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate adduser(fd) 151*0Sstevel@tonic-gate register FILE *fd; 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate uid_t usrid; 154*0Sstevel@tonic-gate long blcks; 155*0Sstevel@tonic-gate char login[NSZ+10]; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate while(fscanf(fd, "%ld %s %ld\n", &usrid, login, &blcks) == 3) { 158*0Sstevel@tonic-gate if( (index = hash(usrid)) == FAIL) return(FAIL); 159*0Sstevel@tonic-gate if(userlist[index].uid == UNUSED) { 160*0Sstevel@tonic-gate userlist[index].uid = usrid; 161*0Sstevel@tonic-gate (void) strncpy(userlist[index].name, login, NSZ); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate userlist[index].usage += blcks; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate ilist(file, fd) 168*0Sstevel@tonic-gate char *file; 169*0Sstevel@tonic-gate register fd; 170*0Sstevel@tonic-gate { 171*0Sstevel@tonic-gate register dev_t dev; 172*0Sstevel@tonic-gate register i, j; 173*0Sstevel@tonic-gate int inopb, inoshift, fsinos, bsize; 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate if (fd < 0 ) { 176*0Sstevel@tonic-gate return (FAIL); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate sync(); 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate /* Fake out block size to be 512 */ 182*0Sstevel@tonic-gate dev = 512; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* Read in super-block of filesystem */ 185*0Sstevel@tonic-gate bread(fd, 1, &sblock, sizeof(sblock), dev); 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* Check for filesystem names to ignore */ 188*0Sstevel@tonic-gate if(!todo(sblock.s_fname)) 189*0Sstevel@tonic-gate return; 190*0Sstevel@tonic-gate /* Check for size of filesystem to be 512 or 1K */ 191*0Sstevel@tonic-gate if (sblock.s_magic == FsMAGIC ) 192*0Sstevel@tonic-gate switch (sblock.s_type) { 193*0Sstevel@tonic-gate case Fs1b: 194*0Sstevel@tonic-gate bsize = 512; 195*0Sstevel@tonic-gate inoshift = 3; 196*0Sstevel@tonic-gate fsinos = (((2)&~07)+1); 197*0Sstevel@tonic-gate break; 198*0Sstevel@tonic-gate case Fs2b: 199*0Sstevel@tonic-gate bsize = 1024; 200*0Sstevel@tonic-gate inoshift = 4; 201*0Sstevel@tonic-gate fsinos = (((2)&~017)+1); 202*0Sstevel@tonic-gate break; 203*0Sstevel@tonic-gate case Fs4b: 204*0Sstevel@tonic-gate bsize = 2048; 205*0Sstevel@tonic-gate inoshift = 5; 206*0Sstevel@tonic-gate fsinos = (((2)&~037)+1); 207*0Sstevel@tonic-gate break; 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate inopb = bsize/sizeof(struct dinode); 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate nfiles = (sblock.s_isize-2) * inopb; 214*0Sstevel@tonic-gate dev = (dev_t)bsize; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate /* Determine physical block 2 */ 217*0Sstevel@tonic-gate i = (daddr_t)(((unsigned)(fsinos)+(2*inopb-1)) >> inoshift); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* Start at physical block 2, inode list */ 220*0Sstevel@tonic-gate for (ino = 0; ino < nfiles; i += NINODE/inopb) { 221*0Sstevel@tonic-gate bread(fd, i, dinode, sizeof(dinode), dev); 222*0Sstevel@tonic-gate for (j = 0; j < NINODE && ino++ < nfiles; j++) 223*0Sstevel@tonic-gate if (dinode[j].di_mode & S_IFMT) 224*0Sstevel@tonic-gate if(count(j, dev) == FAIL) { 225*0Sstevel@tonic-gate if(VERBOSE) 226*0Sstevel@tonic-gate fprintf(stderr,"BAD UID: file system = %s, inode = %u, uid = %ld\n", 227*0Sstevel@tonic-gate file, ino, dinode[j].di_uid); 228*0Sstevel@tonic-gate if(ufd) 229*0Sstevel@tonic-gate fprintf(ufd, "%s %u %ld\n", file, ino, dinode[j].di_uid); 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate return (0); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate ignore(str) 236*0Sstevel@tonic-gate register char *str; 237*0Sstevel@tonic-gate { 238*0Sstevel@tonic-gate char *skip(); 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate for( ; *str && igncnt < MAXIGN; str = skip(str), igncnt++) 241*0Sstevel@tonic-gate ignlist[igncnt] = str; 242*0Sstevel@tonic-gate if(igncnt == MAXIGN) { 243*0Sstevel@tonic-gate fprintf(stderr, "%s: ignore list overflow. Recompile with larger MAXIGN\n", cmd); 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate bread(fd, bno, buf, cnt, dev) 247*0Sstevel@tonic-gate register fd; 248*0Sstevel@tonic-gate register unsigned bno; 249*0Sstevel@tonic-gate register struct dinode *buf; 250*0Sstevel@tonic-gate register dev_t dev; 251*0Sstevel@tonic-gate { 252*0Sstevel@tonic-gate lseek(fd, (long)bno*dev, 0); 253*0Sstevel@tonic-gate if (read(fd, buf, cnt) != cnt) 254*0Sstevel@tonic-gate { 255*0Sstevel@tonic-gate fprintf(stderr, "%s: read error %u\n", cmd, bno); 256*0Sstevel@tonic-gate exit(1); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate count(j, dev) 261*0Sstevel@tonic-gate register j; 262*0Sstevel@tonic-gate register dev_t dev; 263*0Sstevel@tonic-gate { 264*0Sstevel@tonic-gate long blocks(); 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate if ( dinode[j].di_nlink == 0 || dinode[j].di_mode == 0 ) 267*0Sstevel@tonic-gate return(SUCCEED); 268*0Sstevel@tonic-gate if( (index = hash(dinode[j].di_uid)) == FAIL || userlist[index].uid == UNUSED ) 269*0Sstevel@tonic-gate return (FAIL); 270*0Sstevel@tonic-gate userlist[index].usage += blocks(j, dev); 271*0Sstevel@tonic-gate return (SUCCEED); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate output() 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate for (index=0; index < MAXUSERS ; index++) 278*0Sstevel@tonic-gate if ( userlist[index].uid != UNUSED && userlist[index].usage != 0 ) 279*0Sstevel@tonic-gate printf("%ld %s %ld\n", 280*0Sstevel@tonic-gate userlist[index].uid, 281*0Sstevel@tonic-gate userlist[index].name, 282*0Sstevel@tonic-gate userlist[index].usage); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate #define SNGLIND(dev) (dev/sizeof(daddr_t)) 286*0Sstevel@tonic-gate #define DBLIND(dev) ((dev/sizeof(daddr_t))*(dev/sizeof(daddr_t))) 287*0Sstevel@tonic-gate #define TRPLIND(dev) ((dev/sizeof(daddr_t))*(dev/sizeof(daddr_t))*(dev/sizeof(daddr_t))) 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate long 290*0Sstevel@tonic-gate blocks(j, dev) 291*0Sstevel@tonic-gate register int j; 292*0Sstevel@tonic-gate register dev_t dev; 293*0Sstevel@tonic-gate { 294*0Sstevel@tonic-gate register long blks; 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate blks = (dinode[j].di_size + dev - 1)/dev; 297*0Sstevel@tonic-gate if(blks > 10) { 298*0Sstevel@tonic-gate blks += (blks-10+SNGLIND(dev)-1)/SNGLIND(dev); 299*0Sstevel@tonic-gate blks += (blks-10-SNGLIND(dev)+DBLIND(dev)-1)/DBLIND(dev); 300*0Sstevel@tonic-gate blks += (blks-10-SNGLIND(dev)-DBLIND(dev)+TRPLIND(dev)-1)/TRPLIND(dev); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate if(dev != BLOCK) { 303*0Sstevel@tonic-gate blks = (blks+BLOCK/dev)*(dev/BLOCK); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate return(blks); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate unsigned 309*0Sstevel@tonic-gate hash(j) 310*0Sstevel@tonic-gate uid_t j; 311*0Sstevel@tonic-gate { 312*0Sstevel@tonic-gate register unsigned start; 313*0Sstevel@tonic-gate register unsigned circle; 314*0Sstevel@tonic-gate circle = start = (unsigned)j % MAXUSERS; 315*0Sstevel@tonic-gate do 316*0Sstevel@tonic-gate { 317*0Sstevel@tonic-gate if ( userlist[circle].uid == j || userlist[circle].uid == UNUSED ) 318*0Sstevel@tonic-gate return (circle); 319*0Sstevel@tonic-gate circle = (circle + 1) % MAXUSERS; 320*0Sstevel@tonic-gate } while ( circle != start); 321*0Sstevel@tonic-gate return (FAIL); 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate hashinit() { 325*0Sstevel@tonic-gate for(index=0; index < MAXUSERS ; index++) 326*0Sstevel@tonic-gate { 327*0Sstevel@tonic-gate userlist[index].uid = UNUSED; 328*0Sstevel@tonic-gate userlist[index].usage = 0; 329*0Sstevel@tonic-gate userlist[index].name[0] = '\0'; 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate static FILE *pwf = NULL; 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate setup(pfile) 337*0Sstevel@tonic-gate char *pfile; 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate register struct passwd *pw; 340*0Sstevel@tonic-gate void end_pwent(); 341*0Sstevel@tonic-gate struct passwd * (*getpw)(); 342*0Sstevel@tonic-gate void (*endpw)(); 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate if (pfile) { 345*0Sstevel@tonic-gate if( !stpwent(pfile)) { 346*0Sstevel@tonic-gate fprintf(stderr, "%s: Cannot open %s\n", cmd, pfile); 347*0Sstevel@tonic-gate exit(5); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate getpw = fgetpwent; 350*0Sstevel@tonic-gate endpw = end_pwent; 351*0Sstevel@tonic-gate } else { 352*0Sstevel@tonic-gate setpwent(); 353*0Sstevel@tonic-gate getpw = getpwent; 354*0Sstevel@tonic-gate endpw = endpwent; 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate while ( (pw=getpw(pwf)) != NULL ) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate if ( (index=hash(pw->pw_uid)) == FAIL ) 359*0Sstevel@tonic-gate { 360*0Sstevel@tonic-gate fprintf(stderr,"%s: INCREASE SIZE OF MAXUSERS\n", cmd); 361*0Sstevel@tonic-gate return (FAIL); 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate if ( userlist[index].uid == UNUSED ) 364*0Sstevel@tonic-gate { 365*0Sstevel@tonic-gate userlist[index].uid = pw->pw_uid; 366*0Sstevel@tonic-gate (void) strncpy(userlist[index].name, pw->pw_name, NSZ); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate endpw(); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate todo(fname) 374*0Sstevel@tonic-gate register char *fname; 375*0Sstevel@tonic-gate { 376*0Sstevel@tonic-gate register i; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate for(i = 0; i < igncnt; i++) { 379*0Sstevel@tonic-gate if(strncmp(fname, ignlist[i], 6) == 0) return(FALSE); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate return(TRUE); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate char * 385*0Sstevel@tonic-gate skip(str) 386*0Sstevel@tonic-gate register char *str; 387*0Sstevel@tonic-gate { 388*0Sstevel@tonic-gate while(*str) { 389*0Sstevel@tonic-gate if(*str == ' ' || 390*0Sstevel@tonic-gate *str == ',') { 391*0Sstevel@tonic-gate *str = '\0'; 392*0Sstevel@tonic-gate str++; 393*0Sstevel@tonic-gate break; 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate str++; 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate return(str); 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate stpwent(pfile) 402*0Sstevel@tonic-gate register char *pfile; 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate if(pwf == NULL) 405*0Sstevel@tonic-gate pwf = fopen(pfile, "r"); 406*0Sstevel@tonic-gate else 407*0Sstevel@tonic-gate rewind(pwf); 408*0Sstevel@tonic-gate return(pwf != NULL); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate void 412*0Sstevel@tonic-gate end_pwent() 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate if(pwf != NULL) { 415*0Sstevel@tonic-gate (void) fclose(pwf); 416*0Sstevel@tonic-gate pwf = NULL; 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate 420