home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <linux/param.h>
- #include <limits.h>
- #include <time.h>
- #include "netconf.h"
- #include "../xconf/xconf.h"
- #include "netconf.m"
-
- /*
- Read the first line of a file
- Return -1 if any error.
- */
- static int process_readfile (const char *path, char *buf, int sizebuf)
- {
- int ret = -1;
- // No error message signaled as "path" is a file under /proc/pid
- // and the process may vanish while we are reading it.
- FILE *fin = fopen (path,"r");
- if (fin != NULL){
- if (fgets (buf,sizebuf-1,fin)!=NULL){
- ret = 0;
- }
- fclose (fin);
- }
- return ret;
- }
-
- struct PS_PROC {
- char cmdline[256], user[10], cmd[40], state, ttyc[4];
- int uid, pid, ppid, pgrp, session, tty, tpgid, utime, stime,
- cutime, cstime, counter, priority, start_time, signal, blocked,
- sigignore, sigcatch;
- unsigned int flags, min_flt, cmin_flt, maj_flt, cmaj_flt, timeout,
- it_real_value, vsize, rss, rss_rlim, start_code, end_code,
- start_stack, kstk_esp, kstk_eip, wchan;
- };
- /*
- Read the file /proc/pid/stat into the struct PS_PROC
- Return -1 if any error.
- */
-
- static int process_readstat(int pid, PS_PROC &_psp)
- {
- int ret = -1;
- char tmppath[PATH_MAX];
- sprintf (tmppath,"/proc/%d/stat",pid);
- char buf[PATH_MAX];
- if (process_readfile (tmppath,buf,sizeof(buf))!=-1){
- PS_PROC psp;
- sscanf(buf, "%d %s %c %d %d %d %d %d %u %u "
- "%u %u %u %d %d %d %d %d %d %u "
- "%u %d %u %u %u %u %u %u %u %u %u "
- "%u %u %u %u\n",
- &psp.pid, psp.cmd, &psp.state, &psp.ppid,
- &psp.pgrp, &psp.session, &psp.tty, &psp.tpgid,
- &psp.flags, &psp.min_flt, &psp.cmin_flt,
- &psp.maj_flt, &psp.cmaj_flt,
- &psp.utime, &psp.stime, &psp.cutime, &psp.cstime,
- &psp.counter, &psp.priority, &psp.timeout,
- &psp.it_real_value, &psp.start_time,
- &psp.vsize, &psp.rss, &psp.rss_rlim,
- &psp.start_code, &psp.end_code, &psp.start_stack,
- &psp.kstk_esp, &psp.kstk_eip,
- &psp.signal, &psp.blocked, &psp.sigignore, &psp.sigcatch,
- &psp.wchan);
- _psp = psp;
- ret = 0;
- }
- return ret;
- }
-
-
- /*
- Information about a process ID
- */
- PUBLIC PROC::PROC (int _pid, PROC *_next)
- {
- next = _next;
- pid = _pid;
- path = NULL;
- name = NULL;
- char tmppath[PATH_MAX];
- sprintf (tmppath,"/proc/%d/cmdline",_pid);
- char buf[PATH_MAX];
- PS_PROC psp;
- if (process_readfile (tmppath,buf,sizeof(buf))!=-1){
- if (sscanf (buf,"%s",tmppath)==1){
- // Small patch for sendmail
- char *pt = strchr(tmppath,':');
- if (pt != NULL) *pt = '\0';
- path = strdup(tmppath);
- }
- }else if (process_readstat(_pid,psp)!=-1){
- strcpy (buf,psp.cmd[0] == '(' ? psp.cmd+1 : psp.cmd);
- char *pt = strchr(buf,')');
- if (pt != NULL) *pt = '\0';
- path = strdup(buf);
- }
- if (path != NULL){
- name = strrchr(path,'/');
- if (name != NULL){
- name++;
- }else{
- name = path;
- }
- }
- }
- PUBLIC PROC::~PROC ()
- {
- free (path);
- }
- /*
- Return the next PROC in the list or NULL.
- */
- PUBLIC PROC *PROC::getnext ()
- {
- return next;
- }
- /*
- Return != 0 if the information on the process was read properly.
- */
- PUBLIC int PROC::isok ()
- {
- return path != NULL;
- }
-
- /*
- Return the path (command line) of a process
- */
- PUBLIC const char *PROC::getpath ()
- {
- return path;
- }
- /*
- Return the name (command line) of a process
- */
- PUBLIC const char *PROC::getname ()
- {
- return name;
- }
- /*
- Send a signal to the process.
- */
- PUBLIC int PROC::kill (int signo)
- {
- int ret = 0;
- if (!simul_ison()){
- ret = ::kill (pid,signo);
- }
- return ret;
- }
- /*
- Return the start time of a process.
- Return -1 is the process is dead.
- */
- PUBLIC long PROC::getstarttime ()
- {
- long ret = -1;
- long uptime;
- char buf[200];
- if (process_readfile ("/proc/uptime",buf,sizeof(buf))!=-1){
- uptime = atoi(buf);
- PS_PROC psp;
- if (process_readstat(pid,psp)!=-1){
- long seconds = (((uptime * 100) - psp.start_time) / HZ);
- ret = time(NULL) - seconds;
- }
- }
- return ret;
- }
-
- static PROC *first = NULL;
-
- /*
- Read all the process currently active and store for usage by
- other process_function.
- The info is kept for all process_find and isalive call. It
- is flushed when process_read is called again.
- */
- int process_read()
- {
- while (first != NULL){
- PROC *next = first->getnext();
- delete first;
- first = next;
- }
- static char *cmd_ls = "/bin/ls /proc/*/cmdline 2>/dev/null";
- FILE *fin = popen (cmd_ls,"r");
- int nbproc = -1;
- if (fin == NULL){
- xconf_error (MSG_U(E_CANTEXEC,"Can't execute command %s\n"));
- }else{
- nbproc = 0;
- char buf[PATH_MAX+1];
- while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
- if (buf[0] == '/'){
- int pid = atoi(buf+6);
- if (pid != 0){
- PROC *prc = new PROC (pid,first);
- if (prc->isok()){
- first = prc;
- nbproc++;
- }else{
- delete prc;
- }
- }
- }
- }
- pclose (fin);
- }
- return nbproc;
- }
-
- static PROC *process_find(const char *path, const char *name)
- {
- PROC *ret = first;
- while (ret != NULL){
- const char *ppath = ret->getpath();
- const char *pname = ret->getname();
- if (strcmp(path,ppath)==0
- || strcmp(name,pname)==0){
- break;
- }else{
- ret = ret->getnext();
- }
- }
- return ret;
- }
- /*
- Check if a process is running at least once
- Return -1 or the start time of this process.
- */
- PROC *process_find (const char *path)
- {
- /* #Specification: process / lookup / strategy
- When looking for a process, we search first for the exact path
- (command line). If this fail, then we use the name only without
- path. This should be safe enough to prevent mistake.
- */
- if (first == NULL) process_read ();
- const char *name = strrchr (path,'/');
- name = name == NULL ? path : name + 1;
- PROC *ret = process_find (path,"");
- if (ret == NULL) ret = process_find ("",name);
- return ret;
- }
-
- /*
- Check if a process is running at least once
- Return -1 or the start time of this process.
- */
- long process_isactive (const char *path)
- {
- PROC *prc = process_find (path);
- long ret = -1;
- if (prc != NULL) ret = prc->getstarttime();
- return ret;
- }
-
- #ifdef TEST
-
- int main (int argc, char *argv[])
- {
- for (int i=1; i<argc; i++){
- long start = process_isactive(argv[i]);
- printf ("%s -> ",argv[i]);
- if (start == -1){
- printf ("nil\n");
- }else{
- printf ("%ld %s\n",start,ctime(&start));
- }
- }
- return 0;
- }
-
- #endif
-
-