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