Exemplo n.º 1
0
int
netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags)
{
    int	                 mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
    size_t               buf_size, mib_size = sizeof(mib)/sizeof(mib[0]);
    struct kinfo_proc   *processes = NULL;
    struct proc_taskallinfo taskinfo;
    netsnmp_swrun_entry *entry;
    int                  rc, num_entries, i;

    DEBUGMSGTL(("swrun:load:arch"," load\n"));

    /*
     * get size to allocate. This introduces a bit of a race condition,
     * as the size could change between this call and the next...
     */
    rc = sysctl(mib, mib_size, NULL, &buf_size, NULL, 0);
    if (rc < 0) {
        snmp_log(LOG_ERR, "KERN_PROC_ALL size sysctl failed: %d\n", rc);
        return -1;
    }

    processes = (struct kinfo_proc*) malloc(buf_size);
    if (NULL == processes) {
        snmp_log(LOG_ERR, "malloc failed\n");
        return -1;
    }

    rc = sysctl(mib, mib_size, processes, &buf_size, NULL, 0);
    if (rc < 0) {
        snmp_log(LOG_ERR, "KERN_PROC_ALL sysctl failed: %d\n", rc);
        free(processes);
        return -1;
    }
    
    num_entries = buf_size / sizeof(struct kinfo_proc);
    
    for (i = 0; i < num_entries; i++) {
        /*
         * skip empty names.
         * p_stat = (SIDL|SRUN|SSLEEP|SSTOP|SZOMB)
         */
        if (('\0' == processes[i].kp_proc.p_comm[0]) ||
            (0 == processes[i].kp_proc.p_pid)) {
            DEBUGMSGTL(("swrun:load:arch",
                        " skipping p_comm '%s', pid %5d, p_pstat %d\n",
                        processes[i].kp_proc.p_comm ? 
                        processes[i].kp_proc.p_comm : "NULL",
                        processes[i].kp_proc.p_pid,
                        processes[i].kp_proc.p_stat));
            continue;
        }

        DEBUGMSGTL(("swrun:load:arch"," %s pid %5d\n",
                    processes[i].kp_proc.p_comm,
                    processes[i].kp_proc.p_pid));

        entry = netsnmp_swrun_entry_create(processes[i].kp_proc.p_pid);
        if (NULL == entry)
            continue; /* error already logged by function */
        rc = CONTAINER_INSERT(container, entry);

        /*
         * p_comm is a partial name, but it is all we have at this point.
         */
        entry->hrSWRunName_len = snprintf(entry->hrSWRunName,
                                          sizeof(entry->hrSWRunName)-1,
                                          "%s", processes[i].kp_proc.p_comm);

        /** sysctl for name, path, params */
        rc = _set_command_name(entry);

        /*
         * map p_stat to RunStatus. Odd that there is no 'running' status.
         */
        switch(processes[i].kp_proc.p_stat) {
            case SRUN:
                entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE;
                break;
            case SSLEEP:
            case SSTOP:
                entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE;
                break;
            case SIDL:
            case SZOMB:
            default:
                entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID;
                break;
        } 

        /*
         * check for system processes
         */
        if (P_SYSTEM & processes[i].kp_proc.p_flag) {
            entry->hrSWRunType = HRSWRUNTYPE_OPERATINGSYSTEM;
            DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "SYSTEM\n"));
        }
        else entry->hrSWRunType = HRSWRUNTYPE_APPLICATION;

        /*
         * get mem size, run time
         */
        rc = proc_pidinfo( processes[i].kp_proc.p_pid, PROC_PIDTASKALLINFO, 0,
                           &taskinfo, sizeof(taskinfo));
        if (sizeof(taskinfo) != rc) {
            DEBUGMSGTL(("swrun:load:arch", " proc_pidinfo returned %d\n", rc));
        }
        else {
            uint64_t task_mem = taskinfo.ptinfo.pti_resident_size / 1024;
            union {
                u_quad_t     uq; /* u_int64_t */
                UnsignedWide uw; /* struct u_int32_t hi/lo */
            } at, ns;
            at.uq = taskinfo.ptinfo.pti_total_user +
                    taskinfo.ptinfo.pti_total_system;
            ns = at;
            ns.uq = ns.uq / 10000000LL; /* nano to deci */
            if (task_mem > INT32_MAX) {
                DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "mem overflow\n"));
                task_mem = INT32_MAX;
            }
            if (ns.uq > INT32_MAX) {
                DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "time overflow\n"));
                ns.uq = INT32_MAX;
            }
            entry->hrSWRunPerfMem = task_mem;
            entry->hrSWRunPerfCPU = ns.uq;
        }
    }
    free(processes);

    DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n",
                (int)CONTAINER_SIZE(container)));

    return 0;
}
Exemplo n.º 2
0
/* ---------------------------------------------------------------------
 */
