252N/A/*
2728N/A * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
252N/A *
252N/A * U.S. Government Rights - Commercial software. Government users are subject
252N/A * to the Sun Microsystems, Inc. standard license agreement and applicable
252N/A * provisions of the FAR and its supplements.
252N/A *
252N/A *
252N/A * This distribution may include materials developed by third parties. Sun,
252N/A * Sun Microsystems, the Sun logo and Solaris are trademarks or registered
252N/A * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
252N/A *
252N/A */
252N/A/*
252N/A * Note: this file originally auto-generated by mib2c using
252N/A * : mib2c.iterate.conf,v 5.5 2002/12/16 22:50:18 hardaker Exp $
252N/A */
252N/A
252N/A#include <net-snmp/net-snmp-config.h>
252N/A#include <net-snmp/net-snmp-includes.h>
252N/A#include <net-snmp/agent/net-snmp-agent-includes.h>
252N/A#include "sunProcesses.h"
252N/A
252N/A#include <stdio.h>
252N/A#include <errno.h>
252N/A#include <sys/types.h>
2728N/A#include <procfs.h>
252N/A#include <sys/fcntl.h>
252N/A#include <sys/stat.h>
252N/A#include <sys/time.h>
252N/A#include <sys/mntent.h>
252N/A#include <sys/mnttab.h>
252N/A#include <ftw.h>
252N/A#include <stdlib.h>
252N/A#include <dirent.h>
252N/A#include <string.h>
252N/A#include <memory.h>
252N/A#include <pwd.h>
252N/A#include <syslog.h>
252N/A
252N/A#include "snmpvars.h"
252N/A#include "agent.h"
252N/A#include "asn1.h"
252N/A
252N/A/* The following code is borrowed from ps.c */
252N/A#define NUID 64
252N/A#define TRUE 1
252N/A#define FALSE 0
252N/A
252N/A#define NTTYS 20 /* max ttys that can be specified with the -t option */
252N/A#define SIZ 30 /* max processes that can be specified with -p and -g */
252N/A#define ARGSIZ 30 /* size of buffer holding args for -t, -p, -u options */
252N/A
252N/A#define FSTYPE_MAX 8
252N/A
252N/A#ifndef MAXLOGIN
252N/A#define MAXLOGIN 8 /* max number of chars in login that will be printed */
252N/A#endif
252N/A
252N/A#define UDQ 50
252N/A
252N/A
2728N/Astatic struct psinfo info; /* process information structure from /proc */
252N/A
252N/Achar *ttyname();
252N/Astatic char *psfile = "/tmp/mibiisa_ps_data";
252N/A
252N/A
252N/Astatic int ndev; /* number of devices */
252N/Astatic int maxdev; /* number of devl structures allocated */
252N/A
252N/A#define DNSIZE 14
252N/Astatic struct devl { /* device list */
252N/A char dname[DNSIZE]; /* device name */
252N/A dev_t dev; /* device number */
252N/A} *devl = NULL;
252N/A
252N/Astatic char *procdir = "/proc"; /* standard /proc directory */
252N/Astatic int rd_only = 0; /* flag for remote filesystem read-only */
252N/Avoid usage(); /* print usage message and quit */
252N/A
252N/Astatic time_t ps_cache_time = 0;
252N/Atime_t cache_now = 0;
252N/Aint cache_lifetime = 45;
252N/A
252N/Astatic void call_ftw_for_dev(void);
252N/Astatic void wrdata();
252N/Astatic void write_tmp_file();
252N/Astatic int isprocdir();
252N/Astatic void get_ps_data(void);
252N/Astatic void clean_ps(ps_ldata_t *);
252N/Astatic char *get_usr_name(uid_t);
252N/Astatic ps_data_t *find_ps_data(pid_t pid);
252N/Astatic void pr_ps(void);
252N/A
252N/Aps_data_t *pstable = PS_NULL;
252N/Aint pstable_lines = 0; /* # of items in memory block pointed */
252N/A /* to by pstable. */
252N/A
252N/Astatic void
252N/Aclean_ps(ps_ldata_t *head)
252N/A{
252N/A if (head != PS_LNULL) {
252N/A ps_ldata_t *pdp;
252N/A ps_ldata_t *nxt;
252N/A for (pdp = head; pdp != PS_LNULL; pdp = nxt) {
252N/A nxt = pdp->link;
252N/A free(pdp);
252N/A }
252N/A }
252N/A}
252N/A
252N/Astatic int
252N/Apscomp(ps_data_t *i, ps_data_t *j)
252N/A{
252N/A return (i->pid - j->pid);
252N/A}
252N/A
252N/Astatic struct ncache {
252N/A uid_t uid;
252N/A char name[USRNM_SZ+1];
252N/A} nc[NUID];
252N/A
252N/A/*
252N/A * This function assumes that the password file is hashed
252N/A * (or some such) to allow fast access based on a uid key.
252N/A */
252N/Astatic char *
252N/Aget_usr_name(uid_t uid)
252N/A{
252N/A struct passwd *pw;
252N/A int cp;
252N/A
252N/A#if (((NUID) & ((NUID) - 1)) != 0)
252N/Acp = uid % (NUID);
252N/A#else
252N/Acp = uid & ((NUID) - 1);
252N/A#endif
252N/A if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0])
252N/A return (nc[cp].name);
252N/A pw = getpwuid(uid);
252N/A if (!pw)
252N/A return ((char *)0);
252N/A nc[cp].uid = uid;
252N/A strncpy(nc[cp].name, pw->pw_name, USRNM_SZ);
252N/A
252N/A return (nc[cp].name);
252N/A}
252N/A
252N/Avoid
252N/Apr_ps(void)
252N/A{
252N/A ps_data_t *psp;
252N/A int lines;
252N/A
252N/A printf("%d entries\n", pstable_lines);
252N/A printf("UID PID PPID SZ USR WCHAN TTY CPU CMD \n\n");
252N/A
252N/A for (psp = pstable, lines = 0; lines < pstable_lines; psp++, lines++) {
252N/A printf("%d %u %u %d %s %s %s %d %s\n",
252N/A psp->uid,
252N/A psp->pid,
252N/A psp->ppid,
252N/A psp->sz,
252N/A psp->usrname,
252N/A psp->wchan,
252N/A psp->tty,
252N/A psp->cpu,
252N/A psp->cmd);
252N/A }
252N/A}
252N/A
252N/A/*
252N/A * Locate a particular PID.
252N/A * Return a pointer to the entry or NULL if not found.
252N/A */
252N/Astatic ps_data_t * find_ps_data(pid_t pid)
252N/A{
252N/A ps_data_t *psp;
252N/A ps_data_t key;
252N/A
252N/A key.pid = pid;
252N/A
252N/A /* Should add a cache here */
252N/A
252N/A psp = (ps_data_t *)bsearch((char *)&key, (char *)pstable,
252N/A pstable_lines, sizeof (ps_data_t),
252N/A (int (*)())pscomp);
252N/A return (psp);
252N/A}
252N/A
252N/A
252N/Avoid
252N/Aget_ps_data(void)
252N/A{
252N/A ps_ldata_t *ps_last = PS_LNULL;
252N/A ps_ldata_t *ps_head = PS_LNULL;
252N/A ps_ldata_t *psp;
252N/A ps_data_t *pstp;
252N/A static char *usrname;
252N/A int i = 0;
252N/A DIR *dirp;
252N/A struct dirent *dentp;
252N/A char pname[MAXNAMELEN];
252N/A int pdlen;
252N/A char *gettty();
252N/A
252N/A if (pstable != PS_NULL) { /* Don't run ps unless we need to */
252N/A if ((cache_now - ps_cache_time) <= cache_lifetime)
252N/A return;
252N/A free(pstable);
252N/A }
252N/A
252N/A pstable_lines = 0;
252N/A ps_cache_time = cache_now;
252N/A /*
252N/A * Determine root path for remote machine.
252N/A */
252N/A if (!readata()) { /* get data from psfile */
252N/A call_ftw_for_dev();
252N/A wrdata();
252N/A }
252N/A
252N/A /*
252N/A * Determine which processes to print info about by searching
252N/A * the /proc directory and looking at each process.
252N/A */
252N/A if ((dirp = opendir(procdir)) == NULL) {
252N/A (void) SYSLOG0("Cannot open PROC directory\n");
252N/A return;
252N/A }
252N/A
252N/A (void) strcpy(pname, procdir);
252N/A pdlen = strlen(pname);
252N/A pname[pdlen++] = '/';
252N/A
252N/A /* for each active process --- */
252N/A while (dentp = readdir(dirp)) {
252N/A int procfd;
252N/A
252N/A if (dentp->d_name[0] == '.') /* skip . and .. */
252N/A continue;
252N/A (void) strcpy(pname + pdlen, dentp->d_name);
2728N/A (void) strcat(pname + pdlen, "/psinfo");
252N/Aretry:
252N/A if ((procfd = open(pname, O_RDONLY)) == -1)
252N/A continue;
252N/A
252N/A /*
252N/A * Get the info structure for the process and close quickly.
252N/A */
2728N/A if (read(procfd, &info, sizeof (info)) != sizeof (info)) {
252N/A int saverr = errno;
252N/A
252N/A (void) close(procfd);
252N/A if (saverr == EAGAIN)
252N/A goto retry;
252N/A if (saverr != ENOENT)
2728N/A (void) SYSLOG2("read of %s: %s\n",
252N/A pname, strerror(saverr));
252N/A continue;
252N/A }
252N/A (void) close(procfd);
252N/A if ((psp = (ps_ldata_t *)malloc(sizeof (ps_ldata_t))) == PS_LNULL)
252N/A break;
252N/A memset((char *)psp, 0, sizeof (ps_ldata_t));
252N/A psp->pdata.uid = info.pr_uid;
252N/A psp->pdata.pid = info.pr_pid;
252N/A psp->pdata.ppid = info.pr_ppid;
252N/A psp->pdata.sz = info.pr_size;
2728N/A if (info.pr_lwp.pr_wchan)
2728N/A sprintf(psp->pdata.wchan, "%9x", info.pr_lwp.pr_wchan);
252N/A else
252N/A strcpy(psp->pdata.wchan, " ");
252N/A memset(&psp->pdata.stat[0], 0, STAT_SZ+1);
2728N/A if (info.pr_lwp.pr_sname)
2728N/A psp->pdata.stat[0] = info.pr_lwp.pr_sname;
252N/A i = 0;
252N/A strcpy(psp->pdata.tty, (char *)gettty(&i));
252N/A psp->pdata.cpu = info.pr_time.tv_sec;
252N/A strcpy(psp->pdata.cmd, info.pr_fname);
252N/A
252N/A if ((usrname = (get_usr_name(psp->pdata.uid))) != NULL)
252N/A strncpy(psp->pdata.usrname, usrname, USRNM_SZ);
252N/A else {
252N/A free(psp);
252N/A continue;
252N/A }
252N/A
252N/A psp->pdata.usrname[USRNM_SZ] = '\0';
252N/A pstable_lines++;
252N/A if (ps_last == PS_LNULL)
252N/A ps_head = psp;
252N/A else
252N/A ps_last->link = psp;
252N/A ps_last = psp;
252N/A }
252N/A
252N/A (void) closedir(dirp);
252N/A if ((pstable = (ps_data_t *)malloc(pstable_lines
252N/A * sizeof (ps_data_t))) == PS_NULL) {
252N/A clean_ps(ps_head);
252N/A return;
252N/A }
252N/A for (pstp = pstable, psp = ps_head; psp != PS_LNULL;
252N/A pstp++, psp = psp->link) {
252N/A memcpy((char *)pstp, (char *)&(psp->pdata), sizeof (ps_data_t));
252N/A }
252N/A clean_ps(ps_head);
252N/A qsort(pstable, pstable_lines, sizeof (ps_data_t), (int (*)())pscomp);
252N/A}
252N/A
252N/Aint
252N/Areadata()
252N/A{
252N/A struct stat sbuf1, sbuf2;
252N/A int fd;
252N/A
252N/A if ((fd = open(psfile, O_RDONLY)) == -1)
252N/A return (0);
252N/A
252N/A if (fstat(fd, &sbuf1) < 0 || sbuf1.st_size == 0 ||
252N/A stat("/dev", &sbuf2) == -1 || sbuf1.st_mtime <= sbuf2.st_mtime ||
252N/A sbuf1.st_mtime <= sbuf2.st_ctime) {
252N/A
252N/A if (!rd_only) { /* if read-only, believe old data */
252N/A (void) close(fd);
252N/A return (0);
252N/A }
252N/A }
252N/A
252N/A /* Read /dev data from psfile. */
252N/A if (read_tmp_file(fd, (char *) &ndev, sizeof (ndev)) == 0) {
252N/A (void) close(fd);
252N/A return (0);
252N/A }
252N/A
252N/A if (devl)
252N/A free(devl);
252N/A
252N/A if ((devl = (struct devl *)malloc(ndev * sizeof (*devl))) == NULL) {
252N/A SYSLOG1("malloc() for device table failed, %s\n", strerror(errno));
252N/A exit(1);
252N/A }
252N/A if (read_tmp_file(fd, (char *)devl, ndev * sizeof (*devl)) == 0) {
252N/A (void) close(fd);
252N/A return (0);
252N/A }
252N/A
252N/A (void) close(fd);
252N/A return (1);
252N/A}
252N/A
252N/A/*
252N/A * call_ftw_for_dev() uses ftw() to pass pathnames under /dev to gdev()
252N/A * along with a status buffer.
252N/A */
252N/Astatic void
252N/Acall_ftw_for_dev(void)
252N/A{
252N/A int gdev();
252N/A int rcode;
252N/A
252N/A ndev = 0;
252N/A rcode = ftw("/dev", gdev, 17);
252N/A
252N/A switch (rcode) {
252N/A case 0:
252N/A return; /* successful return, devl populated */
252N/A case 1:
252N/A SYSLOG0(" ftw() encountered problem\n");
252N/A break;
252N/A case -1:
252N/A SYSLOG1(" ftw() failed, %s\n", strerror(errno));
252N/A break;
252N/A default:
252N/A SYSLOG1(" ftw() unexpected return, rcode=%d\n", rcode);
252N/A break;
252N/A }
252N/A exit(1);
252N/A}
252N/A
252N/A/*
252N/A * gdev() puts device names and ID into the devl structure for character
252N/A * special files in /dev. The "/dev/" string is stripped from the name
252N/A * and if the resulting pathname exceeds DNSIZE in length then the highest
252N/A * level directory names are stripped until the pathname is DNSIZE or less.
252N/A */
252N/Aint
252N/Agdev(objptr, statp, numb)
252N/A char *objptr;
252N/A struct stat *statp;
252N/A int numb;
252N/A{
252N/A int i;
252N/A int leng, start;
252N/A static struct devl ldevl[2];
252N/A static int lndev, consflg;
252N/A
252N/A switch (numb) {
252N/A
252N/A case FTW_F:
252N/A if ((statp->st_mode & S_IFMT) == S_IFCHR) {
252N/A /* Get more and be ready for syscon & systty. */
252N/A while (ndev + lndev >= maxdev) {
252N/A maxdev += UDQ;
252N/A devl = (struct devl *) ((devl == NULL) ?
252N/A malloc(sizeof (struct devl) * maxdev) :
252N/A realloc(devl, sizeof (struct devl) * maxdev));
252N/A if (devl == NULL) {
252N/A SYSLOG1(" not enough memory for %d devices\n", maxdev);
252N/A exit(1);
252N/A }
252N/A }
252N/A /*
252N/A * Save systty & syscon entries if the console
252N/A * entry hasn't been seen.
252N/A */
252N/A if (!consflg && (strcmp("/dev/systty", objptr) == 0 ||
252N/A strcmp("/dev/syscon", objptr) == 0)) {
252N/A (void) strncpy(ldevl[lndev].dname, &objptr[5], DNSIZE);
252N/A ldevl[lndev].dev = statp->st_rdev;
252N/A lndev++;
252N/A return (0);
252N/A }
252N/A
252N/A leng = strlen(objptr);
252N/A /* Strip off /dev/ */
252N/A if (leng < DNSIZE + 4)
252N/A (void) strcpy(devl[ndev].dname, &objptr[5]);
252N/A else {
252N/A start = leng - DNSIZE - 1;
252N/A
252N/A for (i = start; i < leng && (objptr[i] != '/'); i++)
252N/A ;
252N/A if (i == leng)
252N/A (void) strncpy(devl[ndev].dname,
252N/A &objptr[start], DNSIZE);
252N/A else
252N/A (void) strncpy(devl[ndev].dname,
252N/A &objptr[i+1], DNSIZE);
252N/A }
252N/A devl[ndev].dev = statp->st_rdev;
252N/A ndev++;
252N/A /*
252N/A * Put systty & syscon entries in devl when console
252N/A * is found.
252N/A */
252N/A if (strcmp("/dev/console", objptr) == 0) {
252N/A consflg++;
252N/A for (i = 0; i < lndev; i++) {
252N/A (void) strncpy(devl[ndev].dname,
252N/A ldevl[i].dname, DNSIZE);
252N/A devl[ndev].dev = ldevl[i].dev;
252N/A ndev++;
252N/A }
252N/A lndev = 0;
252N/A }
252N/A }
252N/A return (0);
252N/A
252N/A case FTW_D:
252N/A case FTW_DNR:
252N/A case FTW_NS:
252N/A return (0);
252N/A
252N/A default:
252N/A SYSLOG1(" gdev() error, %d, encountered\n", numb);
252N/A return (1);
252N/A }
252N/A}
252N/A
252N/A
252N/Avoid
252N/Awrdata()
252N/A{
252N/A char tmpname[MAXNAMELEN];
252N/A char *tfname;
252N/A int fd;
252N/A
252N/A (void) umask(02);
252N/A (void) strcpy(tmpname, "/tmp/mibiisa_ps.XXXXXX");
252N/A if ((tfname = mktemp(tmpname)) == NULL || *tfname == '\0') {
252N/A SYSLOG1(" mktemp(\"/tmp/mibiisa_ps.XXXXXX\") failed, %s\n",
252N/A strerror(errno));
252N/A return;
252N/A }
252N/A
252N/A if ((fd = open(tfname, O_WRONLY|O_CREAT|O_EXCL, 0664)) < 0) {
252N/A SYSLOG2(" open(\"%s\") for write failed, %s\n",
252N/A tfname, strerror(errno));
252N/A return;
252N/A }
252N/A
252N/A /*
252N/A * Make owner root, group sys.
252N/A */
252N/A (void) chown(tfname, (uid_t)0, (gid_t)3);
252N/A
252N/A /* write /dev data */
252N/A write_tmp_file(fd, (char *) &ndev, sizeof (ndev));
252N/A write_tmp_file(fd, (char *)devl, ndev * sizeof (*devl));
252N/A
252N/A (void) close(fd);
252N/A
252N/A if (rename(tfname, psfile) != 0) {
252N/A SYSLOG2(" rename(\"%s\",\"%s\") failed\n", tfname, psfile);
252N/A return;
252N/A }
252N/A}
252N/A
252N/A/*
252N/A * gettty returns the user's tty number or ? if none.
252N/A */
252N/Achar *
252N/Agettty(ip)
252N/Aint *ip; /* where the search left off last time */
252N/A{
252N/A int i;
252N/A
252N/A if (info.pr_ttydev != PRNODEV && *ip >= 0) {
252N/A for (i = *ip; i < ndev; i++) {
252N/A if (devl[i].dev == info.pr_ttydev) {
252N/A *ip = i + 1;
252N/A return (devl[i].dname);
252N/A }
252N/A }
252N/A }
252N/A *ip = -1;
252N/A return ("?");
252N/A}
252N/A
252N/A/*
252N/A * Special read; unlinks psfile on read error.
252N/A */
252N/Aint
252N/Aread_tmp_file(fd, bp, bs)
252N/A int fd;
252N/A char *bp;
252N/A unsigned int bs;
252N/A{
252N/A int rbs;
252N/A
252N/A if ((rbs = read(fd, bp, bs)) != bs) {
252N/A SYSLOG2("read_tmp_file() error on read, rbs=%d, bs=%d\n",
252N/A rbs, bs);
252N/A (void) unlink(psfile);
252N/A return (0);
252N/A }
252N/A return (1);
252N/A}
252N/A
252N/A/*
252N/A * Special write; unlinks psfile on write error.
252N/A */
252N/Avoid
252N/Awrite_tmp_file(fd, bp, bs)
252N/Aint fd;
252N/Achar *bp;
252N/Aunsigned bs;
252N/A{
252N/A int wbs;
252N/A
252N/A if ((wbs = write(fd, bp, bs)) != bs) {
252N/A SYSLOG2("write_tmp_file() error on write, wbs=%d, bs=%d\n",
252N/A wbs, bs);
252N/A (void) unlink(psfile);
252N/A }
252N/A}
252N/A
252N/A
252N/A/*
252N/A * Return true iff dir is a /proc directory.
252N/A *
252N/A * This works because of the fact that "/proc/0" and "/proc/00" are the
252N/A * same file, namely process 0, and are not linked to each other. Ugly.
252N/A */
252N/Astatic int
252N/Aisprocdir(dir) /* return TRUE iff dir is a PROC directory */
252N/A char *dir;
252N/A{
252N/A struct stat stat1; /* dir/0 */
252N/A struct stat stat2; /* dir/00 */
252N/A char path[200];
252N/A char *p;
252N/A
252N/A /*
252N/A * Make a copy of the directory name without trailing '/'s
252N/A */
252N/A if (dir == NULL)
252N/A (void) strcpy(path, ".");
252N/A else {
252N/A (void) strncpy(path, dir, (int) sizeof (path) - 4);
252N/A path[sizeof (path)-4] = '\0';
252N/A p = path + strlen(path);
252N/A while (p > path && *--p == '/')
252N/A *p = '\0';
252N/A if (*path == '\0')
252N/A (void) strcpy(path, ".");
252N/A }
252N/A
252N/A /*
252N/A * Append "/0" to the directory path and stat() the file.
252N/A */
252N/A p = path + strlen(path);
252N/A *p++ = '/';
252N/A *p++ = '0';
252N/A *p = '\0';
252N/A if (stat(path, &stat1) != 0)
252N/A return (FALSE);
252N/A
252N/A /*
252N/A * Append "/00" to the directory path and stat() the file.
252N/A */
252N/A *p++ = '0';
252N/A *p = '\0';
252N/A if (stat(path, &stat2) != 0)
252N/A return (FALSE);
252N/A
252N/A /*
252N/A * See if we ended up with the same file.
252N/A */
252N/A if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino ||
252N/A stat1.st_mode != stat2.st_mode ||
252N/A stat1.st_nlink != stat2.st_nlink ||
252N/A stat1.st_uid != stat2.st_uid || stat1.st_gid != stat2.st_gid ||
252N/A stat1.st_size != stat2.st_size)
252N/A return (FALSE);
252N/A
252N/A /*
252N/A * Return TRUE iff we have a regular file with a single link.
252N/A */
252N/A return ((stat1.st_mode & S_IFMT) == S_IFREG && stat1.st_nlink == 1);
252N/A}
252N/A
252N/A
252N/A/*
252N/A * Initialize the sunProcessTable table by defining its contents and how
252N/A * it's structured
252N/A */
252N/Avoid initialize_table_sunProcessTable(void) {
252N/A
252N/A static oid sunProcessTable_oid[] = {1, 3, 6, 1, 4, 1, 42, 3, 12};
252N/A netsnmp_table_registration_info *table_info;
252N/A netsnmp_handler_registration *my_handler;
252N/A netsnmp_iterator_info *iinfo;
252N/A
252N/A /* create the table structure itself */
252N/A table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
252N/A iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
252N/A
252N/A /*
252N/A * if your table is read only, it's easiest to change the
252N/A * HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY
252N/A */
252N/A my_handler = netsnmp_create_handler_registration("sunProcessTable",
252N/A sunProcessTable_handler,
252N/A sunProcessTable_oid,
252N/A OID_LENGTH(sunProcessTable_oid),
252N/A HANDLER_CAN_RWRITE);
252N/A
252N/A if (!my_handler || !table_info || !iinfo)
252N/A return; /* mallocs failed */
252N/A
252N/A /*
252N/A * Setting up the table's definition
252N/A */
252N/A netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, 0);
252N/A
252N/A table_info->min_column = 1;
252N/A table_info->max_column = 11;
252N/A
252N/A /* iterator access routines */
252N/A iinfo->get_first_data_point = sunProcessTable_get_first_data_point;
252N/A iinfo->get_next_data_point = sunProcessTable_get_next_data_point;
252N/A
252N/A iinfo->table_reginfo = table_info;
252N/A
252N/A /*
252N/A * registering the table with the master agent
252N/A */
252N/A DEBUGMSGTL(("initialize_table_sunProcessTable",
252N/A "Registering table sunProcessTable as a table iterator\n"));
252N/A netsnmp_register_table_iterator(my_handler, iinfo);
252N/A}
252N/A
252N/A/* Initializes the sunProcesses module */
252N/Avoid init_sunProcesses(void) {
252N/A
252N/A (void) time(&cache_now);
252N/A
252N/A /* here we initialize all the tables we're planning on supporting */
252N/A initialize_table_sunProcessTable();
252N/A}
252N/A
252N/A/*
252N/A * returns the first data point within the sunProcessTable table data.
252N/A *
252N/A * Set the my_loop_context variable to the first data point structure
252N/A * of your choice (from which you can find the next one). This could
252N/A * be anything from the first node in a linked list, to an integer
252N/A * pointer containing the beginning of an array variable.
252N/A *
252N/A * Set the my_data_context variable to something to be returned to
252N/A * you later that will provide you with the data to return in a given
252N/A * row. * This could be the same pointer as what my_loop_context is
252N/A * set to, or something different.
252N/A *
252N/A * The put_index_data variable contains a list of snmp variable
252N/A * bindings, one for each index in your table. * Set the values of
252N/A * each appropriately according to the data matching the first row
252N/A * and return the put_index_data variable at the end of the function.
252N/A */
252N/Anetsnmp_variable_list *
252N/AsunProcessTable_get_first_data_point(void **my_loop_context,
252N/A void **my_data_context,
252N/A netsnmp_variable_list *put_index_data,
252N/A netsnmp_iterator_info *mydata) {
252N/A long long_type;
252N/A netsnmp_variable_list *vptr;
252N/A ps_data_t *ps_ptr;
252N/A
252N/A get_ps_data();
252N/A
252N/A ps_ptr = pstable;
252N/A if (ps_ptr == NULL) {
252N/A return (NULL);
252N/A }
252N/A
252N/A *my_loop_context = ps_ptr;
252N/A *my_data_context = ps_ptr;
252N/A
252N/A vptr = put_index_data;
252N/A
252N/A long_type = (long)ps_ptr[0].pid;
252N/A snmp_set_var_value(vptr, (u_char *) &long_type, sizeof(long_type));
252N/A
252N/A /* vptr = vptr->next_variable; */
252N/A/*
252N/Apr_ps();
252N/A*/
252N/A return (put_index_data);
252N/A}
252N/A
252N/A/*
252N/A * functionally the same as sunProcessTable_get_first_data_point, but
252N/A * my_loop_context has already been set to a previous value and should
252N/A * be updated to the next in the list. For example, if it was a
252N/A * linked list, you might want to cast it and the return
252N/A * my_loop_context->next. The my_data_context pointer should be set
252N/A * to something you need later and the indexes in put_index_data
252N/A * updated again.
252N/A */
252N/A
252N/Anetsnmp_variable_list *
252N/AsunProcessTable_get_next_data_point(void **my_loop_context,
252N/A void **my_data_context,
252N/A netsnmp_variable_list *put_index_data,
252N/A netsnmp_iterator_info *mydata)
252N/A{
252N/A long long_type;
252N/A netsnmp_variable_list *vptr;
252N/A ps_data_t *ps_ptr;
252N/A
252N/A get_ps_data();
252N/A
252N/A ps_ptr = (ps_data_t *) (*my_loop_context);
252N/A ps_ptr++;
252N/A
252N/A if (ps_ptr > &(pstable[pstable_lines - 1])) {
252N/A return (NULL);
252N/A }
252N/A
252N/A *my_loop_context = ps_ptr;
252N/A *my_data_context = ps_ptr;
252N/A
252N/A vptr = put_index_data;
252N/A
252N/A long_type = (long)ps_ptr[0].pid;
252N/A snmp_set_var_value(vptr, (u_char *) &long_type, sizeof(long_type));
252N/A
252N/A /* vptr = vptr->next_variable; */
252N/A
252N/A return (put_index_data);
252N/A}
252N/A
252N/A/*
252N/A * handles requests for the sunProcessTable table,
252N/A * if anything else needs to be done
252N/A */
252N/Aint sunProcessTable_handler(netsnmp_mib_handler *handler,
252N/A netsnmp_handler_registration *reginfo,
252N/A netsnmp_agent_request_info *reqinfo,
252N/A netsnmp_request_info *requests) {
252N/A
252N/A long long_type;
252N/A netsnmp_request_info *request;
252N/A netsnmp_table_request_info *table_info;
252N/A netsnmp_variable_list *var;
252N/A ps_data_t *psp;
252N/A
252N/A /* For caching purposes, find out what the time is now */
252N/A (void) time(&cache_now);
252N/A
252N/A for (request = requests; request; request = request->next) {
252N/A var = request->requestvb;
252N/A if (request->processed != 0)
252N/A continue;
252N/A
252N/A /* perform anything here that you need to do before each */
252N/A /* request is processed. */
252N/A
252N/A /* the following extracts the my_data_context pointer set in */
252N/A /* the loop functions above. You can then use the results to */
252N/A /* help return data for the columns of the sunProcessTable */
252N/A /* table in question */
252N/A psp = (ps_data_t *) netsnmp_extract_iterator_context(request);
252N/A if (psp == NULL) {
252N/A if (reqinfo->mode == MODE_GET ||
252N/A reqinfo->mode == MODE_SET_RESERVE1) {
252N/A
252N/A netsnmp_set_request_error(reqinfo, request,
252N/A SNMP_NOSUCHINSTANCE);
252N/A continue;
252N/A }
252N/A /*
252N/A * XXX: no row existed, if you support creation and this is a
252N/A * set, start dealing with it here, else continue
252N/A */
252N/A }
252N/A
252N/A /* extracts the information about the table from the request */
252N/A table_info = netsnmp_extract_table_info(request);
252N/A
252N/A /* table_info->colnum contains the column number requested */
252N/A /* table_info->indexes contains a linked list of snmp variable */
252N/A /* bindings for the indexes of the table. Values in the list */
252N/A /* have been set corresponding to the indexes of the request */
252N/A if (table_info == NULL) {
252N/A continue;
252N/A }
252N/A
252N/A switch (reqinfo->mode) {
252N/A /*
252N/A * the table_iterator helper should change all GETNEXTs
252N/A * into GETs for you automatically, so you don't have to
252N/A * worry about the GETNEXT case. Only GETs and SETs need
252N/A * to be dealt with here
252N/A */
252N/A case MODE_GET:
252N/A switch (table_info->colnum) {
252N/A case COLUMN_PSPROCESSID:
252N/A long_type = (long)psp->pid;
252N/A snmp_set_var_typed_value(var, ASN_INTEGER,
252N/A (u_char *) &long_type,
252N/A sizeof (long_type));
252N/A break;
252N/A
252N/A case COLUMN_PSPARENTPROCESSID:
252N/A long_type = (long)psp->ppid;
252N/A snmp_set_var_typed_value(var, ASN_INTEGER,
252N/A (u_char *) &long_type,
252N/A sizeof (long_type));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSSIZE:
252N/A long_type = (long)psp->sz;
252N/A snmp_set_var_typed_value(var, ASN_INTEGER,
252N/A (u_char *) &long_type,
252N/A sizeof (long_type));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSCPUTIME:
252N/A long_type = (long)psp->cpu;
252N/A snmp_set_var_typed_value(var, ASN_INTEGER,
252N/A (u_char *) &long_type,
252N/A sizeof (long_type));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSSTATE:
252N/A snmp_set_var_typed_value(var, ASN_OCTET_STR,
252N/A (u_char *) &psp->stat,
252N/A strlen(psp->stat));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSWAITCHANNEL:
252N/A snmp_set_var_typed_value(var, ASN_OCTET_STR,
252N/A (u_char *) &psp->wchan,
252N/A strlen(psp->wchan));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSTTY:
252N/A snmp_set_var_typed_value(var, ASN_OCTET_STR,
252N/A (u_char *) &psp->tty,
252N/A strlen(psp->tty));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSUSERNAME:
252N/A snmp_set_var_typed_value(var, ASN_OCTET_STR,
252N/A (u_char *) &psp->usrname,
252N/A strlen(psp->usrname));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSUSERID:
252N/A long_type = (long)psp->uid;
252N/A snmp_set_var_typed_value(var, ASN_INTEGER,
252N/A (u_char *) &long_type,
252N/A sizeof (long_type));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSNAME:
252N/A snmp_set_var_typed_value(var, ASN_OCTET_STR,
252N/A (u_char *) &psp->cmd,
252N/A strlen(psp->cmd));
252N/A break;
252N/A
252N/A case COLUMN_PSPROCESSSTATUS:
252N/A long_type = (long)psp->sz;
252N/A snmp_set_var_typed_value(var, ASN_INTEGER,
252N/A (u_char *) &long_type,
252N/A sizeof (long_type));
252N/A break;
252N/A
252N/A default:
252N/A /* We shouldn't get here */
252N/A snmp_log(LOG_ERR,
252N/A"problem encountered in sunProcessTable_handler: unknown column\n");
252N/A }
252N/A break;
252N/A
252N/A case MODE_SET_RESERVE1:
252N/A break;
252N/A
252N/A case MODE_SET_RESERVE2:
252N/A break;
252N/A
252N/A case MODE_SET_FREE:
252N/A break;
252N/A
252N/A case MODE_SET_ACTION:
252N/A /* set handling... */
252N/A/* XXX don't know about 64 bit */
252N/A if ((int) *(requests->requestvb->val.integer) != 0) {
252N/A (void) kill(psp->pid,
252N/A (int)*(requests->requestvb->val.integer));
252N/A }
252N/A break;
252N/A
252N/A case MODE_SET_COMMIT:
252N/A break;
252N/A
252N/A case MODE_SET_UNDO:
252N/A break;
252N/A
252N/A default:
252N/A snmp_log(LOG_ERR,
252N/A "problem encountered in sunProcessTable_handler: unsupported mode\n");
252N/A }
252N/A }
252N/A
252N/A return (SNMP_ERR_NOERROR);
252N/A}