/* * call-seq: * ProcTable.ps(pid=nil) * ProcTable.ps(pid=nil){ |ps| ... } * * In block form, yields a ProcTableStruct for each process entry that you * have rights to. This method returns an array of ProcTableStruct's in * non-block form. * * If a +pid+ is provided, then only a single ProcTableStruct is yielded or * returned, or nil if no process information is found for that +pid+. */ static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){ int err; char state[8]; struct kinfo_proc* procs; VALUE v_pid, v_tty_num, v_tty_dev, v_start_time; VALUE v_pstruct = Qnil; VALUE v_array = rb_ary_new(); size_t length, count; size_t i = 0; char args[ARGS_MAX_LEN+1]; // Passed into sysctl call static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; rb_scan_args(argc, argv, "01", &v_pid); // Get size of proc kproc buffer err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0); if(err == -1) rb_raise(cProcTableError, "sysctl: %s", strerror(errno)); // Populate the kproc buffer procs = malloc(length); if(procs == NULL) rb_raise(cProcTableError, "malloc: %s", strerror(errno)); err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0); if(err == -1) rb_raise(cProcTableError, "sysctl: %s", strerror(errno)); // If we're here, we got our list count = length / sizeof(struct kinfo_proc); for(i = 0; i < count; i++) { v_tty_num = Qnil; v_tty_dev = Qnil; v_start_time = Qnil; // If a PID is provided, skip unless the PID matches if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) ) continue; *args = '\0'; /* Query the command line args */ /* TODO: Cmd line not working for now - fix */ /*args_mib[ARGS_MIB_LEN - 1] = procs[i].kp_proc.p_pid; args_err = sysctl( (int *) args_mib, ARGS_MIB_LEN, args, &args_size, NULL, 0); if(args_err >= 0) { fprintf(stderr, "Ret: %d LEN: %d\n", err, args_size); char *c; for(c = args; c < args+args_size; c++) if(*c == '\0') *c = ' '; args[args_size] = '\0'; } else { fprintf(stderr, "err: %s LEN: %d\n", strerror(errno), args_size); }*/ char cmdline[ARGS_MAX_LEN+1]; argv_of_pid(procs[i].kp_proc.p_pid, &cmdline); /* free(cmdline); */ // Get the start time of the process v_start_time = rb_time_new( procs[i].kp_proc.p_un.__p_starttime.tv_sec, procs[i].kp_proc.p_un.__p_starttime.tv_usec ); // Get the state of the process switch(procs[i].kp_proc.p_stat) { case SIDL: strcpy(state, "idle"); break; case SRUN: strcpy(state, "run"); break; case SSLEEP: strcpy(state, "sleep"); break; case SSTOP: strcpy(state, "stop"); break; case SZOMB: strcpy(state, "zombie"); break; default: strcpy(state, "unknown"); break; } // Get ttynum and ttydev. If ttynum is -1, there is no tty. if(procs[i].kp_eproc.e_tdev != -1){ v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev), v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR)); } v_pstruct = rb_struct_new( sProcStruct, INT2FIX(procs[i].kp_proc.p_pid), INT2FIX(procs[i].kp_eproc.e_ppid), INT2FIX(procs[i].kp_eproc.e_pgid), INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid), INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid), rb_str_new2(procs[i].kp_proc.p_comm), rb_str_new2(state), rb_float_new(procs[i].kp_proc.p_pctcpu), Qnil, v_tty_num, v_tty_dev, rb_str_new2(procs[i].kp_eproc.e_wmesg), INT2FIX(procs[i].kp_proc.p_rtime.tv_sec), INT2FIX(procs[i].kp_proc.p_priority), INT2FIX(procs[i].kp_proc.p_usrpri), INT2FIX(procs[i].kp_proc.p_nice), rb_str_new2(cmdline), v_start_time, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil ); OBJ_FREEZE(v_pstruct); // This is read-only data if(rb_block_given_p()) rb_yield(v_pstruct); else rb_ary_push(v_array, v_pstruct); } if(procs) free(procs); if(!rb_block_given_p()){ if(NIL_P(v_pid)) return v_array; else return v_pstruct; } return Qnil; }
/* * call-seq: * ProcTable.ps(pid=nil) * ProcTable.ps(pid=nil){ |ps| ... } * * In block form, yields a ProcTableStruct for each process entry that you * have rights to. This method returns an array of ProcTableStruct's in * non-block form. * * If a +pid+ is provided, then only a single ProcTableStruct is yielded or * returned, or nil if no process information is found for that +pid+. */ static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){ int err; char state[8]; struct kinfo_proc* procs; VALUE v_pid, v_tty_num, v_tty_dev, v_start_time; VALUE v_pstruct = Qnil; VALUE v_array = rb_ary_new(); size_t length, count; size_t i = 0; int g; VALUE v_cmdline, v_exe, v_environ, v_groups; // Passed into sysctl call static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; rb_scan_args(argc, argv, "01", &v_pid); // Get size of proc kproc buffer err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0); if(err == -1) rb_raise(cProcTableError, "sysctl: %s", strerror(errno)); // Populate the kproc buffer procs = ruby_xmalloc(length); err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0); if(err == -1) rb_raise(cProcTableError, "sysctl: %s", strerror(errno)); // If we're here, we got our list count = length / sizeof(struct kinfo_proc); for(i = 0; i < count; i++) { v_tty_num = Qnil; v_tty_dev = Qnil; v_start_time = Qnil; // If a PID is provided, skip unless the PID matches if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) ) continue; // cmdline will be set only if process exists and belongs to current user or // current user is root v_cmdline = Qnil; v_exe = Qnil; v_environ = Qnil; argv_of_pid(procs[i].kp_proc.p_pid, &v_cmdline, &v_exe, &v_environ); // Get the start time of the process v_start_time = rb_time_new( procs[i].kp_proc.p_un.__p_starttime.tv_sec, procs[i].kp_proc.p_un.__p_starttime.tv_usec ); // Get the state of the process switch(procs[i].kp_proc.p_stat) { case SIDL: strcpy(state, "idle"); break; case SRUN: strcpy(state, "run"); break; case SSLEEP: strcpy(state, "sleep"); break; case SSTOP: strcpy(state, "stop"); break; case SZOMB: strcpy(state, "zombie"); break; default: strcpy(state, "unknown"); break; } // Get ttynum and ttydev. If ttynum is -1, there is no tty. if(procs[i].kp_eproc.e_tdev != -1){ v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev), v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR)); } v_groups = rb_ary_new(); for (g = 0; g < procs[i].kp_eproc.e_ucred.cr_ngroups; ++g) rb_ary_push(v_groups, INT2FIX(procs[i].kp_eproc.e_ucred.cr_groups[g])); v_pstruct = rb_struct_new( sProcStruct, INT2FIX(procs[i].kp_proc.p_pid), INT2FIX(procs[i].kp_eproc.e_ppid), INT2FIX(procs[i].kp_eproc.e_pgid), INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid), INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid), INT2FIX(procs[i].kp_eproc.e_ucred.cr_uid), rb_ary_entry(v_groups, 0), v_groups, INT2FIX(procs[i].kp_eproc.e_pcred.p_svuid), INT2FIX(procs[i].kp_eproc.e_pcred.p_svgid), rb_str_new2(procs[i].kp_proc.p_comm), rb_str_new2(state), rb_float_new(procs[i].kp_proc.p_pctcpu), Qnil, v_tty_num, v_tty_dev, rb_str_new2(procs[i].kp_eproc.e_wmesg), INT2FIX(procs[i].kp_proc.p_rtime.tv_sec), INT2FIX(procs[i].kp_proc.p_priority), INT2FIX(procs[i].kp_proc.p_usrpri), INT2FIX(procs[i].kp_proc.p_nice), v_cmdline, v_exe, v_environ, v_start_time, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil, (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil ); OBJ_FREEZE(v_pstruct); // This is read-only data if(rb_block_given_p()) rb_yield(v_pstruct); else rb_ary_push(v_array, v_pstruct); } if(procs) free(procs); if(!rb_block_given_p()){ if(NIL_P(v_pid)) return v_array; else return v_pstruct; } return Qnil; }