
/*
 *  procs.c -- routines to get the currently running process list
 *
 *  options:
 *  -DBSD		use bsd process routines
 *  -D_AIX		use ibm aix process routines
 *  -DSOLARIS		use solaris /proc filesystem
 *  -D__linux__		use linux /proc filesystem
 *
 */

struct cl_proc {
  int pid;
  int uid;
};

#define MAXPROCS 1024

#include <sys/types.h>
#include <sys/param.h>

#ifdef BSD4_4

#include <stdio.h>
#include <fcntl.h>
#include <kvm.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/sysctl.h>

struct cl_proc *get_processes()
{
    static struct cl_proc procs[MAXPROCS];
    kvm_t *kd;
    struct kinfo_proc *kprocs;
    int count, i, j;

    kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "cleanup");
    if (!kd)
	return(NULL);
    kprocs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count);
    if (!kprocs) {
	fprintf(stderr, "cleanup: can't read processes: %s\n", kvm_geterr(kd));
	return(NULL);
    }

    j = 0;
    for (i = 0; i < count && j < MAXPROCS - 1; i++) {
	if (kprocs[i].kp_proc.p_pid <= 2)
	    continue;
	procs[j].pid = kprocs[i].kp_proc.p_pid;
	procs[j].uid = kprocs[i].kp_eproc.e_pcred.p_ruid;
	j++;
    }

    kvm_close(kd);
    procs[j].pid = procs[j].uid = -1;
    return(procs);
}

#endif

#if defined(BSD) && !defined(BSD4_4)

#include <stdio.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <nlist.h>

#if BSD >= 199306
#include <paths.h>
#endif
#ifndef _PATH_UNIX
#define _PATH_UNIX "/vmunix"
#endif
#ifndef _PATH_KMEM
#define _PATH_KMEM "/dev/kmem"
#endif

struct nlist nl[] =
{
#define PROC 0
  { "_proc0" },
#define NPROC 1
  { "_nprocs" },
  { ""}
};

struct cl_proc *get_processes()
{
    int kmem, nproc, i;
    caddr_t procp;
    struct proc p;
    struct pcred pcr;
    static struct cl_proc procs[MAXPROCS];
    char *kernel = _PATH_UNIX;
    char *memory = _PATH_KMEM;

    if (nlist(kernel, nl) != 0) {
	fprintf(stderr, "cleanup: can't get kernel namelist\n");
	return(NULL);
    }
    kmem = open(memory, O_RDONLY);
    if (kmem < 0) {
        fprintf(stderr, "cleanup: can't open ");
	perror(memory);
	return(NULL);
    }
    lseek(kmem, nl[NPROC].n_value, L_SET);
    read(kmem, &nproc, sizeof(nproc));

    lseek(kmem, nl[PROC].n_value, L_SET);
    read(kmem, &procp, sizeof(procp));

    lseek(kmem, (off_t)procp, L_SET);
    for (i = 0; i < nproc; i++) {
	read(kmem, &p, sizeof(p));
	if (p.p_pid == 0 || p.p_pid == 1 || p.p_pid == 2)
	    continue;			/* no killing of system processes */
	procs[i].pid = p.p_pid;
	lseek(kmem, (off_t)p.p_cred, L_SET);
	read(kmem, &pcr, sizeof(pcr));
	procs[i].uid = pcr.p_ruid;
    }
    close(kmem);
    procs[i].pid = procs[i].uid = -1;
    return(procs);
}

#endif /* BSD */

#ifdef _AIX

struct cl_proc *get_processes()
{
    int kmem, nproc, i;
    caddr_t procp;
    struct proc p;
    static struct cl_proc procs[MAXPROCS];
    char *kernel = "/unix";
    char *memory = "/dev/kmem";

    if (nlist(kernel, nl) != 0) {
	fprintf(stderr, "cleanup: can't get kernel namelist\n");
	return(NULL);
    }
    kmem = open(memory, O_RDONLY);
    if (kmem < 0) {
	fprintf(stderr, "cleanup: can't open %s: %s\n", memory,
		sys_errlist[errno]);
	return(NULL);
    }
    nproc = (nl[MAX_PROC].n_value - nl[PROC].n_value) /
      sizeof(nl[MAX_PROC].n_value);

    lseek(kmem, nl[PROC].n_value, L_SET);
    read(kmem, &procp, sizeof(procp));

    lseek(kmem, ((int)procp & 0x7fffffff), L_SET);
    for (i = 0; i < nproc; i++) {
        readx(kmem, &p, sizeof(p), 1);
	if (p.p_pid == 0) continue;
	if (p.p_stat == SNONE) continue;
	procs[i].pid = p.p_pid;
	procs[i].uid = p.p_uid;
    }
    close(kmem);
    procs[i].pid = procs[i].uid = -1;
    return(procs);
}

#endif /* _AIX */

#ifdef SOLARIS

struct cl_proc *get_processes()
{
    int kmem, nproc, i;
    caddr_t procp;
    struct proc  *p;
    static struct cl_proc procs[MAXPROCS];
    char *kernel = "/dev/ksyms";
    kvm_t *kv;
    int j,pid;
    DIR *dirp;
    struct dirent *dp;
    char *memory = "/dev/kmem";

    kv = kvm_open(NULL,NULL,NULL,O_RDONLY,NULL);
    if (kvm_nlist(kv, &nl) < 0) {
      fprintf(stderr,"cleanup: can't get namelist\n");
      exit(2);
    }
    kvm_read(kv,nl[PROC].n_value,&nproc,sizeof(nproc));
    (void) kvm_setproc(kv);
    i=0;
    dirp = opendir("/proc");
    for (j=0;j<2;j++) dp = readdir(dirp);
    for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
      sscanf(dp->d_name,"%d",&pid);
      p = kvm_getproc(kv,pid);
      if ( p != NULL ) {
	if (p->p_epid == 0)
	  continue;
	else {
	  procs[i].pid = p->p_epid;
	  procs[i].uid = p->p_uid;
	  i++;
	}
      }
    }
    kvm_close(kv);
    procs[i].pid = procs[i].uid = -1;
    return(procs);
}

#endif /* SOLARIS */

#ifdef __linux__

#define _POSIX_SOURCE 1

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>

struct cl_proc *get_processes (int get_all, uid_t get_uid)
{
  DIR *dir;
  struct dirent *ent;
  static struct cl_proc procs[MAXPROCS];
  int size, status, pid, uid;
  char *dname, fname[100];
  struct stat st;

  dir = opendir ("/proc");
  if (! dir) {
    perror ("opendir /proc");
    return NULL;
  }
  size = 0;
  while ((ent = readdir (dir)) != NULL) {
    dname = ent->d_name;
    if (! isdigit (*dname)) continue;
    pid = atoi (dname);
    sprintf (fname, "/proc/%d/cmdline", pid);
    /* get the process owner */
    status = stat (fname, &st);
    if (status != 0) continue;
    uid = st.st_uid;
    /* add the process to the process array */
    procs[size].pid = pid;
    procs[size].uid = uid;
    size++;
  }
  closedir (dir);
  procs[size].pid = procs[size].uid = (-1);
  return procs;
}

#endif /* __linux__ */
