proc.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:21k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #ifdef solaris2
  3. #define _KMEMUSER               /* Needed by <sys/user.h> */
  4. #include <sys/types.h>          /* helps define struct rlimit */
  5. #endif
  6. #if HAVE_IO_H                   /* win32 */
  7. #include <io.h>
  8. #endif
  9. #if HAVE_STDLIB_H
  10. #include <stdlib.h>
  11. #endif
  12. #if HAVE_UNISTD_H
  13. #include <unistd.h>
  14. #endif
  15. #if HAVE_STRING_H
  16. #include <string.h>
  17. #else
  18. #include <strings.h>
  19. #endif
  20. #if HAVE_MALLOC_H
  21. #include <malloc.h>
  22. #endif
  23. #include <math.h>
  24. #include <ctype.h>
  25. #include <sys/types.h>
  26. #if HAVE_NETINET_IN_H
  27. #include <netinet/in.h>
  28. #endif
  29. #if TIME_WITH_SYS_TIME
  30. # ifdef WIN32
  31. #  include <sys/timeb.h>
  32. # else
  33. #  include <sys/time.h>
  34. # endif
  35. # include <time.h>
  36. #else
  37. # if HAVE_SYS_TIME_H
  38. #  include <sys/time.h>
  39. # else
  40. #  include <time.h>
  41. # endif
  42. #endif
  43. #if HAVE_KVM_H
  44. #include <kvm.h>
  45. #endif
  46. #if HAVE_WINSOCK_H
  47. #include <winsock.h>
  48. #endif
  49. #if HAVE_DMALLOC_H
  50. #include <dmalloc.h>
  51. #endif
  52. #include <net-snmp/net-snmp-includes.h>
  53. #include <net-snmp/agent/net-snmp-agent-includes.h>
  54. #include "struct.h"
  55. #include "proc.h"
  56. #ifdef USING_UCD_SNMP_ERRORMIB_MODULE
  57. #include "errormib.h"
  58. #else
  59. #define setPerrorstatus(x) snmp_log_perror(x)
  60. #endif
  61. #include "util_funcs.h"
  62. #include "kernel.h"
  63. static struct myproc *get_proc_instance(struct myproc *, oid);
  64. struct myproc  *procwatch = NULL;
  65. static struct extensible fixproc;
  66. int             numprocs = 0;
  67. void
  68. init_proc(void)
  69. {
  70.     /*
  71.      * define the structure we're going to ask the agent to register our
  72.      * information at 
  73.      */
  74.     struct variable2 extensible_proc_variables[] = {
  75.         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_proc, 1, {MIBINDEX}},
  76.         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_proc, 1,
  77.          {ERRORNAME}},
  78.         {PROCMIN, ASN_INTEGER, RONLY, var_extensible_proc, 1, {PROCMIN}},
  79.         {PROCMAX, ASN_INTEGER, RONLY, var_extensible_proc, 1, {PROCMAX}},
  80.         {PROCCOUNT, ASN_INTEGER, RONLY, var_extensible_proc, 1,
  81.          {PROCCOUNT}},
  82.         {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_proc, 1,
  83.          {ERRORFLAG}},
  84.         {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_proc, 1,
  85.          {ERRORMSG}},
  86.         {ERRORFIX, ASN_INTEGER, RWRITE, var_extensible_proc, 1,
  87.          {ERRORFIX}},
  88.         {ERRORFIXCMD, ASN_OCTET_STR, RONLY, var_extensible_proc, 1,
  89.          {ERRORFIXCMD}}
  90.     };
  91.     /*
  92.      * Define the OID pointer to the top of the mib tree that we're
  93.      * registering underneath 
  94.      */
  95.     oid             proc_variables_oid[] = { UCDAVIS_MIB, PROCMIBNUM, 1 };
  96.     /*
  97.      * register ourselves with the agent to handle our mib tree 
  98.      */
  99.     REGISTER_MIB("ucd-snmp/proc", extensible_proc_variables, variable2,
  100.                  proc_variables_oid);
  101.     snmpd_register_config_handler("proc", proc_parse_config,
  102.                                   proc_free_config,
  103.                                   "process-name [max-num] [min-num]");
  104.     snmpd_register_config_handler("procfix", procfix_parse_config, NULL,
  105.                                   "process-name program [arguments...]");
  106. }
  107. /*
  108.  * Define snmpd.conf reading routines first.  They get called
  109.  * automatically by the invocation of a macro in the proc.h file. 
  110.  */
  111. void
  112. proc_free_config(void)
  113. {
  114.     struct myproc  *ptmp, *ptmp2;
  115.     for (ptmp = procwatch; ptmp != NULL;) {
  116.         ptmp2 = ptmp;
  117.         ptmp = ptmp->next;
  118.         free(ptmp2);
  119.     }
  120.     procwatch = NULL;
  121.     numprocs = 0;
  122. }
  123. /*
  124.  * find a give entry in the linked list associated with a proc name 
  125.  */
  126. static struct myproc *
  127. get_proc_by_name(char *name)
  128. {
  129.     struct myproc  *ptmp;
  130.     if (name == NULL)
  131.         return NULL;
  132.     for (ptmp = procwatch; ptmp != NULL && strcmp(ptmp->name, name) != 0;
  133.          ptmp = ptmp->next);
  134.     return ptmp;
  135. }
  136. void
  137. procfix_parse_config(const char *token, char *cptr)
  138. {
  139.     char            tmpname[STRMAX];
  140.     struct myproc  *procp;
  141.     /*
  142.      * don't allow two entries with the same name 
  143.      */
  144.     cptr = copy_nword(cptr, tmpname, sizeof(tmpname));
  145.     if ((procp = get_proc_by_name(tmpname)) == NULL) {
  146.         config_perror("No proc entry registered for this proc name yet.");
  147.         return;
  148.     }
  149.     if (strlen(cptr) > sizeof(procp->fixcmd)) {
  150.         config_perror("fix command too long.");
  151.         return;
  152.     }
  153.     strcpy(procp->fixcmd, cptr);
  154. }
  155. void
  156. proc_parse_config(const char *token, char *cptr)
  157. {
  158.     char            tmpname[STRMAX];
  159.     struct myproc **procp = &procwatch;
  160.     /*
  161.      * don't allow two entries with the same name 
  162.      */
  163.     copy_nword(cptr, tmpname, sizeof(tmpname));
  164.     if (get_proc_by_name(tmpname) != NULL) {
  165.         config_perror("Already have an entry for this process.");
  166.         return;
  167.     }
  168.     /*
  169.      * skip past used ones 
  170.      */
  171.     while (*procp != NULL)
  172.         procp = &((*procp)->next);
  173.     (*procp) = (struct myproc *) calloc(1, sizeof(struct myproc));
  174.     if (*procp == NULL)
  175.         return;                 /* memory alloc error */
  176.     numprocs++;
  177.     /*
  178.      * not blank and not a comment 
  179.      */
  180.     copy_nword(cptr, (*procp)->name, sizeof((*procp)->name));
  181.     cptr = skip_not_white(cptr);
  182.     if ((cptr = skip_white(cptr))) {
  183.         (*procp)->max = atoi(cptr);
  184.         cptr = skip_not_white(cptr);
  185.         if ((cptr = skip_white(cptr)))
  186.             (*procp)->min = atoi(cptr);
  187.         else
  188.             (*procp)->min = 0;
  189.     } else {
  190.         (*procp)->max = 0;
  191.         (*procp)->min = 0;
  192.     }
  193. #ifdef PROCFIXCMD
  194.     sprintf((*procp)->fixcmd, PROCFIXCMD, (*procp)->name);
  195. #endif
  196.     DEBUGMSGTL(("ucd-snmp/proc", "Read:  %s (%d) (%d)n",
  197.                 (*procp)->name, (*procp)->max, (*procp)->min));
  198. }
  199. /*
  200.  * The routine that handles everything 
  201.  */
  202. u_char         *
  203. var_extensible_proc(struct variable *vp,
  204.                     oid * name,
  205.                     size_t * length,
  206.                     int exact,
  207.                     size_t * var_len, WriteMethod ** write_method)
  208. {
  209.     struct myproc  *proc;
  210.     static long     long_ret;
  211.     static char     errmsg[300];
  212.     if (header_simple_table
  213.         (vp, name, length, exact, var_len, write_method, numprocs))
  214.         return (NULL);
  215.     if ((proc = get_proc_instance(procwatch, name[*length - 1]))) {
  216.         switch (vp->magic) {
  217.         case MIBINDEX:
  218.             long_ret = name[*length - 1];
  219.             return ((u_char *) (&long_ret));
  220.         case ERRORNAME:        /* process name to check for */
  221.             *var_len = strlen(proc->name);
  222.             return ((u_char *) (proc->name));
  223.         case PROCMIN:
  224.             long_ret = proc->min;
  225.             return ((u_char *) (&long_ret));
  226.         case PROCMAX:
  227.             long_ret = proc->max;
  228.             return ((u_char *) (&long_ret));
  229.         case PROCCOUNT:
  230.             long_ret = sh_count_procs(proc->name);
  231.             return ((u_char *) (&long_ret));
  232.         case ERRORFLAG:
  233.             long_ret = sh_count_procs(proc->name);
  234.             if (long_ret >= 0 &&
  235.                 ((proc->min && long_ret < proc->min) ||
  236.                  (proc->max && long_ret > proc->max) ||
  237.                  (proc->min == 0 && proc->max == 0 && long_ret < 1))) {
  238.                 long_ret = 1;
  239.             } else {
  240.                 long_ret = 0;
  241.             }
  242.             return ((u_char *) (&long_ret));
  243.         case ERRORMSG:
  244.             long_ret = sh_count_procs(proc->name);
  245.             if (long_ret < 0) {
  246.                 errmsg[0] = 0;  /* catch out of mem errors return 0 count */
  247.             } else if (proc->min && long_ret < proc->min) {
  248.                 snprintf(errmsg, sizeof(errmsg),
  249.                         "Too few %s running (# = %d)",
  250.                         proc->name, (int) long_ret);
  251.             } else if (proc->max && long_ret > proc->max) {
  252.                 snprintf(errmsg, sizeof(errmsg),
  253.                         "Too many %s running (# = %d)",
  254.                         proc->name, (int) long_ret);
  255.             } else if (proc->min == 0 && proc->max == 0 && long_ret < 1) {
  256.                 snprintf(errmsg, sizeof(errmsg),
  257.                         "No %s process running.", proc->name);
  258.             } else {
  259.                 errmsg[0] = 0;
  260.             }
  261.             errmsg[ sizeof(errmsg)-1 ] = 0;
  262.             *var_len = strlen(errmsg);
  263.             return ((u_char *) errmsg);
  264.         case ERRORFIX:
  265.             *write_method = fixProcError;
  266.             long_return = fixproc.result;
  267.             return ((u_char *) & long_return);
  268.         case ERRORFIXCMD:
  269.             if (proc->fixcmd) {
  270.                 *var_len = strlen(proc->fixcmd);
  271.                 return (u_char *) proc->fixcmd;
  272.             }
  273.             errmsg[0] = 0;
  274.             *var_len = 0;
  275.             return ((u_char *) errmsg);
  276.         }
  277.         return NULL;
  278.     }
  279.     return NULL;
  280. }
  281. int
  282. fixProcError(int action,
  283.              u_char * var_val,
  284.              u_char var_val_type,
  285.              size_t var_val_len,
  286.              u_char * statP, oid * name, size_t name_len)
  287. {
  288.     struct myproc  *proc;
  289.     long            tmp = 0;
  290.     if ((proc = get_proc_instance(procwatch, name[10]))) {
  291.         if (var_val_type != ASN_INTEGER) {
  292.             snmp_log(LOG_ERR, "Wrong type != intn");
  293.             return SNMP_ERR_WRONGTYPE;
  294.         }
  295.         tmp = *((long *) var_val);
  296.         if (tmp == 1 && action == COMMIT) {
  297.             if (proc->fixcmd[0]) {
  298.                 strcpy(fixproc.command, proc->fixcmd);
  299.                 exec_command(&fixproc);
  300.             }
  301.         }
  302.         return SNMP_ERR_NOERROR;
  303.     }
  304.     return SNMP_ERR_WRONGTYPE;
  305. }
  306. static struct myproc *
  307. get_proc_instance(struct myproc *proc, oid inst)
  308. {
  309.     int             i;
  310.     if (proc == NULL)
  311.         return (NULL);
  312.     for (i = 1; (i != (int) inst) && (proc != NULL); i++)
  313.         proc = proc->next;
  314.     return (proc);
  315. }
  316. #ifdef bsdi2
  317. #include <sys/param.h>
  318. #include <sys/sysctl.h>
  319. #define PP(pp, field) ((pp)->kp_proc . field)
  320. #define EP(pp, field) ((pp)->kp_eproc . field)
  321. #define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
  322. /*
  323.  * these are for keeping track of the proc array 
  324.  */
  325. static int      nproc = 0;
  326. static int      onproc = -1;
  327. static struct kinfo_proc *pbase = 0;
  328. int
  329. sh_count_procs(char *procname)
  330. {
  331.     register int    i, ret = 0;
  332.     register struct kinfo_proc *pp;
  333.     static int      mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
  334.     if (sysctl(mib, 3, NULL, &nproc, NULL, 0) < 0)
  335.         return 0;
  336.     if (nproc > onproc || !pbase) {
  337.         if ((pbase = (struct kinfo_proc *) realloc(pbase,
  338.                                                    nproc +
  339.                                                    sizeof(struct
  340.                                                           kinfo_proc))) ==
  341.             0)
  342.             return -1;
  343.         onproc = nproc;
  344.         memset(pbase, 0, nproc + sizeof(struct kinfo_proc));
  345.     }
  346.     if (sysctl(mib, 3, pbase, &nproc, NULL, 0) < 0)
  347.         return -1;
  348.     for (pp = pbase, i = 0; i < nproc / sizeof(struct kinfo_proc);
  349.          pp++, i++) {
  350.         if (PP(pp, p_stat) != 0 && (((PP(pp, p_flag) & P_SYSTEM) == 0))) {
  351.             if (PP(pp, p_stat) != SZOMB
  352.                 && !strcmp(PP(pp, p_comm), procname))
  353.                 ret++;
  354.         }
  355.     }
  356.     return ret;
  357. }
  358. #elif OSTYPE == LINUXID
  359. #include <dirent.h>
  360. #include <fcntl.h>
  361. #include <unistd.h>
  362. int
  363. sh_count_procs(char *procname)
  364. {
  365.     DIR *dir;
  366.     char cmdline[512], *tmpc;
  367.     struct dirent *ent;
  368. #ifdef USE_PROC_CMDLINE
  369.     int fd;
  370. #endif
  371.     int len,plen=strlen(procname),total = 0;
  372.     FILE *status;
  373.     if ((dir = opendir("/proc")) == NULL) return -1;
  374.     while (NULL != (ent = readdir(dir))) {
  375.       if(!(ent->d_name[0] >= '0' && ent->d_name[0] <= '9')) continue;
  376. #ifdef USE_PROC_CMDLINE  /* old method */
  377.       /* read /proc/XX/cmdline */
  378.       sprintf(cmdline,"/proc/%s/cmdline",ent->d_name);
  379.       if((fd = open(cmdline, O_RDONLY)) < 0) break;
  380.       len = read(fd,cmdline,sizeof(cmdline) - 1);
  381.       close(fd);
  382.       if(len <= 0) continue;
  383.       cmdline[len] = 0;
  384.       while(--len && !cmdline[len]);
  385.       while(--len) if(!cmdline[len]) cmdline[len] = ' ';
  386.       if(!strncmp(cmdline,procname,plen)) total++;
  387. #else
  388.       /* read /proc/XX/status */
  389.       sprintf(cmdline,"/proc/%s/status",ent->d_name);
  390.       if ((status = fopen(cmdline, "r")) == NULL)
  391.           break;
  392.       if (fgets(cmdline, sizeof(cmdline), status) == NULL) {
  393.           fclose(status);
  394.           break;
  395.       }
  396.       fclose(status);
  397.       cmdline[sizeof(cmdline)-1] = '';
  398.       /* XXX: assumes Name: is first */
  399.       if (strncmp("Name:",cmdline, 5) != 0)
  400.           break;
  401.       tmpc = skip_token(cmdline);
  402.       if (!tmpc)
  403.           break;
  404.       for (len=0;; len++) {
  405. if (tmpc[len] && isgraph(tmpc[len])) continue;
  406. tmpc[len]='';
  407. break;
  408.       }
  409.       DEBUGMSGTL(("proc","Comparing wanted %s against %sn",
  410.                   procname, tmpc));
  411.       if(len==plen && !strncmp(tmpc,procname,plen)) {
  412.           total++;
  413.           DEBUGMSGTL(("proc", " Matched.  total count now=%dn", total));
  414.       }
  415. #endif      
  416.     }
  417.     closedir(dir);
  418.     return total;
  419. }
  420. #elif OSTYPE == ULTRIXID
  421. #define NPROCS 32      /* number of proces to read at once */
  422. extern int      kmem, mem, swap;
  423. #include <sys/user.h>
  424. #include <sys/proc.h>
  425. #include <sys/file.h>
  426. #include <sys/vm.h>
  427. #include <machine/pte.h>
  428. #ifdef HAVE_NLIST_H
  429. #include <nlist.h>
  430. #endif
  431. static struct user *getuser(struct proc *);
  432. static int      getword(off_t);
  433. static int      getstruct(off_t, char *, off_t, int);
  434. static struct nlist proc_nl[] = {
  435.     {"_nproc"},
  436. #define X_NPROC 0
  437.     {"_proc"},
  438. #define X_PROC 1
  439.     {"_proc_bitmap"},
  440. #define X_PROC_BITMAP 2
  441.     {NULL}
  442. };
  443. int
  444. sh_count_procs(char *procname)
  445. {
  446.     int             total, proc_active, nproc;
  447.     int             thisproc = 0;
  448.     int             absolute_proc_number = -1;
  449.     struct user    *auser;
  450.     struct proc    *aproc, *procp;
  451.     unsigned        bitmap;
  452.     struct proc     procs[NPROCS], *procsp;
  453.     static int      inited = 0;
  454.     procp = (struct proc *) getword(proc_nl[X_PROC].n_value);
  455.     nproc = getword(proc_nl[X_NPROC].n_value);
  456.     total = 0;
  457.     for (;;) {
  458.         do {
  459.             while (thisproc == 0) {
  460.                 int             nread;
  461.                 int             psize;
  462.                 if (nproc == 0)
  463.                     return (total);
  464.                 thisproc = MIN(NPROCS, nproc);
  465.                 psize = thisproc * sizeof(struct proc);
  466.                 nproc -= thisproc;
  467.                 if (lseek(kmem, (off_t) procp, L_SET) == -1 ||
  468.                     (nread = read(kmem, (char *) procs, psize)) < 0) {
  469.                     /*
  470.                      * warn("read proc"); 
  471.                      */
  472.                     return (total);
  473.                 } else if (nread != psize) {
  474.                     thisproc = nread / sizeof(struct proc);
  475.                     nproc = 0;
  476.                     /*
  477.                      * warn("read proc: short read"); 
  478.                      */
  479.                 }
  480.                 procsp = procs;
  481.                 procp += thisproc;
  482.             }
  483.             aproc = procsp++;
  484.             thisproc--;
  485.             absolute_proc_number++;
  486.             if ((absolute_proc_number % 32) == 0)
  487.                 bitmap =
  488.                     getword((unsigned int) proc_nl[X_PROC_BITMAP].n_value +
  489.                             ((absolute_proc_number / 32) * 4));
  490.             proc_active =
  491.                 (bitmap & (1 << (absolute_proc_number % 32))) != 0;
  492.             if (proc_active && aproc->p_stat != SZOMB
  493.                 && !(aproc->p_type & SWEXIT))
  494.                 auser = getuser(aproc);
  495.         } while (!proc_active || auser == NULL);
  496.         if (strcmp(auser->u_comm, procname) == 0)
  497.             total++;
  498.     }
  499. }
  500. #define SW_UADDR dtob(getword((off_t)dmap.dm_ptdaddr))
  501. #define SW_UBYTES sizeof(struct user)
  502. #define SKRD(file, src, dst, size)
  503. (lseek(file, (off_t)(src), L_SET) == -1) ||
  504. (read(file, (char *)(dst), (size)) != (size))
  505. static struct user *
  506. getuser(struct proc *aproc)
  507. {
  508.     static union {
  509.         struct user     user;
  510.         char            upgs[UPAGES][NBPG];
  511.     } u;
  512.     static struct pte uptes[UPAGES];
  513.     static struct dmap dmap;
  514.     int             i, nbytes;
  515.     /*
  516.      * If process is not in core, we simply snarf it's user struct
  517.      * from the swap device.
  518.      */
  519.     if ((aproc->p_sched & SLOAD) == 0) {
  520.         if (!getstruct
  521.             ((off_t) aproc->p_smap, "aproc->p_smap", (off_t) & dmap,
  522.              sizeof(dmap))) {
  523.             /*
  524.              * warnx("can't read dmap for pid %d from %s", aproc->p_pid,
  525.              * _PATH_DRUM); 
  526.              */
  527.             return (NULL);
  528.         }
  529.         if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  530.             /*
  531.              * warnx("can't read u for pid %d from %s", aproc->p_pid, _PATH_DRUM); 
  532.              */
  533.             return (NULL);
  534.         }
  535.         return (&u.user);
  536.     }
  537.     /*
  538.      * Process is in core.  Follow p_addr to read in the page
  539.      * table entries that map the u-area and then read in the
  540.      * physical pages that comprise the u-area.
  541.      *
  542.      * If at any time, an lseek() or read() fails, print a warning
  543.      * message and return NULL.
  544.      */
  545.     if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
  546.         /*
  547.          * warnx("can't read user pt for pid %d from %s", aproc->p_pid, _PATH_DRUM); 
  548.          */
  549.         return (NULL);
  550.     }
  551.     nbytes = sizeof(struct user);
  552.     for (i = 0; i < UPAGES && nbytes > 0; i++) {
  553.         if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
  554.             /*
  555.              * warnx("can't read user page %u for pid %d from %s",
  556.              * uptes[i].pg_pfnum, aproc->p_pid, _PATH_MEM); 
  557.              */
  558.             return (NULL);
  559.         }
  560.         nbytes -= NBPG;
  561.     }
  562.     return (&u.user);
  563. }
  564. static int
  565. getword(off_t loc)
  566. {
  567.     int             val;
  568.     if (SKRD(kmem, loc, &val, sizeof(val)))
  569.         exit(1);
  570.     return (val);
  571. }
  572. static int
  573. getstruct(off_t loc, char *name, off_t dest, int size)
  574. {
  575.     if (SKRD(kmem, loc, dest, size))
  576.         return (0);
  577.     return (1);
  578. }
  579. #elif OSTYPE == SOLARISID
  580. #ifdef _SLASH_PROC_METHOD_
  581. #include <fcntl.h>
  582. #include <dirent.h>
  583. #include <procfs.h>
  584. /*
  585.  * Gets process information from /proc/.../psinfo
  586.  */
  587. int
  588. sh_count_procs(char *procname)
  589. {
  590.     int             fd, total = 0;
  591.     struct psinfo   info;
  592.     char            fbuf[32];
  593.     struct dirent  *ent;
  594.     DIR            *dir;
  595.     if (!(dir = opendir("/proc"))) {
  596.         snmp_perror("/proc");
  597.         return -1;
  598.     }
  599.     while ((ent = readdir(dir))) {
  600.         if (!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "."))
  601.             continue;
  602.         snprintf(fbuf, sizeof fbuf, "/proc/%s/psinfo", ent->d_name);
  603.         if ((fd = open(fbuf, O_RDONLY)) < 0) {  /* Continue or return error? */
  604.             snmp_perror(fbuf);
  605.     continue;
  606.         }
  607.         if (read(fd, (char *) &info, sizeof(struct psinfo)) !=
  608.             sizeof(struct psinfo)) {
  609.             snmp_perror(fbuf);
  610.             close(fd);
  611.             closedir(dir);
  612.             return -1;
  613.         }
  614.         if (!info.pr_nlwp && !info.pr_lwp.pr_lwpid) {
  615.             /*
  616.              * Zombie process 
  617.              */
  618.         } else {
  619.             DEBUGMSGTL(("proc","Comparing wanted %s against %sn",
  620.                         procname, info.pr_fname));
  621.             if (!strcmp(procname, info.pr_fname)) {
  622.                 total++;
  623.                 DEBUGMSGTL(("proc", " Matched.  total count now=%dn", total));
  624.             }
  625.         }
  626.         close(fd);
  627.     }
  628.     closedir(dir);
  629.     return total;
  630. }
  631. #else                           /* _SLASH_PROC_METHOD_ */
  632. #define _KMEMUSER               /* Needed by <sys/user.h> */
  633. #include <kvm.h>
  634. #include <fcntl.h>
  635. #include <sys/user.h>
  636. #include <sys/proc.h>
  637. int
  638. sh_count_procs(char *procname)
  639. {
  640.     struct proc    *p;
  641.     struct user    *u;
  642.     int             total;
  643.     if (kd == NULL) {
  644.         return -1;
  645.     }
  646.     if (kvm_setproc(kd) < 0) {
  647.         return (-1);
  648.     }
  649.     kvm_setproc(kd);
  650.     total = 0;
  651.     while ((p = kvm_nextproc(kd)) != NULL) {
  652.         if (!p) {
  653.             return (-1);
  654.         }
  655.         u = kvm_getu(kd, p);
  656.         /*
  657.          * Skip this entry if u or u->u_comm is a NULL pointer 
  658.          */
  659.         if (!u) {
  660.             continue;
  661.         }
  662.         if (strcmp(procname, u->u_comm) == 0)
  663.             total++;
  664.     }
  665.     return (total);
  666. }
  667. #endif                          /* _SLASH_PROC_METHOD_ */
  668. #else
  669. int
  670. sh_count_procs(char *procname)
  671. {
  672.     char            line[STRMAX], *cptr, *cp;
  673.     int             ret = 0, fd;
  674.     FILE           *file;
  675. #ifndef EXCACHETIME
  676. #endif
  677.     struct extensible ex;
  678.     int             slow = strstr(PSCMD, "ax") != NULL;
  679.     strcpy(ex.command, PSCMD);
  680.     if ((fd = get_exec_output(&ex)) >= 0) {
  681.         if ((file = fdopen(fd, "r")) == NULL) {
  682.             setPerrorstatus("fdopen");
  683.             close(fd);
  684.             return (-1);
  685.         }
  686.         while (fgets(line, sizeof(line), file) != NULL) {
  687.             if (slow) {
  688.                 cptr = find_field(line, 5);
  689.                 cp = strrchr(cptr, '/');
  690.                 if (cp)
  691.                     cptr = cp + 1;
  692.                 else if (*cptr == '-')
  693.                     cptr++;
  694.                 else if (*cptr == '[') {
  695.                     cptr++;
  696.                     cp = strchr(cptr, ']');
  697.                     if (cp)
  698.                         *cp = 0;
  699.                 }
  700.                 copy_nword(cptr, line, sizeof(line));
  701.                 cp = line + strlen(line) - 1;
  702.                 if (*cp == ':')
  703.                     *cp = 0;
  704.             } else {
  705.                 if ((cptr = find_field(line, LASTFIELD)) == NULL)
  706.                     continue;
  707.                 copy_nword(cptr, line, sizeof(line));
  708.             }
  709.             if (!strcmp(line, procname))
  710.                 ret++;
  711.         }
  712.         if (ftell(file) < 2) {
  713. #ifdef USING_UCD_SNMP_ERRORMIB_MODULE
  714.             seterrorstatus("process list unreasonable short (mem?)", 2);
  715. #endif
  716.             ret = -1;
  717.         }
  718.         fclose(file);
  719.         wait_on_exec(&ex);
  720.     } else {
  721.         ret = -1;
  722.     }
  723.     return (ret);
  724. }
  725. #endif