diff --git a/Process.h.in b/Process.h.in index 313554ef1f4f3318cb2f9c0c57cf0103e4de6bfc..7f4ea19928d5d1c649c2826da20f66f09842cbca 100644 --- a/Process.h.in +++ b/Process.h.in @@ -82,6 +82,7 @@ # define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt) # define kwsysProcess_Kill kwsys_ns(Process_Kill) # define kwsysProcess_KillPID kwsys_ns(Process_KillPID) +# define kwsysProcess_GetParentPID kwsys_ns(Process_GetParentPID) # define kwsysProcess_ResetStartTime kwsys_ns(Process_ResetStartTime) #endif @@ -468,6 +469,13 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); */ kwsysEXPORT void kwsysProcess_KillPID(unsigned long); +#ifndef _WIN32 +/** + * Get the parent process ID from a given process ID + */ +kwsysEXPORT unsigned long kwsysProcess_GetParentPID(unsigned long); +#endif + /** * Reset the start time of the child process to the current time. */ @@ -537,6 +545,8 @@ kwsysEXPORT void kwsysProcess_ResetStartTime(kwsysProcess* cp); # undef kwsysProcess_WaitForExit # undef kwsysProcess_Interrupt # undef kwsysProcess_Kill +# undef kwsysProcess_KillPID +# undef kwsysProcess_GetParentPID # undef kwsysProcess_ResetStartTime # endif #endif diff --git a/ProcessUNIX.c b/ProcessUNIX.c index ce6bb7b9cf165220cfa682afbe9a8aa81e100a15..21c57e5973c346328a827eafdf360f6e0103f4b1 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -188,6 +188,7 @@ static void kwsysProcessRestoreDefaultSignalHandlers(void); static pid_t kwsysProcessFork(kwsysProcess* cp, kwsysProcessCreateInformation* si); static void kwsysProcessKill(pid_t process_id); +static pid_t kwsysGetParentPID(pid_t process_id); #if defined(__VMS) static int kwsysProcessSetVMSFeature(char const* name, int value); #endif @@ -2626,6 +2627,73 @@ static void kwsysProcessKill(pid_t process_id) kill(process_id, SIGKILL); #endif } +unsigned long kwsysProcess_GetParentPID(unsigned long process_id) +{ + return kwsysGetParentPID((pid_t)process_id); +} + +static pid_t kwsysGetParentPID(pid_t process_id) +{ +#if defined(__linux__) || defined(__CYGWIN__) + DIR* procdir; +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + /* First try using the /proc filesystem. */ + if ((procdir = opendir("/proc"))) { +# if defined(MAXPATHLEN) + char fname[MAXPATHLEN]; +# elif defined(PATH_MAX) + char fname[PATH_MAX]; +# else + char fname[4096]; +# endif + char buffer[KWSYSPE_PIPE_BUFFER_SIZE + 1]; + + struct stat finfo; + snprintf(fname, sizeof(fname), "/proc/%d/stat", process_id); + if (stat(fname, &finfo) == 0) { + FILE* f = fopen(fname, "r"); + if (f) { + size_t nread = fread(buffer, 1, 1024, f); + fclose(f); + buffer[nread] = '\0'; + if (nread > 0) { + char const* rparen = strrchr(buffer, ')'); + int ppid; + if (rparen && (sscanf(rparen + 1, "%*s %d", &ppid) == 1)) { + return ppid; + } + } + } + } + closedir(procdir); + } else +#endif + { +#if defined(KWSYSPE_PS_COMMAND) + /* Try running "ps" to get the process information. */ + FILE* ps = popen(KWSYSPE_PS_COMMAND, "r"); + + /* Make sure the process started and provided a valid header. */ + if (ps && fscanf(ps, "%*[^\n]\n") != EOF) { + int pid; + int ppid; + while (fscanf(ps, KWSYSPE_PS_FORMAT, &pid, &ppid) == 2) { + if (pid == process_id) { + return ppid; + } + } + } + + /* We are done with the ps process. */ + if (ps) { + pclose(ps); + } +#endif + } + return 0; +} #if defined(__VMS) int decc$feature_get_index(char const* name);