Blame sysdeps/solaris/proclist.c

Packit d37888
/* Copyright (C) 1998-99 Martin Baulig
Packit d37888
   This file is part of LibGTop 1.0.
Packit d37888
Packit d37888
   Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998.
Packit d37888
Packit d37888
   LibGTop is free software; you can redistribute it and/or modify it
Packit d37888
   under the terms of the GNU General Public License as published by
Packit d37888
   the Free Software Foundation; either version 2 of the License,
Packit d37888
   or (at your option) any later version.
Packit d37888
Packit d37888
   LibGTop is distributed in the hope that it will be useful, but WITHOUT
Packit d37888
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit d37888
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit d37888
   for more details.
Packit d37888
Packit d37888
   You should have received a copy of the GNU General Public License
Packit d37888
   along with LibGTop; see the file COPYING. If not, write to the
Packit d37888
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d37888
   Boston, MA 02110-1301, USA.
Packit d37888
*/
Packit d37888
Packit d37888
#include <config.h>
Packit d37888
#include <glibtop.h>
Packit d37888
#include <glibtop/proclist.h>
Packit d37888
Packit d37888
#include "safeio.h"
Packit d37888
#include "glibtop_private.h"
Packit d37888
Packit d37888
#include <sys/stat.h>
Packit d37888
#include <unistd.h>
Packit d37888
#include <dirent.h>
Packit d37888
#include <ctype.h>
Packit d37888
Packit d37888
#define GLIBTOP_PROCLIST_FLAGS	3
Packit d37888
Packit d37888
static const unsigned long _glibtop_sysdeps_proclist =
Packit d37888
(1L << GLIBTOP_PROCLIST_TOTAL) + (1L << GLIBTOP_PROCLIST_NUMBER) +
Packit d37888
(1L << GLIBTOP_PROCLIST_SIZE);
Packit d37888
Packit d37888
/* Init function. */
Packit d37888
Packit d37888
void
Packit d37888
_glibtop_init_proclist_s (glibtop *server)
Packit d37888
{
Packit d37888
	server->sysdeps.proclist = _glibtop_sysdeps_proclist;
Packit d37888
}
Packit d37888
Packit d37888
#define BLOCK_COUNT	256
Packit d37888
#define BLOCK_SIZE	(BLOCK_COUNT * sizeof (pid_t))
Packit d37888
Packit d37888
/* Fetch list of currently running processes.
Packit d37888
 *
Packit d37888
 * IMPORTANT NOTE:
Packit d37888
 *   On error, this function MUST return NULL and set buf->flags to zero !
Packit d37888
 *   On success, it returnes a pointer to a list of buf->number elements
Packit d37888
 *   each buf->size big. The total size is stored in buf->total. */
Packit d37888
Packit d37888
pid_t*
Packit d37888
glibtop_get_proclist_s (glibtop *server, glibtop_proclist *buf,
Packit d37888
			gint64 which, gint64 arg)