int
netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags)
{
    DIR                 *procdir = NULL;
    struct dirent       *procentry_p;
    FILE                *fp;
    int                  pid, i;
    char                 buf[BUFSIZ], buf2[BUFSIZ], *cp;
    netsnmp_swrun_entry *entry;
    
    procdir = opendir("/proc");
    if ( NULL == procdir ) {
        snmp_log( LOG_ERR, "Failed to open /proc" );
        return -1;
    }

    /*
     * Walk through the list of processes in the /proc tree
     */
    while ( NULL != (procentry_p = readdir( procdir ))) {
        pid = atoi( procentry_p->d_name );
        if ( 0 == pid )
            continue;   /* Presumably '.' or '..' */

        entry = netsnmp_swrun_entry_create(pid);
        if (NULL == entry)
            continue;   /* error already logged by function */

        /*
         * Now extract the interesting information
         *   from the various /proc{PID}/ interface files
         */

        /*
         *   Name:  process name
         */
        snprintf( buf2, BUFSIZ, "/proc/%d/status", pid );
        fp = fopen( buf2, "r" );
        if (!fp) {
            netsnmp_swrun_entry_free(entry);
            continue; /* file (process) probably went away */
	}
        memset(buf, 0, sizeof(buf));
        if (fgets( buf, BUFSIZ-1, fp ) == NULL) {
            fclose(fp);
            netsnmp_swrun_entry_free(entry);
            continue;
        }
        fclose(fp);

        for ( cp = buf; *cp != ':'; cp++ )
            ;
        while (isspace(*(++cp)))	/* Skip ':' and following spaces */
            ;
        entry->hrSWRunName_len = snprintf(entry->hrSWRunName,
                                   sizeof(entry->hrSWRunName)-1, "%s", cp);
        if ( '\n' == entry->hrSWRunName[ entry->hrSWRunName_len-1 ]) {
            entry->hrSWRunName[ entry->hrSWRunName_len-1 ] = '\0';
            entry->hrSWRunName_len--;           /* Stamp on trailing newline */
        }

        /*
         *  Command Line:
         *     argv[0] '\0' argv[1] '\0' ....
         */
        snprintf( buf2, BUFSIZ, "/proc/%d/cmdline", pid );
        fp = fopen( buf2, "r" );
        if (!fp) {
            netsnmp_swrun_entry_free(entry);
            continue; /* file (process) probably went away */
	}
        memset(buf, 0, sizeof(buf));
        if ((cp = fgets( buf, BUFSIZ-1, fp )) == NULL) {
            fclose(fp);
            netsnmp_swrun_entry_free(entry);
            continue;
        }
        fclose(fp);

        if ( cp ) {
            /*
             *     argv[0]   is hrSWRunPath
             */ 
            entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath,
                                       sizeof(entry->hrSWRunPath)-1, "%s", buf);
            /*
             * Stitch together argv[1..] to construct hrSWRunParameters
             */
            cp = buf + entry->hrSWRunPath_len+1;
            while ( 1 ) {
                while (*cp)
                    cp++;
                if ( '\0' == *(cp+1))
                    break;      /* '\0''\0' => End of command line */
                *cp = ' ';
            }
            entry->hrSWRunParameters_len
                = sprintf(entry->hrSWRunParameters, "%.*s",
                          (int)sizeof(entry->hrSWRunParameters) - 1,
                          buf + entry->hrSWRunPath_len + 1);
        } else {
            memcpy(entry->hrSWRunPath, entry->hrSWRunName, entry->hrSWRunName_len);
            entry->hrSWRunPath_len       = entry->hrSWRunName_len;
            entry->hrSWRunParameters_len = 0;
        }
 
        /*
         * XXX - No information regarding system processes vs applications
         */
        entry->hrSWRunType = HRSWRUNTYPE_APPLICATION;

        /*
         *   {xxx} {xxx} STATUS  {xxx}*10  UTIME STIME  {xxx}*8 RSS
         */
        snprintf( buf, BUFSIZ, "/proc/%d/stat", pid );
        fp = fopen( buf, "r" );
        if (!fp) {
            netsnmp_swrun_entry_free(entry);
            continue; /* file (process) probably went away */
	}
        if (fgets( buf, BUFSIZ-1, fp ) == NULL) {
            fclose(fp);
            netsnmp_swrun_entry_free(entry);
            continue;
        }
        fclose(fp);

        cp = buf;
        while ( ' ' != *(cp++))    /* Skip first field */
            ;
        while ( ' ' != *(cp++))    /* Skip second field */
            ;
        
        switch (*cp) {
        case 'R':  entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING;
                   break;
        case 'S':  entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE;
                   break;
        case 'D':
        case 'T':  entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE;
                   break;
        case 'Z':
        default:   entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID;
                   break;
        }
        for (i=10; i; i--) {   /* Skip STATUS + 10 fields */
            while (' ' != *(cp++))
                ;
            cp++;
        }
        entry->hrSWRunPerfCPU  = atoi( cp );   /*  utime */
        while ( ' ' != *(cp++))
            ;
        cp++;				   /* Skip utime */
        entry->hrSWRunPerfCPU += atoi( cp );   /* +stime */

        for (i=8; i; i--) {   /* Skip stime + 8 fields */
            while (' ' != *(cp++))
                ;
            cp++;
        }
        entry->hrSWRunPerfMem  = atoi( cp );   /*  rss */
        entry->hrSWRunPerfMem *= (getpagesize()/1024);  /* in kB */
        CONTAINER_INSERT(container, entry);
    }
    closedir( procdir );

    DEBUGMSGTL(("swrun:load:arch"," loaded %" NETSNMP_PRIz "d entries\n",
                CONTAINER_SIZE(container)));

    return 0;
}
Exemplo n.º 3
0
/* ---------------------------------------------------------------------
 */
