Esempio n. 1
0
/*
** The engine() drives the main-loop of the program
*/
static void
engine(void)
{
	int 			i, j;
	struct sigaction 	sigact;
	static time_t		timelimit;
	void			getusr1(int), getusr2(int);

	/*
	** reserve space for system-level statistics
	*/
	static struct sstat	*cursstat; /* current   */
	static struct sstat	*presstat; /* previous  */
	static struct sstat	*devsstat; /* deviation */
	static struct sstat	*hlpsstat;

	/*
	** reserve space for task-level statistics
	*/
	static struct tstat	*curpact;	/* current active list  */
	static int		curplen;	/* current active size  */

	struct tstat		*curpexit;	/* exited process list	*/
	struct tstat		*devtstat;	/* deviation list	*/
	struct tstat		**devpstat;	/* pointers to processes*/
						/* in deviation list    */

	unsigned int		ntask, nexit, nexitnet;
	unsigned int		noverflow, ndeviat, nactproc;
	int			totproc, totrun, totslpi, totslpu, totzombie;

	/*
	** initialization: allocate required memory dynamically
	*/
	cursstat = calloc(1, sizeof(struct sstat));
	presstat = calloc(1, sizeof(struct sstat));
	devsstat = calloc(1, sizeof(struct sstat));

	curplen  = countprocs() * 3 / 2;	/* add 50% for threads */
	curpact  = calloc(curplen, sizeof(struct tstat));

	ptrverify(cursstat, "Malloc failed for current sysstats\n");
	ptrverify(presstat, "Malloc failed for prev    sysstats\n");
	ptrverify(devsstat, "Malloc failed for deviate sysstats\n");
	ptrverify(curpact,  "Malloc failed for %d procstats\n", curplen);

	/*
	** install the signal-handler for ALARM, USR1 and USR2 (triggers
	* for the next sample)
	*/
	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr1;
	sigaction(SIGUSR1, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr2;
	sigaction(SIGUSR2, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getalarm;
	sigaction(SIGALRM, &sigact, (struct sigaction *)0);

	if (interval > 0)
		alarm(interval);

	if (midnightflag)
	{
		time_t		timenow = time(0);
		struct tm	*tp = localtime(&timenow);

		tp->tm_hour = 23;
		tp->tm_min  = 59;
		tp->tm_sec  = 59;

		timelimit = mktime(tp);
	}

	/*
	** MAIN-LOOP:
	**    -	Wait for the requested number of seconds or for other trigger
	**
	**    -	System-level counters
	**		get current counters
	**		calculate the differences with the previous sample
	**
	**    -	Process-level counters
	**		get current counters from running & exited processes
	**		calculate the differences with the previous sample
	**
	**    -	Call the print-function to visualize the differences
	*/
	for (sampcnt=0; sampcnt < nsamples; sampcnt++)
	{
		char	lastcmd;

		/*
		** if the limit-flag is specified:
		**  check if the next sample is expected before midnight;
		**  if not, stop atop now 
		*/
		if (midnightflag && (curtime+interval) > timelimit)
			break;

		/*
		** wait for alarm-signal to arrive (except first sample)
		** or wait for SIGUSR1/SIGUSR2
		*/
		if (sampcnt > 0 && awaittrigger)
			pause();

		awaittrigger = 1;

		/*
		** gather time info for this sample
		*/
		pretime  = curtime;
		curtime  = time(0);		/* seconds since 1-1-1970 */

		/*
		** take a snapshot of the current system-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		*/
		hlpsstat = cursstat;	/* swap current/prev. stats */
		cursstat = presstat;
		presstat = hlpsstat;

		photosyst(cursstat);	/* obtain new counters      */

		deviatsyst(cursstat, presstat, devsstat);

		/*
		** take a snapshot of the current task-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		**
		** first register active tasks
		**  --> atop malloc's a minimal amount of space which is
		**      only extended when needed
		*/
		memset(curpact, 0, curplen * sizeof(struct tstat));

		while ( (ntask = photoproc(curpact, curplen)) == curplen)
		{
			curplen += PROCCHUNK;

			curpact = realloc(curpact,
					curplen * sizeof(struct tstat));

			ptrverify(curpact,
			          "Realloc failed for %d tasks\n", curplen);

			memset(curpact, 0, curplen * sizeof(struct tstat));
		}

		/*
		** register processes that exited during last sample;
		** first determine how many processes exited
		**
		** the number of exited processes is limited to avoid
		** that atop explodes in memory and introduces OOM killing
		*/
		nexit = acctprocnt();	/* number of exited processes */

		if (nexit > MAXACCTPROCS)
		{
			noverflow = nexit - MAXACCTPROCS;
			nexit     = MAXACCTPROCS;
		}
		else
			noverflow = 0;

		/*
		** determine how many processes have been exited
		** for the netatop module (only processes that have
		** used the network)
		*/
		if (nexit > 0 && (supportflags & NETATOPD))
			nexitnet = netatop_exitstore();
		else
			nexitnet = 0;

		/*
		** reserve space for the exited processes and read them
		*/
		if (nexit > 0)
		{
			curpexit = malloc(nexit * sizeof(struct tstat));

			ptrverify(curpexit,
			          "Malloc failed for %d exited processes\n",
			          nexit);

			memset(curpexit, 0, nexit * sizeof(struct tstat));

			acctphotoproc(curpexit, nexit);

			/*
 			** reposition offset in accounting file when not
			** all exited processes have been read (i.e. skip
			** those processes)
			*/
			if (noverflow)
				acctrepos(noverflow);
		}
		else
		{
			curpexit    = NULL;
		}

		/*
		** calculate deviations
		*/
		devtstat = malloc((ntask+nexit) * sizeof(struct tstat));

		ptrverify(devtstat, "Malloc failed for %d modified processes\n",
			          				ntask+nexit);

		ndeviat = deviatproc(curpact, ntask, curpexit, nexit, 
				deviatonly, devtstat, devsstat, &nactproc,
				&totproc, &totrun, &totslpi, &totslpu, 
		                &totzombie);

  	      	/*
 		** create list of pointers specifically to the process entries
		** in the task list
		*/
       		devpstat = malloc(sizeof (struct tstat *) * nactproc);

		ptrverify(devpstat, "Malloc failed for %d process ptrs\n",
			          				nactproc);

		for (i=0, j=0; i < ndeviat; i++)
		{
			if ( (devtstat+i)->gen.isproc)
				devpstat[j++] = devtstat+i;
		}

		/*
		** activate the installed print-function to visualize
		** the deviations
		*/
		lastcmd = (vis.show_samp)( curtime,
				     curtime-pretime > 0 ? curtime-pretime : 1,
		           	     devsstat, devtstat, devpstat,
		                     ndeviat, ntask, nactproc,
		                     totproc, totrun, totslpi, totslpu,
		                     totzombie, nexit, noverflow, sampcnt==0);

		/*
		** release dynamically allocated memory
		*/
		if (nexit > 0)
			free(curpexit);

		if (nexitnet > 0)
			netatop_exiterase();

		free(devtstat);
		free(devpstat);

		if (lastcmd == 'r')	/* reset requested ? */
		{
			sampcnt = -1;

			curtime = getboot() / hertz;	// reset current time

			/* set current (will be 'previous') counters to 0 */
			memset(cursstat, 0,           sizeof(struct sstat));
			memset(curpact,  0, curplen * sizeof(struct tstat));

			/* remove all tasks in database */
			pdb_makeresidue();
			pdb_cleanresidue();
		}
	} /* end of main-loop */
}
Esempio n. 2
0
int
main(int argc, char *argv[])
{
	register int	i;
	int		c;
	char		*p;
	struct rlimit	rlim;

	/*
	** since priviliged actions will be done later on, at this stage
	** the root-priviliges are dropped by switching effective user-id
	** to real user-id (security reasons)
	*/
        if (! droprootprivs() )
	{
		fprintf(stderr, "not possible to drop root privs\n");
                exit(42);
	}

	/*
	** preserve command arguments to allow restart of other version
	*/
	argvp = argv;

	/*
	** read defaults-files /etc/atoprc en $HOME/.atoprc (if any)
	*/
	readrc("/etc/atoprc");

	if ( (p = getenv("HOME")) )
	{
		char path[1024];

		snprintf(path, sizeof path, "%s/.atoprc", p);

		readrc(path);
	}

	/*
	** check if we are supposed to behave as 'atopsar'
	** i.e. system statistics only
	*/
	if ( (p = strrchr(argv[0], '/')))
		p++;
	else
		p = argv[0];

	if ( memcmp(p, "atopsar", 7) == 0)
		return atopsar(argc, argv);

	/* 
	** interpret command-line arguments & flags 
	*/
	if (argc > 1)
	{
		/* 
		** gather all flags for visualization-functions
		**
		** generic flags will be handled here;
		** unrecognized flags are passed to the print-routines
		*/
		i = 0;

		while (i < MAXFL-1 && (c=getopt(argc, argv, allflags)) != EOF)
		{
			switch (c)
			{
			   case '?':		/* usage wanted ?             */
				prusage(argv[0]);
				break;

			   case 'V':		/* version wanted ?           */
				printf("%s\n", getstrvers());
				exit(0);

			   case 'w':		/* writing of raw data ?      */
				if (optind >= argc)
					prusage(argv[0]);

				strncpy(rawname, argv[optind++], RAWNAMESZ-1);
				vis.show_samp = rawwrite;
				break;

			   case 'r':		/* reading of raw data ?      */
				if (optind < argc && *(argv[optind]) != '-')
					strncpy(rawname, argv[optind++],
							RAWNAMESZ-1);

				rawreadflag++;
				break;

			   case 'S':		/* midnight limit ?           */
				midnightflag++;
				break;

                           case 'a':		/* all processes per sample ? */
				deviatonly=0;
				break;

                           case 'b':		/* begin time ?               */
				if ( !hhmm2secs(optarg, &begintime) )
					prusage(argv[0]);
				break;

                           case 'e':		/* end   time ?               */
				if ( !hhmm2secs(optarg, &endtime) )
					prusage(argv[0]);
				break;

                           case 'j':		/* show disk partitions statistics */
				diskpartview = 1;
				break;

                           case 'P':		/* parseable output?          */
				if ( !parsedef(optarg) )
					prusage(argv[0]);

				vis.show_samp = parseout;
				break;

                           case 'L':		/* line length                */
				if ( !numeric(optarg) )
					prusage(argv[0]);

				linelen = atoi(optarg);
				break;

			   default:		/* gather other flags */
				flaglist[i++] = c;
			}
		}

		/*
		** get optional interval-value and optional number of samples	
		*/
			if (optind < argc && optind < MAXFL)
		{
			if (!numeric(argv[optind]))
				prusage(argv[0]);
	
			interval = atoi(argv[optind]);
	
			optind++;
	
			if (optind < argc)
			{
				if (!numeric(argv[optind]) )
					prusage(argv[0]);

				if ( (nsamples = atoi(argv[optind])) < 1)
					prusage(argv[0]);
			}
		}
	}

	/*
	** determine the name of this node (without domain-name)
	** and the kernel-version
	*/
	(void) uname(&utsname);

	if ( (p = strchr(utsname.nodename, '.')) )
		*p = '\0';

	utsnodenamelen = strlen(utsname.nodename);

	sscanf(utsname.release, "%d.%d.%d", &osrel, &osvers, &ossub);

	/*
	** determine the clock rate and memory page size for this machine
	*/
	hertz		= sysconf(_SC_CLK_TCK);
	pagesize	= sysconf(_SC_PAGESIZE);

	/*
	** check if raw data from a file must be viewed
	*/
	if (rawreadflag)
	{
		rawread();
		cleanstop(0);
	}

	/*
	** determine start-time for gathering current statistics
	*/
	curtime = getboot() / hertz;

	/*
	** catch signals for proper close-down
	*/
	signal(SIGHUP,  cleanstop);
	signal(SIGTERM, cleanstop);

	/*
	** regain the root-priviliges that we dropped at the beginning
	** to do some priviliged work
	*/
	regainrootprivs();

	/*
	** lock ATOP in memory to get reliable samples (also when
	** memory is low);
	** ignored if not running under superuser priviliges!
	*/
	rlim.rlim_cur	= RLIM_INFINITY;
	rlim.rlim_max	= RLIM_INFINITY;
	(void) setrlimit(RLIMIT_MEMLOCK, &rlim);

	(void) mlockall(MCL_CURRENT|MCL_FUTURE);

	/*
	** increment CPU scheduling-priority to get reliable samples (also
	** during heavy CPU load);
	** ignored if not running under superuser priviliges!
	*/
	if ( nice(-20) == -1)
		;

	/*
	** switch-on the process-accounting mechanism to register the
	** (remaining) resource-usage by processes which have finished
	*/
	acctreason = acctswon();

	/*
	** determine properties (like speed) of all interfaces
	*/
	initifprop();

	/*
 	** open socket to the IP layer to issue getsockopt() calls later on
	*/
	netatop_ipopen();
	
	/*
	** since priviliged activities are finished now, there is no
	** need to keep running under root-priviliges, so switch
	** effective user-id to real user-id
	*/
        if (! droprootprivs() )
		cleanstop(42);

	/*
	** start the engine now .....
	*/
	engine();

	cleanstop(0);

	return 0;	/* never reached */
}
Esempio n. 3
0
/*
 * Install hard disk driver.
 *
 */
install()
{
    int i, pdev, ldev;
    int maxsiz;
    char *s, *d, sdev, dvr[15];
    char *lbuf;
    extern char rootstart, rootend;
    extern char bootstart, bootend;

    if ((ldev = glogdev()) < 0) 
	return BAILOUT;
  
    /* final warning */
    sdev = ldev + 'C';
    (instfnl[INSTDRV].ob_spec)->te_ptext = &sdev;
    instfnl[INSTOK].ob_state = NORMAL;
    instfnl[INSTCN].ob_state = NORMAL;
    if (execform(instfnl) != INSTOK) return BAILOUT;

    /* find maximum sector size on system */
    if (!vernum)	    /* new version of AHDI? */
	maxsiz = 512;	    /* if not, sector size is always 512 bytes */
    else
	maxsiz = *(vernum + 1);	/* max sector size kept after version # */

    if (!(lbuf = Malloc((long)maxsiz))) {
	err(nomemory);
	return ERROR;
    }

    /* find which physical unit the chosen logical drive belongs to */
    pdev = physdev[ldev];
    pdev &= 0x1f;		/* mask off extra bits */
      
    /* Remove old driver if there is one */
    dvr[0] = sdev;
    strcpy(&dvr[1], OLDDVR);
    if (!(Fsfirst(dvr, 0x04)))	/* 0x04 = system files */
	Fdelete(dvr);
          
  
    /* copy driver to specified unit */
    if (copydvr(sdev) != OK)
	return ERROR;

    /* read in the root sector */
    if (getroot(pdev, lbuf) != 0) {
	err(rootread);
	goto argh;
    }
  
    /* copy boot code into root sector */
    for (d = lbuf, s = &rootstart, i = &rootend - &rootstart; i--;)
	*d++ = *s++;

    /* if gemroot() is not successful, return with error */
    if (gemroot(lbuf, 1) != 0) {
	err(cantinst);
	goto argh;
    }

    /* write installed root sector back to disk */  
    if (putroot(pdev, lbuf) != 0) {
	err(rootwrit);
	goto argh;
    }

    /* read boot sector from partition */
    if (getboot(ldev, lbuf) != 0) {
	err(bootread);
	goto argh;
    }

    /* 
     * copy boot code to boot sector, avoiding the BPB information 
     * copy bytes 0..1 for BRA.S to code;
     * leave bytes 2..$1d unaltered (information for BPB);
     * copy bytes $1e..$1fe for code.
     */
    s = &bootstart;
    d = lbuf;
    *d++ = *s++;
    *d++ = *s++;
    d += 0x1c;
    s += 0x1c;
    for (i = &bootend-&bootstart-0x1e; i--;)
	*d++ = *s++;

    /* make the image executable */
    Protobt(lbuf, -1L, -1, 1);

    /* write the installed boot sector back to disk */
    if (putboot(ldev, lbuf) != 0) {
	err(bootwrit);
	goto argh;
    }

    return;

argh:
    dvr[0] = sdev;
    strcpy(&dvr[1], DVRNAME);
    Fdelete(dvr);
}
Esempio n. 4
0
int
photoproc(struct tstat *tasklist, int maxtask)
{
	static int			firstcall = 1;
	static unsigned long long	bootepoch;

	register struct tstat	*curtask;

	FILE		*fp;
	DIR		*dirp;
	struct dirent	*entp;
	char		origdir[1024];
	int		tval=0;

	/*
	** one-time initialization stuff
	*/
	if (firstcall)
	{
		/*
		** check if this kernel offers io-statistics per task
		*/
		regainrootprivs();

		if ( (fp = fopen("/proc/1/io", "r")) )
		{
			supportflags |= IOSTAT;
			fclose(fp);
		}

		if (! droprootprivs())
			cleanstop(42);

		/*
 		** find epoch time of boot moment
		*/
		bootepoch = getboot();

		firstcall = 0;
	}

	/*
	** probe if the netatop module and (optionally) the
	** netatopd daemon are active
	*/
	regainrootprivs();

	netatop_probe();

	if (! droprootprivs())
		cleanstop(42);

	/*
	** read all subdirectory-names below the /proc directory
	*/
	if ( getcwd(origdir, sizeof origdir) == NULL)
		cleanstop(53);

	if ( chdir("/proc") == -1)
		cleanstop(53);

	dirp = opendir(".");

	while ( (entp = readdir(dirp)) && tval < maxtask )
	{
		/*
		** skip non-numerical names
		*/
		if (!isdigit(entp->d_name[0]))
			continue;

		/*
		** change to the process' subdirectory
		*/
		if ( chdir(entp->d_name) != 0 )
			continue;

		/*
 		** gather process-level information
		*/
		curtask	= tasklist+tval;

		if ( !procstat(curtask, bootepoch, 1)) /* from /proc/pid/stat */
		{
			if ( chdir("..") == -1);
			continue;
		}

		if ( !procstatus(curtask) )	    /* from /proc/pid/status  */
		{
			if ( chdir("..") == -1);
			continue;
		}

		if ( !procio(curtask) )		    /* from /proc/pid/io      */
		{
			if ( chdir("..") == -1);
			continue;
		}

		proccmd(curtask);		    /* from /proc/pid/cmdline */

		// read network stats from netatop
		netatop_gettask(curtask->gen.tgid, 'g', curtask);

		tval++;		/* increment for process-level info */

		/*
 		** if needed (when number of threads is larger than 0):
		**   read and fill new entries with thread-level info
		*/
		if (curtask->gen.nthr > 1)
		{
			DIR		*dirtask;
			struct dirent	*tent;

			curtask->gen.nthrrun  = 0;
			curtask->gen.nthrslpi = 0;
			curtask->gen.nthrslpu = 0;
			
			/*
			** open underlying task directory
			*/
			if ( chdir("task") == 0 )
			{
				dirtask = opendir(".");
	
				while ((tent=readdir(dirtask)) && tval<maxtask)
				{
					struct tstat *curthr = tasklist+tval;

					/*
					** change to the thread's subdirectory
					*/
					if ( tent->d_name[0] == '.'  ||
					     chdir(tent->d_name) != 0 )
						continue;

					if ( !procstat(curthr, bootepoch, 0))
					{
						if ( chdir("..") == -1);
						continue;
					}
			
					if ( !procstatus(curthr) )
					{
						if ( chdir("..") == -1);
						continue;
					}

					if ( !procio(curthr) )
					{
						if ( chdir("..") == -1);
						continue;
					}

					switch (curthr->gen.state)
					{
	   		   		   case 'R':
						curtask->gen.nthrrun  += 1;
						break;
	   		   		   case 'S':
						curtask->gen.nthrslpi += 1;
						break;
	   		   		   case 'D':
						curtask->gen.nthrslpu += 1;
						break;
					}

					curthr->gen.nthr = 1;

					// read network stats from netatop
					netatop_gettask(curthr->gen.pid, 't',
									curthr);

					// all stats read now
					tval++;	    /* increment thread-level */
					if ( chdir("..") == -1); /* thread */
				}

				closedir(dirtask);
				if ( chdir("..") == -1); /* leave task */
			}
		}

		if ( chdir("..") == -1); /* leave process-level directry */
	}

	closedir(dirp);

	if ( chdir(origdir) == -1)
		cleanstop(53);

	return tval;
}
Esempio n. 5
0
/*
** The engine() drives the main-loop of the program
*/
static void
engine(void)
{
	struct sigaction 	sigact;
	static time_t		timelimit;
	void			getusr1(int), getusr2(int);

	/*
	** reserve space for system-level statistics
	*/
	static struct sstat	*cursstat; /* current   */
	static struct sstat	*presstat; /* previous  */
	static struct sstat	*devsstat; /* deviation */
	static struct sstat	*hlpsstat;

	/*
	** reserve space for process-level statistics
	*/
	static struct pstat	*curpact;	/* current active list  */
	static int		curplen;	/* current active size  */

	struct pstat		*curpexit;	/* exitted process list	*/
	struct pstat		*devpstat;	/* deviation list	*/

	int			npresent, nexit, n;
	int			ntrun, ntslpi, ntslpu, nzombie;

	/*
	** initialization: allocate required memory dynamically
	*/
	cursstat = calloc(1, sizeof(struct sstat));
	presstat = calloc(1, sizeof(struct sstat));
	devsstat = calloc(1, sizeof(struct sstat));

	curplen = countprocs() + PROCCHUNK;
	curpact = calloc(curplen, sizeof(struct pstat));

	if (!cursstat || !presstat || !devsstat || !curpact)
	{
		fprintf(stderr, "unexpected calloc-failure...\n");
		cleanstop(1);
	}

	/*
	** install the signal-handler for ALARM, USR1 and USR2 (triggers
	* for the next sample)
	*/
	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr1;
	sigaction(SIGUSR1, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr2;
	sigaction(SIGUSR2, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getalarm;
	sigaction(SIGALRM, &sigact, (struct sigaction *)0);

	if (interval > 0)
		alarm(interval);

	if (midnightflag)
	{
		time_t		timenow = time(0);
		struct tm	*tp = localtime(&timenow);

		tp->tm_hour = 23;
		tp->tm_min  = 59;
		tp->tm_sec  = 59;

		timelimit = mktime(tp);
	}

	/*
	** MAIN-LOOP:
	**    -	Wait for the requested number of seconds or for other trigger
	**
	**    -	System-level counters
	**		get current counters
	**		calculate the differences with the previous sample
	**
	**    -	Process-level counters
	**		get current counters from running & exited processes
	**		calculate the differences with the previous sample
	**
	**    -	Call the print-function to visualize the differences
	*/
	for (sampcnt=0; sampcnt < nsamples; sampcnt++)
	{
		char	lastcmd;

		/*
		** if the limit-flag is specified:
		**  check if the next sample is expected before midnight;
		**  if not, stop atop now 
		*/
		if (midnightflag && (curtime+interval) > timelimit)
			break;

		/*
		** wait for alarm-signal to arrive (except first sample)
		** or wait for SIGUSR1/SIGUSR2
		*/
		if (sampcnt > 0 && awaittrigger)
			pause();

		awaittrigger = 1;

		/*
		** gather time info for this sample
		*/
		pretime  = curtime;
		curtime  = time(0);		/* seconds since 1-1-1970 */

		/*
		** take a snapshot of the current system-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		*/
		hlpsstat = cursstat;	/* swap current/prev. stats */
		cursstat = presstat;
		presstat = hlpsstat;

		photosyst(cursstat);	/* obtain new counters      */

		deviatsyst(cursstat, presstat, devsstat);

		/*
		** take a snapshot of the current process-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		**
		** first register active processes
		**  --> atop malloc's a minimal amount of space which is
		**      only extended when needed
		*/
		memset(curpact, 0, curplen * sizeof(struct pstat));

		while ( (npresent = photoproc(curpact, curplen)) == curplen)
		{
			curplen = countprocs() + PROCCHUNK;

			curpact = realloc(curpact,
			                   curplen * sizeof(struct pstat));

			memset(curpact, 0, curplen * sizeof(struct pstat));
		}

		/*
		** register processes which exited during last sample;
		** first determine how many processes exited and
		** reserve space for them, and secondly obtain the info
		*/
		nexit = acctprocnt();	/* number of exited processes */

		if (nexit > 0)	
		{
			curpexit = malloc(  nexit * sizeof(struct pstat));
			memset(curpexit, 0, nexit * sizeof(struct pstat));

			acctphotoproc(curpexit, nexit);
		}
		else
			curpexit = NULL;

		/*
		** calculate deviations
		*/
		devpstat = malloc((npresent+nexit) * sizeof(struct pstat));

		n = deviatproc(curpact, npresent, curpexit, nexit,
				deviatonly, devpstat, devsstat,
				&ntrun, &ntslpi, &ntslpu, &nzombie);

		/*
		** activate the installed print-function to visualize
		** the deviations
		*/
		lastcmd = (vis.show_samp)( curtime,
				     curtime-pretime > 0 ? curtime-pretime : 1,
		           	     devsstat, devpstat, n, npresent,
		                     ntrun, ntslpi, ntslpu, nzombie,
		                     nexit, sampcnt==0);

		/*
		** release dynamically allocated memory
		*/
		if (nexit > 0)
			free(curpexit);

		free(devpstat);

		if (lastcmd == 'r')	/* reset requested ? */
		{
			sampcnt = -1;

			curtime = getboot();	/* reset current time */

			/* set current (will be 'previous') counters to 0 */
			memset(cursstat, 0,           sizeof(struct sstat));
			memset(curpact,  0, curplen * sizeof(struct pstat));

			/* remove all processes in process database */
			pdb_makeresidue();
			pdb_cleanresidue();
		}
	} /* end of main-loop */
}