⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sa.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char *sccsid = "@(#)sa.c	4.2	ULTRIX	1/3/91";#endif/************************************************************************ *									* *			Copyright (c) 1991 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Modification History * * 1/3/91 - dlong *	Modified to eliminate unnecessary global declarations, particularily *	"bcmp()" which was conflicting with a libc routine. *//* *	Extensive modifications to internal data structures *	to allow arbitrary number of different commands and users added. *	 *	Also allowed the digit option on the -v flag (interactive *	threshold compress) to be a digit string, so one can *	set the threshold > 9. * *	Also added the -f flag, to force no interactive threshold *	compression with the -v flag. * *	Robert Henry *	UC Berkeley *	31jan81 * *	aps00  9/21/83	-- fixed code in doacct() so that the -u *			would work properly. * *	aps01 9/21/83	-- changed doacct() so that login names are *			printed instead of UID's during -u option * *//* *	Modified By :	Aki Hirai , Digital Equipment Corp. *			30 - May - 1985 * *	/aki00/	-------	Fix a floaing point violation problem when -t flag *	/aki01/ ------- Fix a rubbish output problem when -u flag *	/aki02/ ------- Fix a rubbish command name problem when AFORK *	Jon Reeves, November 1988 *	/jlr001/ ------ Add portable fix-point conversion code */#include <stdio.h>#include <sys/types.h>#include <sys/acct.h>#include <signal.h>#include <utmp.h>#include <pwd.h>/* interpret command time accounting */#define	NC	sizeof(acctbuf.ac_comm)#ifndef AHZ#define AHZ 60#endif#ifdef vax#define SCALEF 2#else#define SCALEF 1#endifstatic struct acct acctbuf;static int	lflg;static int	cflg;static int	Dflg;static int	dflg;static int	iflg;static int	jflg;static int	Kflg;static int	kflg;static int	nflg;static int	aflg;static int	rflg;static int	oflg;static int	tflg;static int	vflg;static int	fflg;static int	uflg;static int	thres = 0;static int	sflg;static int	bflg;static int	mflg;static struct	utmp	utmp;#define	NAMELG	(sizeof(utmp.ut_name)+1)struct 	Olduser{	int	Us_cnt;	double	Us_ctime;	double	Us_io;	double	Us_imem;};	struct	user {	char	name[NC];		/* this is <\001><user id><\000> */	struct	Olduser	oldu;	char	us_name[NAMELG];};#define	us_cnt		oldu.Us_cnt#define	us_ctime	oldu.Us_ctime#define	us_io		oldu.Us_io#define	us_imem		oldu.Us_imem/* *	We protect ourselves from preposterous user id's by looking *	through the passwd file for the highest uid allocated, and *	then adding 10 to that. *	This prevents the user structure from growing too large. */#define	USERSLOP	10static int	maxuser = -1;		/* highest uid from /etc/passwd, + 10 for slop*/struct	process {	char	name[NC];	int	count;	double	realt;	double	cput;	double	syst;	double	imem;	double	io;};union	Tab{	struct	process	p;	struct	user	u;};typedef	union Tab cell;static int	(*cmp)();	/* compares 2 cells; set to appropriate func */static cell	*enter();static struct	user *finduser();static struct	user *wasuser();/* *	Table elements are keyed by the name of the file exec'ed. *	Because on large systems, many files can be exec'ed, *	a static table size may grow to be too large. * *	Table elements are allocated in chunks dynamically, linked *	together so that they may be retrieved sequentially. * *	An index into the table structure is provided by hashing through *	a seperate hash table. *	The hash table is segmented, and dynamically extendable. *	Realize that the hash table and accounting information is kept *	in different segments! * *	We have a linked list of hash table segments; within each *	segment we use a quadratic rehash that touches no more than 1/2 *	of the buckets in the hash table when probing. *	If the probe does not find the desired symbol, it moves to the *	next segment, or allocates a new segment. * *	Hash table segments are kept on the linked list with the first *	segment always first (that will probably contain the *	most frequently executed commands) and *	the last added segment immediately after the first segment, *	to hopefully gain something by locality of reference. * *	We store the per user information in the same structure as *	the per exec'ed file information.  This allows us to use the *	same managers for both, as the number of user id's may be very *	large. *	User information is keyed by the first character in the name *	being a '\001', followed by four bytes of (long extended) *	user id number, followed by a null byte. *	The actual user names are kept in a seperate field of the *	user structure, and is filled in upon demand later. *	Iteration through all users by low user id to high user id *	is done by just probing the table, which is gross. */#define	USERKEY	'\001'#define	ISPROCESS(tp)	(tp->p.name[0] && (tp->p.name[0] != USERKEY))#define	ISUSER(tp)	(tp->p.name[0] && (tp->p.name[0] == USERKEY))#define	TABDALLOP	500struct 	allocbox{	struct	allocbox	*nextalloc;	cell			tabslots[TABDALLOP];};static struct	allocbox	*allochead;	/*head of chunk list*/static struct	allocbox	*alloctail;	/*tail*/static struct	allocbox	*newbox;	/*for creating a new chunk*/static cell			*nexttab;	/*next table element that is free*/static int			tabsleft;	/*slots left in current chunk*/static int			ntabs;/* *	Iterate through all symbols in the symbol table in declaration *	order. *	struct	allocbox	*allocwalk; *	cell			*sp, *ub; * *	sp points to the desired item, allocwalk and ub are there *	to make the iteration go. */#define DECLITERATE(allocwalk, walkpointer, ubpointer) \	for(allocwalk = allochead; \	    allocwalk != 0; \	    allocwalk = allocwalk->nextalloc) \		for (walkpointer = &allocwalk->tabslots[0],\		        ubpointer = &allocwalk->tabslots[TABDALLOP], \		        ubpointer = ubpointer > ( (cell *)alloctail) \				 ? nexttab : ubpointer ;\		     walkpointer < ubpointer; \		     walkpointer++ )#define TABCHUNKS(allocwalk, tabptr, size) \	for (allocwalk = allochead; \	    allocwalk != 0; \	    allocwalk = allocwalk->nextalloc) \	    if ( \		(tabptr = &allocwalk->tabslots[0]), \		(size = \		 (   (&allocwalk->tabslots[TABDALLOP]) \		   > ((cell *)alloctail) \		 ) \		   ? (nexttab - tabptr) : TABDALLOP \		), \		1 \	    )#define	PROCESSITERATE(allocwalk, walkpointer, ubpointer) \	DECLITERATE(allocwalk, walkpointer, ubpointer) \	if (ISPROCESS(walkpointer))#define	USERITERATE(allocwalk, walkpointer, ubpointer) \	DECLITERATE(allocwalk, walkpointer, ubpointer) \	if (ISUSER(walkpointer))/* *	When we have to sort the segmented accounting table, we *	create a vector of sorted queues that is merged *	to sort the entire accounting table. */struct chunkdesc   {	cell	*chunk_tp;	int	chunk_n;};/* *	Hash table segments and manager */#define	NHASH	1103struct hashdallop {	int	h_nused;	struct	hashdallop	*h_next;	cell		*h_tab[NHASH];};static struct	hashdallop	*htab;	/* head of the list */static int	htabinstall = 1;	/* install the symbol */static double	treal;static double	tcpu;static double	tsys;static double	tio;static double	timem;static cell	*junkp = 0;static char	*sname;static double	ncom;#ifndef vax /* JLR001 */static time_t	expand();#endifstatic char	*getname();/* *	usracct saves records of type Olduser. *	There is one record for every possible uid less than *	the largest uid seen in the previous usracct or in savacct. *	uid's that had no activity correspond to zero filled slots; *	thus one can index the file and get the user record out. *	It would be better to save only user information for users *	that the system knows about to save space, but that is not *	upward compatabile with the old system. * *	In the old version of sa, uid's greater than 999 were not handled *	properly; this system will do that. */#ifdef	DEBUG#define	USRACCT "./usracct"#define	SAVACCT	"./savacct"#define	ACCT	"./acct"#else#define	USRACCT "/usr/adm/usracct"#define	SAVACCT	"/usr/adm/savacct"#define	ACCT	"/usr/adm/acct"#endif	DEBUGstatic int	cellcmp();/* *	The threshold is built up from digits in the argv ; *	eg, -v1s0u1 *	will build a value of thres of 101. * *	If the threshold is zero after processing argv, it is set to 1 *//* we assume pagesize is at least 1k */static int	pgdiv;#define	pgtok(x)	((x) / pgdiv)static	tcmp(), ncmp(), bcmp(), dcmp(), Dcmp(), kcmp(), Kcmp();extern	double sum();main(argc, argv)	char **argv;{	FILE *ff;	double ft;	register struct	allocbox *allocwalk;	register cell *tp, *ub;	int i, j, size, nchunks, smallest;	struct chunkdesc *chunkvector;	pgdiv = getpagesize() / 1024;	if (pgdiv == 0)		pgdiv = 1;	maxuser = USERSLOP + getmaxuid();	tabinit();	cmp = tcmp;	if (argc>1)	if (argv[1][0]=='-') {		argv++;		argc--;		for(i=1; argv[0][i]; i++)		switch(argv[0][i]) {		case 'o':			oflg++;			break;		case 'i':			iflg++;			break;		case 'b':			bflg++;			cmp = bcmp;			break;		case 'l':			lflg++;			break;		case 'c':			cflg++;			break;		case 'd':			dflg++;			cmp = dcmp;			break;		case 'D':			Dflg++;			cmp = Dcmp;			break;		case 'j':			jflg++;			break;		case 'k':			kflg++;			cmp = kcmp;			break;		case 'K':			Kflg++;			cmp = Kcmp;			break;		case 'n':			nflg++;			cmp = ncmp;			break;		case 'a':			aflg++;			break;		case 'r':			rflg++;			break;		case 't':			tflg++;			break;		case 's':			sflg++;			aflg++;			break;		case '0':		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		case '8':		case '9':			thres = thres * 10 + (argv[0][i]-'0');			break;		case 'v':			vflg++;			break;		case 'f':			fflg++;	/* force v option; no tty interaction */			break;		case 'u':			uflg++;			break;		case 'm':			mflg++;			break;		}	}	if (thres == 0)		thres = 1;	if (iflg==0)		init();	if (argc<2)		doacct(ACCT);	else while (--argc)		doacct(*++argv);	if (uflg) {		return;	}/* * cleanup pass * put junk together */	if (vflg)		strip();	if(!aflg)	PROCESSITERATE(allocwalk, tp, ub){		for(j=0; j<NC; j++)			if(tp->p.name[j] == '?')				goto yes;		if(tp->p.count != 1)			continue;	yes:		if(junkp == 0)			junkp = enter("***other");		junkp->p.count += tp->p.count;		junkp->p.realt += tp->p.realt;		junkp->p.cput += tp->p.cput;		junkp->p.syst += tp->p.syst;		junkp->p.imem += tp->p.imem;		junkp->p.io += tp->p.io;		tp->p.name[0] = 0;	}	if (sflg) {		signal(SIGINT, SIG_IGN);		if ((ff = fopen(USRACCT, "w")) != NULL) {			static	struct	user ZeroUser = {0};			struct 	user	*up;			int	uid;			/*			 *	Write out just enough user slots,			 *	filling with zero slots for users that			 *	weren't found.			 *	The file can be indexed directly by uid			 *	to get the correct record.			 */			for (uid = 0; uid < maxuser; uid++){				if ( (up = wasuser(uid)) != 0)					fwrite((char *)&(up->oldu),						sizeof(struct Olduser),1,ff);				else					fwrite((char *)&(ZeroUser.oldu),						sizeof(struct Olduser),1,ff);			}		}		if ((ff = fopen(SAVACCT, "w")) == NULL) {			printf("Can't save\n");			exit(0);		}		PROCESSITERATE(allocwalk, tp, ub)			fwrite((char *)&(tp->p), sizeof(struct process), 1, ff);		fclose(ff);		creat(sname, 0644);		signal(SIGINT, SIG_DFL);	}/* * sort and print */	if (mflg) {		printmoney();		exit(0);	}	column(ncom, treal, tcpu, tsys, timem, tio);	printf("\n");	/*	 *	the fragmented table is sorted by sorting each fragment	 *	and then merging.	 */	nchunks = 0;	TABCHUNKS(allocwalk, tp, size){		qsort(tp, size, sizeof(cell), cellcmp);		nchunks ++;	}	chunkvector = (struct chunkdesc *)calloc(nchunks,		sizeof(struct chunkdesc));	nchunks = 0;	TABCHUNKS(allocwalk, tp, size){		chunkvector[nchunks].chunk_tp = tp;		chunkvector[nchunks].chunk_n = size;		nchunks++;	}	for(; nchunks; ){		/*		 *	Find the smallest element at the head of the queues.		 */		smallest = 0;		for (i = 1; i < nchunks; i++){			if (cellcmp(chunkvector[i].chunk_tp,				chunkvector[smallest].chunk_tp) < 0)					smallest = i;		}		tp = chunkvector[smallest].chunk_tp++;		/*		 *	If this queue is drained, drop the chunk count,		 *	and readjust the queues.		 */		if (--chunkvector[smallest].chunk_n == 0){			nchunks--;			for (i = smallest; i < nchunks; i++)				chunkvector[i] = chunkvector[i+1];		}		if (ISPROCESS(tp)){			ft = tp->p.count;			column(ft, tp->p.realt, tp->p.cput,				tp->p.syst, tp->p.imem, tp->p.io);			printf("   %.14s\n", tp->p.name);		}	}	/* iterate to merge the lists */}static printmoney(){	register i;	register char *cp;	register	struct user	*up;	getnames();		/* fetches all of the names! */	for (i = 0; i < maxuser; i++) {		if ( (up = wasuser(i)) != 0){			if (up->us_cnt) {				if (up->us_name[0])					printf("%-8s", up->us_name);				else 					printf("%-8d", i);				printf("%7u %9.2fcpu %10.0ftio %12.0fk*sec\n",					up->us_cnt, up->us_ctime / 60,					up->us_io,					up->us_imem / (AHZ * SCALEF));			}		}	}}static column(n, a, b, c, d, e)	double n, a, b, c, d, e;{	printf("%8.0f", n);	if(cflg) {		if(n == ncom)			printf("%9s", ""); else			printf("%8.2f%%", 100.*n/ncom);	}	col(n, a, treal, "re");	if (oflg)		col(n, 60*AHZ*(b/(b+c)), tcpu+tsys, "u/s");	else if(lflg) {		col(n, b, tcpu, "u");		col(n, c, tsys, "s");	} else		col(n, b+c, tcpu+tsys, "cp");	if(tflg)/* aki00 */	    if(b+c)		printf("%8.1fre/cp", a/(b+c));	    else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -