proc.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:21k
- #include <net-snmp/net-snmp-config.h>
- #ifdef solaris2
- #define _KMEMUSER /* Needed by <sys/user.h> */
- #include <sys/types.h> /* helps define struct rlimit */
- #endif
- #if HAVE_IO_H /* win32 */
- #include <io.h>
- #endif
- #if HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #if HAVE_MALLOC_H
- #include <malloc.h>
- #endif
- #include <math.h>
- #include <ctype.h>
- #include <sys/types.h>
- #if HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #if TIME_WITH_SYS_TIME
- # ifdef WIN32
- # include <sys/timeb.h>
- # else
- # include <sys/time.h>
- # endif
- # include <time.h>
- #else
- # if HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
- #endif
- #if HAVE_KVM_H
- #include <kvm.h>
- #endif
- #if HAVE_WINSOCK_H
- #include <winsock.h>
- #endif
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- #include <net-snmp/net-snmp-includes.h>
- #include <net-snmp/agent/net-snmp-agent-includes.h>
- #include "struct.h"
- #include "proc.h"
- #ifdef USING_UCD_SNMP_ERRORMIB_MODULE
- #include "errormib.h"
- #else
- #define setPerrorstatus(x) snmp_log_perror(x)
- #endif
- #include "util_funcs.h"
- #include "kernel.h"
- static struct myproc *get_proc_instance(struct myproc *, oid);
- struct myproc *procwatch = NULL;
- static struct extensible fixproc;
- int numprocs = 0;
- void
- init_proc(void)
- {
- /*
- * define the structure we're going to ask the agent to register our
- * information at
- */
- struct variable2 extensible_proc_variables[] = {
- {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_proc, 1, {MIBINDEX}},
- {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_proc, 1,
- {ERRORNAME}},
- {PROCMIN, ASN_INTEGER, RONLY, var_extensible_proc, 1, {PROCMIN}},
- {PROCMAX, ASN_INTEGER, RONLY, var_extensible_proc, 1, {PROCMAX}},
- {PROCCOUNT, ASN_INTEGER, RONLY, var_extensible_proc, 1,
- {PROCCOUNT}},
- {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_proc, 1,
- {ERRORFLAG}},
- {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_proc, 1,
- {ERRORMSG}},
- {ERRORFIX, ASN_INTEGER, RWRITE, var_extensible_proc, 1,
- {ERRORFIX}},
- {ERRORFIXCMD, ASN_OCTET_STR, RONLY, var_extensible_proc, 1,
- {ERRORFIXCMD}}
- };
- /*
- * Define the OID pointer to the top of the mib tree that we're
- * registering underneath
- */
- oid proc_variables_oid[] = { UCDAVIS_MIB, PROCMIBNUM, 1 };
- /*
- * register ourselves with the agent to handle our mib tree
- */
- REGISTER_MIB("ucd-snmp/proc", extensible_proc_variables, variable2,
- proc_variables_oid);
- snmpd_register_config_handler("proc", proc_parse_config,
- proc_free_config,
- "process-name [max-num] [min-num]");
- snmpd_register_config_handler("procfix", procfix_parse_config, NULL,
- "process-name program [arguments...]");
- }
- /*
- * Define snmpd.conf reading routines first. They get called
- * automatically by the invocation of a macro in the proc.h file.
- */
- void
- proc_free_config(void)
- {
- struct myproc *ptmp, *ptmp2;
- for (ptmp = procwatch; ptmp != NULL;) {
- ptmp2 = ptmp;
- ptmp = ptmp->next;
- free(ptmp2);
- }
- procwatch = NULL;
- numprocs = 0;
- }
- /*
- * find a give entry in the linked list associated with a proc name
- */
- static struct myproc *
- get_proc_by_name(char *name)
- {
- struct myproc *ptmp;
- if (name == NULL)
- return NULL;
- for (ptmp = procwatch; ptmp != NULL && strcmp(ptmp->name, name) != 0;
- ptmp = ptmp->next);
- return ptmp;
- }
- void
- procfix_parse_config(const char *token, char *cptr)
- {
- char tmpname[STRMAX];
- struct myproc *procp;
- /*
- * don't allow two entries with the same name
- */
- cptr = copy_nword(cptr, tmpname, sizeof(tmpname));
- if ((procp = get_proc_by_name(tmpname)) == NULL) {
- config_perror("No proc entry registered for this proc name yet.");
- return;
- }
- if (strlen(cptr) > sizeof(procp->fixcmd)) {
- config_perror("fix command too long.");
- return;
- }
- strcpy(procp->fixcmd, cptr);
- }
- void
- proc_parse_config(const char *token, char *cptr)
- {
- char tmpname[STRMAX];
- struct myproc **procp = &procwatch;
- /*
- * don't allow two entries with the same name
- */
- copy_nword(cptr, tmpname, sizeof(tmpname));
- if (get_proc_by_name(tmpname) != NULL) {
- config_perror("Already have an entry for this process.");
- return;
- }
- /*
- * skip past used ones
- */
- while (*procp != NULL)
- procp = &((*procp)->next);
- (*procp) = (struct myproc *) calloc(1, sizeof(struct myproc));
- if (*procp == NULL)
- return; /* memory alloc error */
- numprocs++;
- /*
- * not blank and not a comment
- */
- copy_nword(cptr, (*procp)->name, sizeof((*procp)->name));
- cptr = skip_not_white(cptr);
- if ((cptr = skip_white(cptr))) {
- (*procp)->max = atoi(cptr);
- cptr = skip_not_white(cptr);
- if ((cptr = skip_white(cptr)))
- (*procp)->min = atoi(cptr);
- else
- (*procp)->min = 0;
- } else {
- (*procp)->max = 0;
- (*procp)->min = 0;
- }
- #ifdef PROCFIXCMD
- sprintf((*procp)->fixcmd, PROCFIXCMD, (*procp)->name);
- #endif
- DEBUGMSGTL(("ucd-snmp/proc", "Read: %s (%d) (%d)n",
- (*procp)->name, (*procp)->max, (*procp)->min));
- }
- /*
- * The routine that handles everything
- */
- u_char *
- var_extensible_proc(struct variable *vp,
- oid * name,
- size_t * length,
- int exact,
- size_t * var_len, WriteMethod ** write_method)
- {
- struct myproc *proc;
- static long long_ret;
- static char errmsg[300];
- if (header_simple_table
- (vp, name, length, exact, var_len, write_method, numprocs))
- return (NULL);
- if ((proc = get_proc_instance(procwatch, name[*length - 1]))) {
- switch (vp->magic) {
- case MIBINDEX:
- long_ret = name[*length - 1];
- return ((u_char *) (&long_ret));
- case ERRORNAME: /* process name to check for */
- *var_len = strlen(proc->name);
- return ((u_char *) (proc->name));
- case PROCMIN:
- long_ret = proc->min;
- return ((u_char *) (&long_ret));
- case PROCMAX:
- long_ret = proc->max;
- return ((u_char *) (&long_ret));
- case PROCCOUNT:
- long_ret = sh_count_procs(proc->name);
- return ((u_char *) (&long_ret));
- case ERRORFLAG:
- long_ret = sh_count_procs(proc->name);
- if (long_ret >= 0 &&
- ((proc->min && long_ret < proc->min) ||
- (proc->max && long_ret > proc->max) ||
- (proc->min == 0 && proc->max == 0 && long_ret < 1))) {
- long_ret = 1;
- } else {
- long_ret = 0;
- }
- return ((u_char *) (&long_ret));
- case ERRORMSG:
- long_ret = sh_count_procs(proc->name);
- if (long_ret < 0) {
- errmsg[0] = 0; /* catch out of mem errors return 0 count */
- } else if (proc->min && long_ret < proc->min) {
- snprintf(errmsg, sizeof(errmsg),
- "Too few %s running (# = %d)",
- proc->name, (int) long_ret);
- } else if (proc->max && long_ret > proc->max) {
- snprintf(errmsg, sizeof(errmsg),
- "Too many %s running (# = %d)",
- proc->name, (int) long_ret);
- } else if (proc->min == 0 && proc->max == 0 && long_ret < 1) {
- snprintf(errmsg, sizeof(errmsg),
- "No %s process running.", proc->name);
- } else {
- errmsg[0] = 0;
- }
- errmsg[ sizeof(errmsg)-1 ] = 0;
- *var_len = strlen(errmsg);
- return ((u_char *) errmsg);
- case ERRORFIX:
- *write_method = fixProcError;
- long_return = fixproc.result;
- return ((u_char *) & long_return);
- case ERRORFIXCMD:
- if (proc->fixcmd) {
- *var_len = strlen(proc->fixcmd);
- return (u_char *) proc->fixcmd;
- }
- errmsg[0] = 0;
- *var_len = 0;
- return ((u_char *) errmsg);
- }
- return NULL;
- }
- return NULL;
- }
- int
- fixProcError(int action,
- u_char * var_val,
- u_char var_val_type,
- size_t var_val_len,
- u_char * statP, oid * name, size_t name_len)
- {
- struct myproc *proc;
- long tmp = 0;
- if ((proc = get_proc_instance(procwatch, name[10]))) {
- if (var_val_type != ASN_INTEGER) {
- snmp_log(LOG_ERR, "Wrong type != intn");
- return SNMP_ERR_WRONGTYPE;
- }
- tmp = *((long *) var_val);
- if (tmp == 1 && action == COMMIT) {
- if (proc->fixcmd[0]) {
- strcpy(fixproc.command, proc->fixcmd);
- exec_command(&fixproc);
- }
- }
- return SNMP_ERR_NOERROR;
- }
- return SNMP_ERR_WRONGTYPE;
- }
- static struct myproc *
- get_proc_instance(struct myproc *proc, oid inst)
- {
- int i;
- if (proc == NULL)
- return (NULL);
- for (i = 1; (i != (int) inst) && (proc != NULL); i++)
- proc = proc->next;
- return (proc);
- }
- #ifdef bsdi2
- #include <sys/param.h>
- #include <sys/sysctl.h>
- #define PP(pp, field) ((pp)->kp_proc . field)
- #define EP(pp, field) ((pp)->kp_eproc . field)
- #define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
- /*
- * these are for keeping track of the proc array
- */
- static int nproc = 0;
- static int onproc = -1;
- static struct kinfo_proc *pbase = 0;
- int
- sh_count_procs(char *procname)
- {
- register int i, ret = 0;
- register struct kinfo_proc *pp;
- static int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
- if (sysctl(mib, 3, NULL, &nproc, NULL, 0) < 0)
- return 0;
- if (nproc > onproc || !pbase) {
- if ((pbase = (struct kinfo_proc *) realloc(pbase,
- nproc +
- sizeof(struct
- kinfo_proc))) ==
- 0)
- return -1;
- onproc = nproc;
- memset(pbase, 0, nproc + sizeof(struct kinfo_proc));
- }
- if (sysctl(mib, 3, pbase, &nproc, NULL, 0) < 0)
- return -1;
- for (pp = pbase, i = 0; i < nproc / sizeof(struct kinfo_proc);
- pp++, i++) {
- if (PP(pp, p_stat) != 0 && (((PP(pp, p_flag) & P_SYSTEM) == 0))) {
- if (PP(pp, p_stat) != SZOMB
- && !strcmp(PP(pp, p_comm), procname))
- ret++;
- }
- }
- return ret;
- }
- #elif OSTYPE == LINUXID
- #include <dirent.h>
- #include <fcntl.h>
- #include <unistd.h>
- int
- sh_count_procs(char *procname)
- {
- DIR *dir;
- char cmdline[512], *tmpc;
- struct dirent *ent;
- #ifdef USE_PROC_CMDLINE
- int fd;
- #endif
- int len,plen=strlen(procname),total = 0;
- FILE *status;
- if ((dir = opendir("/proc")) == NULL) return -1;
- while (NULL != (ent = readdir(dir))) {
- if(!(ent->d_name[0] >= '0' && ent->d_name[0] <= '9')) continue;
- #ifdef USE_PROC_CMDLINE /* old method */
- /* read /proc/XX/cmdline */
- sprintf(cmdline,"/proc/%s/cmdline",ent->d_name);
- if((fd = open(cmdline, O_RDONLY)) < 0) break;
- len = read(fd,cmdline,sizeof(cmdline) - 1);
- close(fd);
- if(len <= 0) continue;
- cmdline[len] = 0;
- while(--len && !cmdline[len]);
- while(--len) if(!cmdline[len]) cmdline[len] = ' ';
- if(!strncmp(cmdline,procname,plen)) total++;
- #else
- /* read /proc/XX/status */
- sprintf(cmdline,"/proc/%s/status",ent->d_name);
- if ((status = fopen(cmdline, "r")) == NULL)
- break;
- if (fgets(cmdline, sizeof(cmdline), status) == NULL) {
- fclose(status);
- break;
- }
- fclose(status);
- cmdline[sizeof(cmdline)-1] = ' ';
- /* XXX: assumes Name: is first */
- if (strncmp("Name:",cmdline, 5) != 0)
- break;
- tmpc = skip_token(cmdline);
- if (!tmpc)
- break;
- for (len=0;; len++) {
- if (tmpc[len] && isgraph(tmpc[len])) continue;
- tmpc[len]=' ';
- break;
- }
- DEBUGMSGTL(("proc","Comparing wanted %s against %sn",
- procname, tmpc));
- if(len==plen && !strncmp(tmpc,procname,plen)) {
- total++;
- DEBUGMSGTL(("proc", " Matched. total count now=%dn", total));
- }
- #endif
- }
- closedir(dir);
- return total;
- }
- #elif OSTYPE == ULTRIXID
- #define NPROCS 32 /* number of proces to read at once */
- extern int kmem, mem, swap;
- #include <sys/user.h>
- #include <sys/proc.h>
- #include <sys/file.h>
- #include <sys/vm.h>
- #include <machine/pte.h>
- #ifdef HAVE_NLIST_H
- #include <nlist.h>
- #endif
- static struct user *getuser(struct proc *);
- static int getword(off_t);
- static int getstruct(off_t, char *, off_t, int);
- static struct nlist proc_nl[] = {
- {"_nproc"},
- #define X_NPROC 0
- {"_proc"},
- #define X_PROC 1
- {"_proc_bitmap"},
- #define X_PROC_BITMAP 2
- {NULL}
- };
- int
- sh_count_procs(char *procname)
- {
- int total, proc_active, nproc;
- int thisproc = 0;
- int absolute_proc_number = -1;
- struct user *auser;
- struct proc *aproc, *procp;
- unsigned bitmap;
- struct proc procs[NPROCS], *procsp;
- static int inited = 0;
- procp = (struct proc *) getword(proc_nl[X_PROC].n_value);
- nproc = getword(proc_nl[X_NPROC].n_value);
- total = 0;
- for (;;) {
- do {
- while (thisproc == 0) {
- int nread;
- int psize;
- if (nproc == 0)
- return (total);
- thisproc = MIN(NPROCS, nproc);
- psize = thisproc * sizeof(struct proc);
- nproc -= thisproc;
- if (lseek(kmem, (off_t) procp, L_SET) == -1 ||
- (nread = read(kmem, (char *) procs, psize)) < 0) {
- /*
- * warn("read proc");
- */
- return (total);
- } else if (nread != psize) {
- thisproc = nread / sizeof(struct proc);
- nproc = 0;
- /*
- * warn("read proc: short read");
- */
- }
- procsp = procs;
- procp += thisproc;
- }
- aproc = procsp++;
- thisproc--;
- absolute_proc_number++;
- if ((absolute_proc_number % 32) == 0)
- bitmap =
- getword((unsigned int) proc_nl[X_PROC_BITMAP].n_value +
- ((absolute_proc_number / 32) * 4));
- proc_active =
- (bitmap & (1 << (absolute_proc_number % 32))) != 0;
- if (proc_active && aproc->p_stat != SZOMB
- && !(aproc->p_type & SWEXIT))
- auser = getuser(aproc);
- } while (!proc_active || auser == NULL);
- if (strcmp(auser->u_comm, procname) == 0)
- total++;
- }
- }
- #define SW_UADDR dtob(getword((off_t)dmap.dm_ptdaddr))
- #define SW_UBYTES sizeof(struct user)
- #define SKRD(file, src, dst, size)
- (lseek(file, (off_t)(src), L_SET) == -1) ||
- (read(file, (char *)(dst), (size)) != (size))
- static struct user *
- getuser(struct proc *aproc)
- {
- static union {
- struct user user;
- char upgs[UPAGES][NBPG];
- } u;
- static struct pte uptes[UPAGES];
- static struct dmap dmap;
- int i, nbytes;
- /*
- * If process is not in core, we simply snarf it's user struct
- * from the swap device.
- */
- if ((aproc->p_sched & SLOAD) == 0) {
- if (!getstruct
- ((off_t) aproc->p_smap, "aproc->p_smap", (off_t) & dmap,
- sizeof(dmap))) {
- /*
- * warnx("can't read dmap for pid %d from %s", aproc->p_pid,
- * _PATH_DRUM);
- */
- return (NULL);
- }
- if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
- /*
- * warnx("can't read u for pid %d from %s", aproc->p_pid, _PATH_DRUM);
- */
- return (NULL);
- }
- return (&u.user);
- }
- /*
- * Process is in core. Follow p_addr to read in the page
- * table entries that map the u-area and then read in the
- * physical pages that comprise the u-area.
- *
- * If at any time, an lseek() or read() fails, print a warning
- * message and return NULL.
- */
- if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
- /*
- * warnx("can't read user pt for pid %d from %s", aproc->p_pid, _PATH_DRUM);
- */
- return (NULL);
- }
- nbytes = sizeof(struct user);
- for (i = 0; i < UPAGES && nbytes > 0; i++) {
- if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
- /*
- * warnx("can't read user page %u for pid %d from %s",
- * uptes[i].pg_pfnum, aproc->p_pid, _PATH_MEM);
- */
- return (NULL);
- }
- nbytes -= NBPG;
- }
- return (&u.user);
- }
- static int
- getword(off_t loc)
- {
- int val;
- if (SKRD(kmem, loc, &val, sizeof(val)))
- exit(1);
- return (val);
- }
- static int
- getstruct(off_t loc, char *name, off_t dest, int size)
- {
- if (SKRD(kmem, loc, dest, size))
- return (0);
- return (1);
- }
- #elif OSTYPE == SOLARISID
- #ifdef _SLASH_PROC_METHOD_
- #include <fcntl.h>
- #include <dirent.h>
- #include <procfs.h>
- /*
- * Gets process information from /proc/.../psinfo
- */
- int
- sh_count_procs(char *procname)
- {
- int fd, total = 0;
- struct psinfo info;
- char fbuf[32];
- struct dirent *ent;
- DIR *dir;
- if (!(dir = opendir("/proc"))) {
- snmp_perror("/proc");
- return -1;
- }
- while ((ent = readdir(dir))) {
- if (!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "."))
- continue;
- snprintf(fbuf, sizeof fbuf, "/proc/%s/psinfo", ent->d_name);
- if ((fd = open(fbuf, O_RDONLY)) < 0) { /* Continue or return error? */
- snmp_perror(fbuf);
- continue;
- }
- if (read(fd, (char *) &info, sizeof(struct psinfo)) !=
- sizeof(struct psinfo)) {
- snmp_perror(fbuf);
- close(fd);
- closedir(dir);
- return -1;
- }
- if (!info.pr_nlwp && !info.pr_lwp.pr_lwpid) {
- /*
- * Zombie process
- */
- } else {
- DEBUGMSGTL(("proc","Comparing wanted %s against %sn",
- procname, info.pr_fname));
- if (!strcmp(procname, info.pr_fname)) {
- total++;
- DEBUGMSGTL(("proc", " Matched. total count now=%dn", total));
- }
- }
- close(fd);
- }
- closedir(dir);
- return total;
- }
- #else /* _SLASH_PROC_METHOD_ */
- #define _KMEMUSER /* Needed by <sys/user.h> */
- #include <kvm.h>
- #include <fcntl.h>
- #include <sys/user.h>
- #include <sys/proc.h>
- int
- sh_count_procs(char *procname)
- {
- struct proc *p;
- struct user *u;
- int total;
- if (kd == NULL) {
- return -1;
- }
- if (kvm_setproc(kd) < 0) {
- return (-1);
- }
- kvm_setproc(kd);
- total = 0;
- while ((p = kvm_nextproc(kd)) != NULL) {
- if (!p) {
- return (-1);
- }
- u = kvm_getu(kd, p);
- /*
- * Skip this entry if u or u->u_comm is a NULL pointer
- */
- if (!u) {
- continue;
- }
- if (strcmp(procname, u->u_comm) == 0)
- total++;
- }
- return (total);
- }
- #endif /* _SLASH_PROC_METHOD_ */
- #else
- int
- sh_count_procs(char *procname)
- {
- char line[STRMAX], *cptr, *cp;
- int ret = 0, fd;
- FILE *file;
- #ifndef EXCACHETIME
- #endif
- struct extensible ex;
- int slow = strstr(PSCMD, "ax") != NULL;
- strcpy(ex.command, PSCMD);
- if ((fd = get_exec_output(&ex)) >= 0) {
- if ((file = fdopen(fd, "r")) == NULL) {
- setPerrorstatus("fdopen");
- close(fd);
- return (-1);
- }
- while (fgets(line, sizeof(line), file) != NULL) {
- if (slow) {
- cptr = find_field(line, 5);
- cp = strrchr(cptr, '/');
- if (cp)
- cptr = cp + 1;
- else if (*cptr == '-')
- cptr++;
- else if (*cptr == '[') {
- cptr++;
- cp = strchr(cptr, ']');
- if (cp)
- *cp = 0;
- }
- copy_nword(cptr, line, sizeof(line));
- cp = line + strlen(line) - 1;
- if (*cp == ':')
- *cp = 0;
- } else {
- if ((cptr = find_field(line, LASTFIELD)) == NULL)
- continue;
- copy_nword(cptr, line, sizeof(line));
- }
- if (!strcmp(line, procname))
- ret++;
- }
- if (ftell(file) < 2) {
- #ifdef USING_UCD_SNMP_ERRORMIB_MODULE
- seterrorstatus("process list unreasonable short (mem?)", 2);
- #endif
- ret = -1;
- }
- fclose(file);
- wait_on_exec(&ex);
- } else {
- ret = -1;
- }
- return (ret);
- }
- #endif