int
netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags)
{
    struct kinfo_proc   *proc_table;
    int                  nprocs, i, rc;
    char                 buf[BUFSIZ], **argv, *cp;
    char                *name, *path;
    netsnmp_swrun_entry *entry;

    if ( 0 == kd ) {
        DEBUGMSGTL(("swrun:load:arch"," Can't query kvm info\n"));
        return 1;     /* No handle for retrieving process table */
    }
    proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs );
    for ( i=0 ; i<nprocs; i++ ) {
        if ( 0 == proc_table[i].SWRUN_K_STAT )
            continue;
        entry = netsnmp_swrun_entry_create(proc_table[i].SWRUN_K_PID);
        if (NULL == entry)
            continue;   /* error already logged by function */
        rc = CONTAINER_INSERT(container, entry);

        /*
         * There are two possible sources for the command being run:
         *   - SWRUN_K_COMM  (from the proc_table entry directly)
         *   - running kvm_getargv on the process entry.
         *
         * We'll use argv[0] (if set) for hrSWRunPath,
         *   since that might potentially contain the
         *   absolute path to the running binary.
         * We'll use SWRUN_K_COMM for hrSWRunName,
         *   and as an alternative for hrSWRunPath
         */
        argv = kvm_getargv( kd, &(proc_table[i]), 0);

        entry->hrSWRunName_len = snprintf(entry->hrSWRunName,
                                   sizeof(entry->hrSWRunName)-1,
                                          "%s", proc_table[i].SWRUN_K_COMM);

        if ( argv && *argv)
            entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath,
                                       sizeof(entry->hrSWRunPath)-1,
                                              "%s", argv[0]);
        else {
            memcpy( entry->hrSWRunPath, entry->hrSWRunName,
                                        entry->hrSWRunName_len );
            entry->hrSWRunPath_len = entry->hrSWRunName_len;
        }

        /*
         * Stitch together the rest of argv[] to build hrSWRunParameters
         *
         * Note:
         *   We add a separating space before each argv[] parameter,
         *   *including* the first one.  So we need to skip this
         *   leading space (buf[0]) when setting hrSWRunParameters.
         * This is also why we cleared the first *two* characters
         *   in the buffer initially. If there were no command-line
         *   arguments, then buf[1] would still be a null string.
         */
        buf[0] = '\0';
        buf[1] = '\0';
        if (argv)
            argv++;    /* Skip argv[0] */
        while ( argv && *argv ) {
            strcat(buf, " ");
            strcat(buf, *argv);
            argv++;
        }
        entry->hrSWRunParameters_len = snprintf(entry->hrSWRunParameters,
                                         sizeof(entry->hrSWRunParameters)-1,
                                          "%s", buf+1);

        entry->hrSWRunType = (P_SYSTEM & proc_table[i].SWRUN_K_FLAG) 
