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();
main(argc,argv)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
adduser(fd)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
ilist(file,fd)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
ignore(str)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 }
bread(fd,bno,buf,cnt,dev)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
count(j,dev)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
output()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
blocks(j,dev)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
hash(j)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
hashinit()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
setup(pfile)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
todo(fname)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 *
skip(str)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
stpwent(pfile)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
end_pwent()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