#include #include #include #include #include #include #include #include #include #include #include "monitortasks.m" static HELP_FILE help_choice ("monitortasks","killchoice"); /* 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_readppid (int pid) { 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); ret = psp.ppid; } return ret; } /* Locate the first process child of a given process */ static int killchoice_findchild (int pid) { pid_t ret = (pid_t)-1; SSTRINGS lst; int n = dir_getlist ("/proc",lst); for (int i=0; iget(); int child = atoi(dirpid); if (pid != 0){ int parent = process_readppid (child); if (parent == pid){ ret = child; break; } } } return ret; } int main (int argc, char *argv[]) { char bdict[30]; sprintf (bdict,"monitortasks-msg-%s",PACKAGE_REV); const char *packages[]={bdict,NULL}; (argc, argv,packages); xconf_notice (MSG_U(N_CHOICEUSAGE,"killchoice program-name pid [ args ]")); int ret = -1; if (argc == 2){ pid_t parent = atoi(argv[1]); pid_t pid = killchoice_findchild (parent); if (pid != (pid_t)-1){ DIALOG dia; dia.settype (DIATYPE_POPUP); char opt=0; dia.newf_radio ("",opt,0,MSG_U(I_KILLRUN ,"Terminate the process and start a new one")); dia.newf_radio ("",opt,1,MSG_U(I_RUNEW ,"Start a new one")); dia.newf_radio ("",opt,2,MSG_U(I_KILL ,"Terminate the process")); SSTRING intro; intro.setfromf (MSG_U(I_ALREADY ,"The program %s (process id %u) is already running\n" "It is unusual to start several instances of this program\n" "Pick the appropriate option"),argv[0],pid); int nof=0; if (dia.edit (MSG_U(T_ALREADY,"Process already running") ,intro.get() ,help_choice ,nof)==MENU_ACCEPT){ if (opt == 0 || opt == 2){ kill (pid,SIGTERM); // Wait until it it dead for (int i=0; i<5; i++){ if (kill(pid,0)!=-1){ sleep(1); }else{ break; } } if (kill(pid,0)!=-1) kill (pid,SIGKILL); } if (opt == 0 || opt == 1){ exit (0); }else{ exit (1); } } }else{ xconf_error (MSG_U(E_NOCHILD,"No child for process %u!!!") ,parent); } }else{ usage(); } return ret; return -1; }