#ifdef SWRUN_K_CLASS
                             ? ((PRI_ITHD == proc_table[i].SWRUN_K_CLASS)
                                ? 3  /* device driver    */
                                : 2  /* operating system */
                               )
#else
                             ? 2  /* operating system */
#endif
                             : 4  /*  application     */
                             ;

        switch (proc_table[i].SWRUN_K_STAT) {
        case SRUN:    entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING;
                      break;
        case SSLEEP:
        case SWAIT:   entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE;
                      break;
        case SSTOP:
        case SLOCK:   entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE;
                      break;
        case SIDL:
        case SZOMB:
        default:      entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID;
                      break;
        }
        
#if defined(freebsd5) && __FreeBSD_version >= 500014
# ifdef NOT_DEFINED
   Apparently following these pointers triggers a SIG10 error

        entry->hrSWRunPerfCPU  = proc_table[i].ki_paddr->p_uticks;
        entry->hrSWRunPerfCPU += proc_table[i].ki_paddr->p_sticks;
        entry->hrSWRunPerfCPU += proc_table[i].ki_paddr->p_iticks;
        entry->hrSWRunPerfMem  = proc_table[i].ki_vmspace->vm_tsize;
        entry->hrSWRunPerfMem += proc_table[i].ki_vmspace->vm_ssize;
        entry->hrSWRunPerfMem += proc_table[i].ki_vmspace->vm_dsize;
        entry->hrSWRunPerfMem *= (getpagesize()/1024);  /* in kB */
# endif
        entry->hrSWRunPerfCPU  = proc_table[i].ki_runtime / 100000;
        entry->hrSWRunPerfMem  = proc_table[i].ki_size / 1024;;
#else
        /*
         * early FreeBSD, NetBSD, OpenBSD
         */
        entry->hrSWRunPerfCPU  = proc_table[i].kp_proc.p_uticks;
        entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_sticks;
        entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_iticks;
        entry->hrSWRunPerfMem  = proc_table[i].kp_eproc.e_vm.vm_tsize;
        entry->hrSWRunPerfMem += proc_table[i].kp_eproc.e_vm.vm_ssize;
        entry->hrSWRunPerfMem += proc_table[i].kp_eproc.e_vm.vm_dsize;
        entry->hrSWRunPerfMem *= (getpagesize() / 1024);
#endif
    }
    /*
     * 'proc_table' is owned by the kvm library,
     *   so shouldn't be freed here.
     */

    DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n",
                CONTAINER_SIZE(container)));

    return 0;
}