Пример #1
0
int
rresvport_addr(int *alport, struct sockaddr_storage *addr)
{
	int res, err;

	(void) __priv_bracket(PRIV_ON);

	res = _rresvport_addr(alport, addr);

	err = errno;
	(void) __priv_bracket(PRIV_OFF);
	errno = err;

	return (res);
}
Пример #2
0
int
getdiskquota(struct mnttab *mntp, uid_t uid, struct dqblk *dqp)
{
	int fd;
	dev_t fsdev;
	struct stat64 statb;
	char qfilename[MAXPATHLEN];

	if (stat64(mntp->mnt_special, &statb) < 0 ||
	    (statb.st_mode & S_IFMT) != S_IFBLK)
		return (0);
	fsdev = statb.st_rdev;
	(void) snprintf(qfilename, sizeof (qfilename), "%s/%s",
	    mntp->mnt_mountp, QFNAME);
	if (stat64(qfilename, &statb) < 0 || statb.st_dev != fsdev)
		return (0);
	(void) __priv_bracket(PRIV_ON);
	fd = open64(qfilename, O_RDONLY);
	(void) __priv_bracket(PRIV_OFF);
	if (fd < 0)
		return (0);
	(void) llseek(fd, (offset_t)dqoff(uid), L_SET);
	switch (read(fd, dqp, sizeof (struct dqblk))) {
	case 0:				/* EOF */
		/*
		 * Convert implicit 0 quota (EOF)
		 * into an explicit one (zero'ed dqblk).
		 */
		memset((caddr_t)dqp, 0, sizeof (struct dqblk));
		break;

	case sizeof (struct dqblk):	/* OK */
		break;

	default:			/* ERROR */
		close(fd);
		return (0);
	}
	close(fd);
	return (1);
}
Пример #3
0
int
quotactl(int cmd, char *mountp, uid_t uid, caddr_t addr)
{
	int		fd;
	int		status;
	struct quotctl	quota;
	char		qfile[MAXPATHLEN];

	FILE		*fstab;
	struct mnttab	mnt;


	if ((mountp == NULL) && (cmd == Q_ALLSYNC)) {
	/*
	 * Find the mount point of any mounted file system. This is
	 * because the ioctl that implements the quotactl call has
	 * to go to a real file, and not to the block device.
	 */
		if ((fstab = fopen(MNTTAB, "r")) == NULL) {
			fprintf(stderr, "%s: ", MNTTAB);
			perror("open");
			zexit(32);
		}
		fd = -1;
		while ((status = getmntent(fstab, &mnt)) == NULL) {
			if (strcmp(mnt.mnt_fstype, MNTTYPE_UFS) != 0 ||
			    hasopt(MNTOPT_RO, mnt.mnt_mntopts))
				continue;
			if ((strlcpy(qfile, mnt.mnt_mountp,
			    sizeof (qfile)) >= sizeof (qfile)) ||
			    (strlcat(qfile, "/" QFNAME, sizeof (qfile)) >=
			    sizeof (qfile))) {
				continue;
			}
			(void) __priv_bracket(PRIV_ON);
			fd = open64(qfile, O_RDONLY);
			(void) __priv_bracket(PRIV_OFF);
			if (fd != -1)
				break;
		}
		fclose(fstab);
		if (fd == -1) {
			errno = ENOENT;
			return (-1);
		}
	} else {
		if (mountp == NULL || mountp[0] == '\0') {
			errno = ENOENT;
			return (-1);
		}
		if ((strlcpy(qfile, mountp, sizeof (qfile)) >= sizeof
		    (qfile)) ||
		    (strlcat(qfile, "/" QFNAME, sizeof (qfile)) >= sizeof
		    (qfile))) {
			errno = ENOENT;
			return (-1);
		}
		(void) __priv_bracket(PRIV_ON);
		fd = open64(qfile, O_RDONLY);
		(void) __priv_bracket(PRIV_OFF);
		if (fd < 0)
			return (-1);
	}	/* else */
	quota.op = cmd;
	quota.uid = uid;
	quota.addr = addr;
	status = ioctl(fd, Q_QUOTACTL, &quota);
	if (fd != 0)
		close(fd);
	return (status);
}
Пример #4
0
int
main(int argc, char *argv[])
{
	struct utmpx	*ut;
	struct utmpx	*utmpbegin;
	struct utmpx	*utmpend;
	struct utmpx	*utp;
	struct uproc	*up, *parent, *pgrp;
	struct psinfo	info;
	struct sigaction actinfo[ACTSIZE];
	struct pstatus	statinfo;
	size_t		size;
	struct stat	sbuf;
	DIR   		*dirp;
	struct	dirent	*dp;
	char		pname[64];
	char 		*fname;
	int		procfd;
	char		*cp;
	int		i;
	int		days, hrs, mins;
	int		entries;
	double		loadavg[3];

	/*
	 * This program needs the proc_owner privilege
	 */
	(void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER,
	    (char *)NULL);

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	login = (argv[0][0] == '-');
	cp = strrchr(argv[0], '/');
	firstchar = login ? argv[0][1] : (cp == 0) ? argv[0][0] : cp[1];
	prog = argv[0];

	while (argc > 1) {
		if (argv[1][0] == '-') {
			for (i = 1; argv[1][i]; i++) {
				switch (argv[1][i]) {

				case 'h':
					header = 0;
					break;

				case 'l':
					lflag++;
					break;
				case 's':
					lflag = 0;
					break;

				case 'u':
				case 'w':
					firstchar = argv[1][i];
					break;

				default:
					(void) fprintf(stderr, gettext(
					    "%s: bad flag %s\n"),
					    prog, argv[1]);
					exit(1);
				}
			}
		} else {
			if (!isalnum(argv[1][0]) || argc > 2) {
				(void) fprintf(stderr, gettext(
				    "usage: %s [ -hlsuw ] [ user ]\n"), prog);
				exit(1);
			} else
				sel_user = argv[1];
		}
		argc--; argv++;
	}

	/*
	 * read the UTMPX_FILE (contains information about each logged in user)
	 */
	if (stat(UTMPX_FILE, &sbuf) == ERR) {
		(void) fprintf(stderr, gettext("%s: stat error of %s: %s\n"),
		    prog, UTMPX_FILE, strerror(errno));
		exit(1);
	}
	entries = sbuf.st_size / sizeof (struct futmpx);
	size = sizeof (struct utmpx) * entries;
	if ((ut = malloc(size)) == NULL) {
		(void) fprintf(stderr, gettext("%s: malloc error of %s: %s\n"),
		    prog, UTMPX_FILE, strerror(errno));
		exit(1);
	}

	(void) utmpxname(UTMPX_FILE);

	utmpbegin = ut;
	utmpend = (struct utmpx *)((char *)utmpbegin + size);

	setutxent();
	while ((ut < utmpend) && ((utp = getutxent()) != NULL))
		(void) memcpy(ut++, utp, sizeof (*ut));
	endutxent();

	(void) time(&now);	/* get current time */

	if (header) {	/* print a header */
		prtat(&now);
		for (ut = utmpbegin; ut < utmpend; ut++) {
			if (ut->ut_type == USER_PROCESS) {
				if (!nonuserx(*ut))
					nusers++;
			} else if (ut->ut_type == BOOT_TIME) {
				uptime = now - ut->ut_xtime;
				uptime += 30;
				days = uptime / (60*60*24);
				uptime %= (60*60*24);
				hrs = uptime / (60*60);
				uptime %= (60*60);
				mins = uptime / 60;

				PRINTF((gettext("up")));
				if (days > 0)
					PRINTF((gettext(
					    " %d day(s),"), days));
				if (hrs > 0 && mins > 0) {
					PRINTF((" %2d:%02d,", hrs, mins));
				} else {
					if (hrs > 0)
						PRINTF((gettext(
						    " %d hr(s),"), hrs));
					if (mins > 0)
						PRINTF((gettext(
						    " %d min(s),"), mins));
				}
			}
		}

		ut = utmpbegin;	/* rewind utmp data */
		PRINTF((((nusers == 1) ?
		    gettext("  %d user") : gettext("  %d users")), nusers));
		/*
		 * Print 1, 5, and 15 minute load averages.
		 */
		(void) getloadavg(loadavg, 3);
		PRINTF((gettext(",  load average: %.2f, %.2f, %.2f\n"),
		    loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
		    loadavg[LOADAVG_15MIN]));

		if (firstchar == 'u')	/* uptime command */
			exit(0);

		if (lflag) {
			PRINTF((dcgettext(NULL, "User     tty      "
			    "login@         idle    JCPU    PCPU what\n",
			    LC_TIME)));
		} else {
			PRINTF((dcgettext(NULL,
			    "User     tty         idle what\n",
			    LC_TIME)));
		}

		if (fflush(stdout) == EOF) {
			perror((gettext("%s: fflush failed\n"), prog));
			exit(1);
		}
	}

	/*
	 * loop through /proc, reading info about each process
	 * and build the parent/child tree
	 */
	if (!(dirp = opendir(PROCDIR))) {
		(void) fprintf(stderr, gettext("%s: could not open %s: %s\n"),
		    prog, PROCDIR, strerror(errno));
		exit(1);
	}

	while ((dp = readdir(dirp)) != NULL) {
		if (dp->d_name[0] == '.')
			continue;
retry:
		(void) sprintf(pname, "%s/%s/", PROCDIR, dp->d_name);
		fname = pname + strlen(pname);
		(void) strcpy(fname, "psinfo");
		if ((procfd = open(pname, O_RDONLY)) < 0)
			continue;
		if (read(procfd, &info, sizeof (info)) != sizeof (info)) {
			int err = errno;
			(void) close(procfd);
			if (err == EAGAIN)
				goto retry;
			if (err != ENOENT)
				(void) fprintf(stderr, gettext(
				    "%s: read() failed on %s: %s \n"),
				    prog, pname, strerror(err));
			continue;
		}
		(void) close(procfd);

		up = findhash(info.pr_pid);
		up->p_ttyd = info.pr_ttydev;
		up->p_state = (info.pr_nlwp == 0? ZOMBIE : RUNNING);
		up->p_time = 0;
		up->p_ctime = 0;
		up->p_igintr = 0;
		(void) strncpy(up->p_comm, info.pr_fname,
		    sizeof (info.pr_fname));
		up->p_args[0] = 0;

		if (up->p_state != NONE && up->p_state != ZOMBIE) {
			(void) strcpy(fname, "status");

			/* now we need the proc_owner privilege */
			(void) __priv_bracket(PRIV_ON);

			procfd = open(pname, O_RDONLY);

			/* drop proc_owner privilege after open */
			(void) __priv_bracket(PRIV_OFF);

			if (procfd < 0)
				continue;

			if (read(procfd, &statinfo, sizeof (statinfo))
			    != sizeof (statinfo)) {
				int err = errno;
				(void) close(procfd);
				if (err == EAGAIN)
					goto retry;
				if (err != ENOENT)
					(void) fprintf(stderr, gettext(
					    "%s: read() failed on %s: %s \n"),
					    prog, pname, strerror(err));
				continue;
			}
			(void) close(procfd);

			up->p_time = statinfo.pr_utime.tv_sec +
			    statinfo.pr_stime.tv_sec;	/* seconds */
			up->p_ctime = statinfo.pr_cutime.tv_sec +
			    statinfo.pr_cstime.tv_sec;

			(void) strcpy(fname, "sigact");

			/* now we need the proc_owner privilege */
			(void) __priv_bracket(PRIV_ON);

			procfd = open(pname, O_RDONLY);

			/* drop proc_owner privilege after open */
			(void) __priv_bracket(PRIV_OFF);

			if (procfd < 0)
				continue;

			if (read(procfd, actinfo, sizeof (actinfo))
			    != sizeof (actinfo)) {
				int err = errno;
				(void) close(procfd);
				if (err == EAGAIN)
					goto retry;
				if (err != ENOENT)
					(void) fprintf(stderr, gettext(
					    "%s: read() failed on %s: %s \n"),
					    prog, pname, strerror(err));
				continue;
			}
			(void) close(procfd);

			up->p_igintr =
			    actinfo[SIGINT-1].sa_handler == SIG_IGN &&
			    actinfo[SIGQUIT-1].sa_handler == SIG_IGN;

			/*
			 * Process args.
			 */
			up->p_args[0] = 0;
			clnarglist(info.pr_psargs);
			(void) strcat(up->p_args, info.pr_psargs);
			if (up->p_args[0] == 0 ||
			    up->p_args[0] == '-' && up->p_args[1] <= ' ' ||
			    up->p_args[0] == '?') {
				(void) strcat(up->p_args, " (");
				(void) strcat(up->p_args, up->p_comm);
				(void) strcat(up->p_args, ")");
			}
		}

		/*
		 * link pgrp together in case parents go away
		 * Pgrp chain is a single linked list originating
		 * from the pgrp leader to its group member.
		 */
		if (info.pr_pgid != info.pr_pid) {	/* not pgrp leader */
			pgrp = findhash(info.pr_pgid);
			up->p_pgrpl = pgrp->p_pgrpl;
			pgrp->p_pgrpl = up;
		}
		parent = findhash(info.pr_ppid);

		/* if this is the new member, link it in */
		if (parent->p_upid != INITPROCESS) {
			if (parent->p_child) {
				up->p_sibling = parent->p_child;
				up->p_child = 0;
			}
			parent->p_child = up;
		}
	}

	/* revert to non-privileged user after opening */
	(void) __priv_relinquish();

	(void) closedir(dirp);
	(void) time(&now);	/* get current time */

	/*
	 * loop through utmpx file, printing process info
	 * about each logged in user
	 */
	for (ut = utmpbegin; ut < utmpend; ut++) {
		if (ut->ut_type != USER_PROCESS)
			continue;
		if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0)
			continue;	/* we're looking for somebody else */

		/* print login name of the user */
		PRINTF(("%-*.*s ", LOGIN_WIDTH, NMAX, ut->ut_name));

		/* print tty user is on */
		if (lflag) {
			PRINTF(("%-*.*s ", LINE_WIDTH, LMAX, ut->ut_line));
		} else {
			if (ut->ut_line[0] == 'p' && ut->ut_line[1] == 't' &&
			    ut->ut_line[2] == 's' && ut->ut_line[3] == '/') {
				PRINTF(("%-*.*s ", LINE_WIDTH, LMAX,
				    &ut->ut_line[4]));
			} else {
				PRINTF(("%-*.*s ", LINE_WIDTH, LMAX,
				    ut->ut_line));
			}
		}

		/* print when the user logged in */
		if (lflag) {
			time_t tim = ut->ut_xtime;
			prtat(&tim);
		}

		/* print idle time */
		idle = findidle(ut->ut_line);
		prttime(idle, 8);
		showtotals(findhash(ut->ut_pid));
	}
	if (fclose(stdout) == EOF) {
		perror((gettext("%s: fclose failed"), prog));
		exit(1);
	}
	return (0);
}
Пример #5
0
int
ucbmain(int argc, char **argv)
{
	psinfo_t info;		/* process information structure from /proc */
	char *psargs = NULL;	/* pointer to buffer for -w and -ww options */
	char *svpsargs = NULL;
	struct psent *psent;
	int entsize;
	int nent;
	pid_t maxpid;

	struct tty *ttyp = tty;
	char	*tmp;
	char	*p;
	int	c;
	pid_t	pid;		/* pid: process id */
	pid_t	ppid;		/* ppid: parent process id */
	int	i, found;

	size_t	size;

	DIR *dirp;
	struct dirent *dentp;
	char	psname[100];
	char	asname[100];
	int	pdlen;
	size_t  len;

	(void) setlocale(LC_ALL, "");

	my_uid = getuid();

	/*
	 * This program needs the proc_owner privilege
	 */
	(void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER,
	    (char *)NULL);

	/*
	 * calculate width of pid fields based on configured MAXPID
	 * (must be at least 5 to retain output format compatibility)
	 */
	maxpid = (pid_t)sysconf(_SC_MAXPID);
	pidwidth = 1;
	while ((maxpid /= 10) > 0)
		++pidwidth;
	pidwidth = pidwidth < 5 ? 5 : pidwidth;

	if (ioctl(1, TIOCGWINSZ, &win) == -1)
		twidth = 80;
	else
		twidth = (win.ws_col == 0 ? 80 : win.ws_col);

	/* add the '-' for BSD compatibility */
	if (argc > 1) {
		if (argv[1][0] != '-' && !isdigit(argv[1][0])) {
			len = strlen(argv[1]) + 2;
			tmp = malloc(len);
			if (tmp != NULL) {
				(void) snprintf(tmp, len, "%s%s", "-", argv[1]);
				argv[1] = tmp;
			}
		}
	}

	setbuf(stdout, stdbuf);
	while ((c = getopt(argc, argv, "lcaengrSt:xuvwU")) != EOF)
		switch (c) {
		case 'g':
			gflg++;	/* include process group leaders */
			break;
		case 'c':	/* display internal command name */
			cflg++;
			break;
		case 'r':	/* restrict output to running processes */
			rflg++;
			break;
		case 'S': /* display time by process and all reaped children */
			Sflg++;
			break;
		case 'x':	/* process w/o controlling tty */
			xflg++;
			break;
		case 'l':	/* long listing */
			lflg++;
			uflg = vflg = 0;
			break;
		case 'u':	/* user-oriented output */
			uflg++;
			lflg = vflg = 0;
			break;
		case 'U':	/* update private database ups_data */
			Uflg++;
			break;
		case 'w':	/* increase display width */
			if (twidth < 132)
				twidth = 132;
			else	/* second w option */
				twidth = NCARGS;
			break;
		case 'v':	/* display virtual memory format */
			vflg++;
			lflg = uflg = 0;
			break;
		case 'a':
			/*
			 * display all processes except process group
			 * leaders and processes w/o controlling tty
			 */
			aflg++;
			gflg++;
			break;
		case 'e':
			/* Display environment along with aguments. */
			eflg++;
			break;
		case 'n':	/* Display numerical output */
			nflg++;
			break;
		case 't':	/* restrict output to named terminal */
#define	TSZ	30
			tflg++;
			gflg++;
			xflg = 0;

			p1 = optarg;
			do {	/* only loop through once (NTTYS = 2) */
				parg = argbuf;
				if (ntty >= NTTYS-1)
					break;
				getarg();
				if ((p = malloc(TSZ+1)) == NULL) {
					(void) fprintf(stderr,
					    "ps: no memory\n");
					exit(1);
				}
				p[0] = '\0';
				size = TSZ;
				if (isdigit(*parg)) {
					(void) strcpy(p, "tty");
					size -= 3;
				}

				(void) strncat(p, parg, size);
				ttyp->tdev = PRNODEV;
				if (parg && *parg == '?')
					xflg++;
				else {
					char nambuf[TSZ+6]; /* for /dev/+\0 */
					struct stat64 s;
					(void) strcpy(nambuf, "/dev/");
					(void) strcat(nambuf, p);
					if (stat64(nambuf, &s) == 0)
						ttyp->tdev = s.st_rdev;
				}
				ttyp++->tname = p;
				ntty++;
			} while (*p1);
			break;
		default:			/* error on ? */
			errflg++;
			break;
		}

	if (errflg)
		usage();

	if (optind + 1 < argc) { /* more than one additional argument */
		(void) fprintf(stderr, "ps: too many arguments\n");
		usage();
	}

	/*
	 * The -U option is obsolete.  Attempts to use it cause ps to exit
	 * without printing anything.
	 */
	if (Uflg)
		exit(0);

	if (optind < argc) { /* user specified a specific proc id */
		pflg++;
		p1 = argv[optind];
		parg = argbuf;
		getarg();
		if (!num(parg)) {
			(void) fprintf(stderr,
	"ps: %s is an invalid non-numeric argument for a process id\n", parg);
			usage();
		}
		pidsave = (pid_t)atol(parg);
		aflg = rflg = xflg = 0;
		gflg++;
	}

	if (tflg)
		ttyp->tname = NULL;

	/* allocate an initial guess for the number of processes */
	entsize = 1024;
	psent = malloc(entsize * sizeof (struct psent));
	if (psent == NULL) {
		(void) fprintf(stderr, "ps: no memory\n");
		exit(1);
	}
	nent = 0;	/* no active entries yet */

	if (lflg) {
		(void) sprintf(hdr,
		    " F   UID%*s%*s %%C PRI NI   SZ  RSS    "
		    "WCHAN S TT        TIME COMMAND", pidwidth + 1, "PID",
		    pidwidth + 1, "PPID");
	} else if (uflg) {
		if (nflg)
			(void) sprintf(hdr,
			    "   UID%*s %%CPU %%MEM   SZ  RSS "
			    "TT       S    START  TIME COMMAND",
			    pidwidth + 1, "PID");
		else
			(void) sprintf(hdr,
			    "USER    %*s %%CPU %%MEM   SZ  RSS "
			    "TT       S    START  TIME COMMAND",
			    pidwidth + 1, "PID");
	} else if (vflg) {
		(void) sprintf(hdr,
		    "%*s TT       S  TIME SIZE  RSS %%CPU %%MEM "
		    "COMMAND", pidwidth + 1, "PID");
	} else
		(void) sprintf(hdr, "%*s TT       S  TIME COMMAND",
		    pidwidth + 1, "PID");

	twidth = twidth - strlen(hdr) + 6;
	(void) printf("%s\n", hdr);

	if (twidth > PRARGSZ && (psargs = malloc(twidth)) == NULL) {
		(void) fprintf(stderr, "ps: no memory\n");
		exit(1);
	}
	svpsargs = psargs;

	/*
	 * Determine which processes to print info about by searching
	 * the /proc directory and looking at each process.
	 */
	if ((dirp = opendir(procdir)) == NULL) {
		(void) fprintf(stderr, "ps: cannot open PROC directory %s\n",
		    procdir);
		exit(1);
	}

	(void) strcpy(psname, procdir);
	pdlen = strlen(psname);
	psname[pdlen++] = '/';

	/* for each active process --- */
	while (dentp = readdir(dirp)) {
		int	psfd;	/* file descriptor for /proc/nnnnn/psinfo */
		int	asfd;	/* file descriptor for /proc/nnnnn/as */

		if (dentp->d_name[0] == '.')		/* skip . and .. */
			continue;
		(void) strcpy(psname + pdlen, dentp->d_name);
		(void) strcpy(asname, psname);
		(void) strcat(psname, "/psinfo");
		(void) strcat(asname, "/as");
retry:
		if ((psfd = open(psname, O_RDONLY)) == -1)
			continue;
		asfd = -1;
		if (psargs != NULL || eflg) {

			/* now we need the proc_owner privilege */
			(void) __priv_bracket(PRIV_ON);

			asfd = open(asname, O_RDONLY);

			/* drop proc_owner privilege after open */
			(void) __priv_bracket(PRIV_OFF);
		}

		/*
		 * Get the info structure for the process
		 */
		if (read(psfd, &info, sizeof (info)) != sizeof (info)) {
			int	saverr = errno;

			(void) close(psfd);
			if (asfd > 0)
				(void) close(asfd);
			if (saverr == EAGAIN)
				goto retry;
			if (saverr != ENOENT)
				(void) fprintf(stderr, "ps: read() on %s: %s\n",
				    psname, err_string(saverr));
			continue;
		}
		(void) close(psfd);

		found = 0;
		if (info.pr_lwp.pr_state == 0)		/* can't happen? */
			goto closeit;
		pid = info.pr_pid;
		ppid = info.pr_ppid;

		/* Display only process from command line */
		if (pflg) {	/* pid in arg list */
			if (pidsave == pid)
				found++;
			else
				goto closeit;
		}

		/*
		 * Omit "uninteresting" processes unless 'g' option.
		 */
		if ((ppid == 1) && !(gflg))
			goto closeit;

		/*
		 * Omit non-running processes for 'r' option
		 */
		if (rflg &&
		    !(info.pr_lwp.pr_sname == 'O' ||
		    info.pr_lwp.pr_sname == 'R'))
			goto closeit;

		if (!found && !tflg && !aflg && info.pr_euid != my_uid)
			goto closeit;

		/*
		 * Read the args for the -w and -ww cases
		 */
		if (asfd > 0) {
			if ((psargs != NULL &&
			    preadargs(asfd, &info, psargs) == -1) ||
			    (eflg && preadenvs(asfd, &info, psargs) == -1)) {
				int	saverr = errno;

				(void) close(asfd);
				if (saverr == EAGAIN)
					goto retry;
				if (saverr != ENOENT)
					(void) fprintf(stderr,
					    "ps: read() on %s: %s\n",
					    asname, err_string(saverr));
				continue;
			}
		} else {
			psargs = info.pr_psargs;
		}

		if (nent >= entsize) {
			entsize *= 2;
			psent = (struct psent *)realloc((char *)psent,
			    entsize * sizeof (struct psent));
			if (psent == NULL) {
				(void) fprintf(stderr, "ps: no memory\n");
				exit(1);
			}
		}
		if ((psent[nent].psinfo = malloc(sizeof (psinfo_t)))
		    == NULL) {
			(void) fprintf(stderr, "ps: no memory\n");
			exit(1);
		}
		*psent[nent].psinfo = info;
		if (psargs == NULL)
			psent[nent].psargs = NULL;
		else {
			if ((psent[nent].psargs = malloc(strlen(psargs)+1))
			    == NULL) {
				(void) fprintf(stderr, "ps: no memory\n");
				exit(1);
			}
			(void) strcpy(psent[nent].psargs, psargs);
		}
		psent[nent].found = found;
		nent++;
closeit:
		if (asfd > 0)
			(void) close(asfd);
		psargs = svpsargs;
	}

	/* revert to non-privileged user */
	(void) __priv_relinquish();

	(void) closedir(dirp);

	qsort((char *)psent, nent, sizeof (psent[0]), pscompare);

	for (i = 0; i < nent; i++) {
		struct psent *pp = &psent[i];
		if (prcom(pp->found, pp->psinfo, pp->psargs)) {
			(void) printf("\n");
			retcode = 0;
		}
	}

	return (retcode);
}