Packit d37888
{
Packit d37888
	DIR *proc;
Packit d37888
	struct dirent *entry;
Packit d37888
	char buffer [BUFSIZ];
Packit d37888
	unsigned count, total, pid = 0, mask;
Packit d37888
	pid_t pids [BLOCK_COUNT], *pids_chain = NULL;
Packit d37888
	unsigned pids_size = 0, pids_offset = 0, new_size;
Packit d37888
	struct stat statb;
Packit d37888
	int len, ok;
Packit d37888
Packit d37888
	memset (buf, 0, sizeof (glibtop_proclist));
Packit d37888
	mask = which & ~GLIBTOP_KERN_PROC_MASK;
Packit d37888
	which &= GLIBTOP_KERN_PROC_MASK;
Packit d37888
Packit d37888
	/* Check if the user wanted only one process */
Packit d37888
Packit d37888
	if(which == GLIBTOP_KERN_PROC_PID)
Packit d37888
	{
Packit d37888
	   if(mask)
Packit d37888
	   {
Packit d37888
#ifdef HAVE_PROCFS_H
Packit d37888
	      struct psinfo psinfo;
Packit d37888
#else
Packit d37888
	      struct prpsinfo psinfo;
Packit d37888
#endif
Packit d37888
	      if(glibtop_get_proc_data_psinfo_s(server, &psinfo, pid))
Packit d37888
		 return NULL;
Packit d37888
	      if(mask & GLIBTOP_EXCLUDE_IDLE && !psinfo.pr_pctcpu)
Packit d37888
		 return NULL;
Packit d37888
	      if(mask & GLIBTOP_EXCLUDE_SYSTEM && psinfo.pr_flag & SSYS)
Packit d37888
		 return NULL;
Packit d37888
	      if(mask & GLIBTOP_EXCLUDE_NOTTY && psinfo.pr_ttydev == PRNODEV)
Packit d37888
		 return NULL;
Packit d37888
	   }
Packit d37888
	   else
Packit d37888
	   {
Packit d37888
	      sprintf(buffer, "/proc/%lld", arg);
Packit d37888
	      if(s_stat(buffer, &statb) < 0)
Packit d37888
		 return NULL;
Packit d37888
	   }
Packit d37888
	   pids_chain = g_malloc(sizeof(pid_t));
Packit d37888
	   *pids_chain = pid;
Packit d37888
	   return pids_chain;
Packit d37888
	}
Packit d37888
Packit d37888
	proc = opendir ("/proc");
Packit d37888
	if (!proc) return NULL;
Packit d37888
Packit d37888
	/* read every every entry in /proc */
Packit d37888
Packit d37888
	for (count = total = 0, entry = readdir (proc);
Packit d37888
	     entry; entry = readdir (proc)) {
Packit d37888
		ok = 1; len = strlen (entry->d_name);
Packit d37888
Packit d37888
		/* does it consist entirely of digits? */
Packit d37888
		/* It does, except for "." and "..". Let's speed up */
Packit d37888
Packit d37888
		if(entry->d_name[0] == '.')
Packit d37888
		   continue;
Packit d37888
Packit d37888
		/* convert it in a number */
Packit d37888
		pid = (unsigned)atol(entry->d_name);
Packit d37888
Packit d37888
#ifdef HAVE_PROCFS_H
Packit d37888
Packit d37888
		/* Can we skip it based on the request? We have
Packit d37888
		   RUID and RGID in struct stat. But we can't do it
Packit d37888
		   like this for LP64 process, because stat() will fail.
Packit d37888
		   XXX Unimplemented for now */
Packit d37888
Packit d37888
		if(!mask && which == GLIBTOP_KERN_PROC_RUID)
Packit d37888
		{
Packit d37888
		   sprintf (buffer, "/proc/%d", pid);
Packit d37888
		   if (s_stat (buffer, &statb)) continue;
Packit d37888
Packit d37888
		   if (!S_ISDIR (statb.st_mode)) continue;
Packit d37888
Packit d37888
		   if(statb.st_uid != arg) continue;
Packit d37888
		}
Packit d37888
Packit d37888
		if(mask || which != GLIBTOP_KERN_PROC_ALL)
Packit d37888
		{
Packit d37888
		   struct psinfo psinfo;
Packit d37888
Packit d37888
		   if(glibtop_get_proc_data_psinfo_s(server, &psinfo, pid))
Packit d37888
		      continue;
Packit d37888
		   if(mask)
Packit d37888
		   {
Packit d37888
		      if(mask & GLIBTOP_EXCLUDE_IDLE && !psinfo.pr_pctcpu)
Packit d37888
			 continue;
Packit d37888
		      if(mask & GLIBTOP_EXCLUDE_SYSTEM && psinfo.pr_flag & SSYS)
Packit d37888
			 continue;
Packit d37888
		      if(mask & GLIBTOP_EXCLUDE_NOTTY
Packit d37888
			 && psinfo.pr_ttydev == PRNODEV)
Packit d37888
			 continue;
Packit d37888
		   }
Packit d37888
		   switch(which)
Packit d37888
		   {
Packit d37888
		      case GLIBTOP_KERN_PROC_PGRP:    if(psinfo.pr_pgid != arg)
Packit d37888
						         continue;
Packit d37888
						      break;
Packit d37888
		      case GLIBTOP_KERN_PROC_SESSION: if(psinfo.pr_sid != arg)
Packit d37888
							 continue;
Packit d37888
						      break;
Packit d37888
		      case GLIBTOP_KERN_PROC_TTY:    if(psinfo.pr_ttydev != arg)
Packit d37888
						         continue;
Packit d37888
						      break;
Packit d37888
		      case GLIBTOP_KERN_PROC_UID:     if(psinfo.pr_euid != arg)
Packit d37888
							 continue;
Packit d37888
						      break;
Packit d37888
		      case GLIBTOP_KERN_PROC_RUID:    if(psinfo.pr_uid != arg)
Packit d37888
						         continue;
Packit d37888
						      break;
Packit d37888
		      default:			      break;
Packit d37888
		   }
Packit d37888
		}
Packit d37888
#endif
Packit d37888
		/* Fine. Now we first try to store it in pids. If this buffer is
Packit d37888
		 * full, we copy it to the pids_chain. */
Packit d37888
Packit d37888
		if (count >= BLOCK_COUNT) {
Packit d37888
			/* The following call to g_realloc will be
Packit d37888
			 * equivalent to g_malloc () if `pids_chain' is
Packit d37888
			 * NULL. We just calculate the new size and copy `pids'
Packit d37888
			 * to the beginning of the newly allocated block. */
Packit d37888
Packit d37888
			new_size = pids_size + BLOCK_SIZE;
Packit d37888
Packit d37888
			pids_chain = g_realloc (pids_chain, new_size);
Packit d37888
Packit d37888
			memcpy (pids_chain + pids_offset, pids, BLOCK_SIZE);
Packit d37888
Packit d37888
			pids_size = new_size;
Packit d37888
Packit d37888
			pids_offset += BLOCK_COUNT;
Packit d37888
Packit d37888
			count = 0;
Packit d37888
		}
Packit d37888
Packit d37888
		/* pids is now big enough to hold at least one single pid. */
Packit d37888
Packit d37888
		pids [count++] = pid;
Packit d37888
Packit d37888
		total++;
Packit d37888
	}
Packit d37888
Packit d37888
	s_closedir (proc);
Packit d37888
Packit d37888
	/* count is only zero if an error occured (one a running Linux system,
Packit d37888
	 * we have at least one single process). */
Packit d37888
Packit d37888
	if (!count) return NULL;
Packit d37888
Packit d37888
	/* The following call to g_realloc will be equivalent to
Packit d37888
	 * g_malloc if pids_chain is NULL. We just calculate the
Packit d37888
	 * new size and copy pids to the beginning of the newly allocated
Packit d37888
	 * block. */
Packit d37888
Packit d37888
	new_size = pids_size + count * sizeof (pid_t);
Packit d37888
Packit d37888
	pids_chain = g_realloc (pids_chain, new_size);
Packit d37888
Packit d37888
	memcpy (pids_chain + pids_offset, pids, count * sizeof (pid_t));
Packit d37888
Packit d37888
	pids_size = new_size;
Packit d37888
Packit d37888
	pids_offset += BLOCK_COUNT;
Packit d37888
Packit d37888
	/* Since everything is ok now, we can set buf->flags, fill in the
Packit d37888
	 * remaining fields and return the `pids_chain'. */
Packit d37888
Packit d37888
	buf->flags = _glibtop_sysdeps_proclist;
Packit d37888
Packit d37888
	buf->size = sizeof (pid_t);
Packit d37888
	buf->number = total;
Packit d37888
Packit d37888
	buf->total = buf->number * buf->size;
Packit d37888
Packit d37888
	return pids_chain;
Packit d37888
}