diff options
Diffstat (limited to 'kcontrol/tdefontinst/tdefontinst/GetPid.c')
-rw-r--r-- | kcontrol/tdefontinst/tdefontinst/GetPid.c | 519 |
1 files changed, 519 insertions, 0 deletions
diff --git a/kcontrol/tdefontinst/tdefontinst/GetPid.c b/kcontrol/tdefontinst/tdefontinst/GetPid.c new file mode 100644 index 000000000..015ea7ce9 --- /dev/null +++ b/kcontrol/tdefontinst/tdefontinst/GetPid.c @@ -0,0 +1,519 @@ +/* +//////////////////////////////////////////////////////////////////////////////// +// +// File Name : GetPid.c +// Author : Craig Drummond +// Project : K Font Installer +// Creation Date : 19/03/2003 +// Version : $Revision$ $Date$ +// +//////////////////////////////////////////////////////////////////////////////// +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//////////////////////////////////////////////////////////////////////////////// +// (C) Craig Drummond, 2003 +//////////////////////////////////////////////////////////////////////////////// +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(__DragonFly__) +#include <sys/param.h> +#endif + +#include <sys/types.h> + +#ifndef __cplusplus +#define bool unsigned int +#define false 0 +#define true (!false) +#endif + +#define BUFSIZE 1024 +#define PROCDIR "/proc" + +/* + Get process ID - using name of exe and parent process ID + + Implemented for: + + Linux Tested on Linux 2.4 + FreeBSD Tested on FreeBSD 5.1 by Brian Ledbetter <brian@shadowcom.net> + NetBSD + Irix + Solaris Tested on Solaris 8 x86 by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE> + HP-UX Tested on HP-UX B.11.11 U 9000/800 + AIX + ...else parse output of "ps -eaf" + + + Some sections of this code are copied from / inspired by ksysguard, + Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org> + + To test this file, do the following: + + 1. Compile this file as follows: + + gcc GetPid.c -DTEST_GETPID -DOS_Linux -o tst + + ...replace OS_Linux with your particular OS type: OS_FreeBSD, OS_NetBSD, OS_Irix, OS_Solaris, + OS_HPUX, or OS_AIX + + 2. Start a program - such as "vi" + 3. Do a "ps -eaf" to ensure there is *only one* process called "vi" + 4. Get the parent process ID of your "vi" above + 5. Call tst with that value -e.g. vi ppid=23 then ./tst vi 23 + ...this should then print out the process ID of "vi" + 6. Email me and let me know if it works! +*/ + +#if defined OS_Linux || defined __Linux__ + +#include <dirent.h> +#include <ctype.h> + +#define FOUND_NAME 1 +#define FOUND_PPID 2 +#define FOUND_ALL (FOUND_NAME+FOUND_PPID) + +unsigned int kfi_getPid(const char *proc, unsigned int ppid) +{ + bool error=false; + unsigned int pid=0; + DIR *dir; + struct dirent *entry; + + /* read in current process list via the /proc filesystem entry */ + if(NULL!=(dir=opendir(PROCDIR))) + { + while((entry=readdir(dir)) && !error) + if(isdigit(entry->d_name[0])) + { + char buf[BUFSIZE]; + FILE *fd; + + snprintf(buf, BUFSIZE-1, PROCDIR"/%d/status", atoi(entry->d_name)); + + if(NULL!=(fd=fopen(buf, "r"))) + { + char format[32], + tagformat[32], + tag[32], + name[64]; + int found=0; + + found=0; + sprintf(format, "%%%d[^\n]\n", (int) sizeof(buf) - 1); + sprintf(tagformat, "%%%ds", (int) sizeof(tag) - 1); + for(;found<FOUND_ALL;) + { + if (fscanf(fd, format, buf)!=1) + break; + buf[sizeof(buf)-1]='\0'; + sscanf(buf, tagformat, tag); + tag[sizeof(tag) - 1] = '\0'; + if(0==strcmp(tag, "Name:")) + { + sscanf(buf, "%*s %63s", name); + if(NULL==name || 0!=strcmp(name, proc)) + break; + found|=FOUND_NAME; + } + else if(0==strcmp(tag, "PPid:")) + { + unsigned int proc_ppid; + + sscanf(buf, "%*s %u", &proc_ppid); + if(ppid!=proc_ppid) + break; + found|=FOUND_PPID; + } + } + if(FOUND_ALL==found) + { + if(pid) + error=true; + else + pid=atoi(entry->d_name); + } + fclose(fd); + } + } + closedir(dir); + } + + return error ? 0 : pid; +} + +#elif defined OS_FreeBSD || defined OS_NetBSD || defined __FreeBSD__ || defined __NetBSD__ || defined OS_Darwin + +#include <ctype.h> +#include <dirent.h> +#include <pwd.h> +#include <stdio.h> +#include <sys/param.h> +#if __FreeBSD_version > 500015 +#include <sys/priority.h> +#endif +#include <sys/sysctl.h> +#include <sys/time.h> +#include <sys/user.h> +#include <unistd.h> +unsigned int kfi_getPid(const char *proc, unsigned int ppid) +{ + bool error=false; + unsigned int pid=0; + int mib[4]; + size_t len, + num; + struct kinfo_proc *p; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ALL; + sysctl(mib, 3, NULL, &len, NULL, 0); + p=(struct kinfo_proc*)malloc(len); + sysctl(mib, 3, p, &len, NULL, 0); + + for(num=0; num < len / sizeof(struct kinfo_proc) && !error; num++) + { + struct kinfo_proc proc_p; + size_t len; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; +#if __FreeBSD_version >= 500015 + mib[3] = p[num].ki_pid; +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + mib[3] = p[num].kp_pid; +#else + mib[3] = p[num].kp_proc.p_pid; +#endif + + len=sizeof(proc_p); + if(-1==sysctl(mib, 4, &proc_p, &len, NULL, 0) || !len) + break; + else + { +#if __FreeBSD_version >= 500015 + if(proc_p.ki_ppid==ppid && p[num].ki_comm && 0==strcmp(p[num].ki_comm, proc)) + if(pid) + error=true; + else + pid=p[num].ki_pid; +#elif defined (__DragonFly__) && __DragonFly_version >= 190000 + if(proc_p.kp_ppid==ppid && p[num].kp_comm && 0==strcmp(p[num].kp_comm, proc)) + if(pid) + error=true; + else + pid=p[num].kp_pid; +#else +#if defined(__DragonFly__) + if(proc_p.kp_eproc.e_ppid==ppid && p[num].kp_thread.td_comm && 0==strcmp(p[num].kp_thread.td_comm, proc)) +#else + if(proc_p.kp_eproc.e_ppid==ppid && p[num].kp_proc.p_comm && 0==strcmp(p[num].kp_proc.p_comm, proc)) +#endif + if(pid) + error=true; + else + pid=p[num].kp_proc.p_pid; +#endif + } + } + free(p); + + return error ? 0 : pid; +} + +#elif defined OS_Irix || defined OS_Solaris + +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <dirent.h> +#include <pwd.h> +#include <sys/resource.h> +#ifdef OS_Solaris + +#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) +#define PROCFS_FILE_OFFSET_BITS_HACK 1 +#undef _FILE_OFFSET_BITS +#else +#define PROCFS_FILE_OFFSET_BITS_HACK 0 +#endif + +#include <procfs.h> + +#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) +#define _FILE_OFFSET_BITS 64 +#endif + +#else +#include <sys/procfs.h> +#include <sys/sysmp.h> +#endif +#include <sys/sysinfo.h> + +unsigned int kfi_getPid(const char *proc, pid_t ppid) +{ + DIR *procdir; + bool error=false; + pid_t pid=(pid_t)0; + + if(NULL!=(procdir=opendir(PROCDIR))) + { + struct dirent *de; + + rewinddir(procdir); + while((de=readdir(procdir)) && !error) + if('.'==de->d_name[0]) + continue; + else + { + int fd; + char buf[BUFSIZE]; +#ifdef OS_Solaris + psinfo_t psinfo; + + snprintf(buf, BUFSIZE - 1, "%s/%s/psinfo", PROCDIR, de->d_name); +#else + prpsinfo_t psinfo; + + sprintf(buf, PROCDIR"/pinfo/%ld", pid); +#endif + + if((fd=open(buf, O_RDONLY))<0) + continue; + +#ifdef OS_Solaris + if(sizeof(psinfo_t)!=read(fd, &psinfo, sizeof(psinfo_t))) +#else + if(ioctl(fd, PIOCPSINFO, &psinfo)<0) +#endif + { + close(fd); + continue; + } + close(fd); + + if(psinfo.pr_ppid==ppid && psinfo.pr_fname && 0==strcmp(psinfo.pr_fname, proc)) + if(pid) + error=true; + else + pid=psinfo.pr_pid; + } + closedir(procdir); + } + + return error ? 0 : pid; +} + +#elif defined OS_HPUX + +#include <sys/pstat.h> +#define MAX_PROCS 50 + +unsigned int kfi_getPid(const char *proc, unsigned int ppid) +{ + bool error=false; + unsigned int pid=0; + int i, + count, + idx=0; + struct pst_status pst[MAX_PROCS]; + + while((count=pstat_getproc(&pst[0], sizeof(pst[0]), MAX_PROCS, idx)) > 0 && !error) + { + for (i = 0; i<count && !error; i++) + if(pst[i].pst_ppid==ppid && pst[i].pst_ucomm && 0==strcmp(pst[i].pst_ucomm, proc)) + if(pid) + error=true; + else + pid=pst[i].pst_pid; + + idx=pst[count-1].pst_idx+1; + } + + return error ? 0 : pid; +} + +#elif defined OS_AIX + +#include <procinfo.h> +#define MAX_PROCS 50 + +unsigned int kfi_getPid(const char *proc, unsigned int ppid) +{ + bool error=false; + unsigned int pid=0; + int i, + count, + idx=0; + struct procsinfo pi[MAX_PROCS]; + + while((count=getprocs(&pi, sizeof(pi[0]), 0, 0, &pid, 1)) >0 && !error) + { + for (i = 0; i<count && !error; i++) + if(pi[i].pi_ppid==ppid && pi[i].pi_comm && 0==strcmp(pi[i].pi_comm, proc)) + if(pid) + error=true; + else + pid=pi[i].pi_pid; + + idx=pi[count-1].pi_idx+1; + } + + return error ? 0 : pid; +} + +#else +#warning "Unable to determine operating system version! This may cause the getPid() function to fail at random!" + +/* Default to reading "ps -eaf" output */ + +#include <pwd.h> +#include <limits.h> +#include <ctype.h> + +#define FOUND_PID 1 +#define FOUND_PPID 2 +#define FOUND_CMD 4 +#define FOUND_ALL (FOUND_PID+FOUND_PPID+FOUND_CMD) + +static int checkCmd(const char *proc, const char *cmd) +{ + int len=(int)strlen(cmd), + ch; + + if(len>1) + for(ch=len-2; ch>=0; --ch) + if('/'==cmd[ch]) + return strcmp(proc, &cmd[ch+1]); + + return strcmp(proc, cmd); +} + +unsigned int kfi_getPid(const char *proc, unsigned int ppid) +{ + bool error=false; + unsigned int pid=0; + static int pid_c=-1, + ppid_c=-1, + time_c=-1, + cmd_c=-1; + + char cmd[BUFSIZE+1]; + FILE *p; + + /* If this function has been run before, and we know the column positions, then we can grep for just our command */ + if(-1!=pid_c && -1!=ppid_c && -1!=time_c && -1!=cmd_c) + snprintf(cmd, BUFSIZE, "ps -eaf | grep %s", proc); + else + strcpy(cmd, "ps -eaf"); + + if(NULL!=(p=popen(cmd, "r"))) + { + char line[BUFSIZE+1]; + int c=0; + char *linep=NULL, + *token=NULL; + + /* Read 1st line to determine columns... */ + if((-1==pid_c || -1==ppid_c || -1==time_c || -1==cmd_c) && NULL!=fgets(line, BUFSIZE, p)) + { + for(linep=line; -1==pid_c || -1==ppid_c || -1==time_c || -1==cmd_c; linep=NULL) + if(NULL!=(token=strtok(linep, " \t\n"))) + { + if(0==strcmp("PID", token)) + pid_c=c; + else if(0==strcmp("PPID", token)) + ppid_c=c; + else if(NULL!=strstr("TIME", token)) + time_c=c; + else if(0==strcmp("COMMAND", token) || 0==strcmp("CMD", token)) + cmd_c=c; + c++; + } + else + break; + } + + /* If all column headings read, then look for details... */ + if(-1!=pid_c && -1!=ppid_c && -1!=time_c && -1!=cmd_c) + while(NULL!=fgets(line, BUFSIZE, p) && !error) + { + int found=0, + ps_pid=0, + offset=0; + + c=0; + for(linep=line; FOUND_ALL!=found; linep=NULL) + if(NULL!=(token=strtok(linep, " \t\n"))) + { + if(c==pid_c) + { + found|=FOUND_PID; + ps_pid=atoi(token); + } + else if(c==ppid_c) + { + if(((unsigned int)atoi(token))!=ppid) + break; + found|=FOUND_PPID; + } + else if(c==time_c) + offset=isdigit(token[0]) ? 0 : 1; + else if(c==(cmd_c+offset)) + { + if(0!=checkCmd(proc, token)) + break; + found|=FOUND_CMD; + } + c++; + } + else + break; + + if(FOUND_ALL==found) + { + if(pid) + error=true; + else + pid=ps_pid; + } + } + pclose(p); + } + + return error ? 0 : pid; +} + +#endif + +#ifdef TEST_GETPID +int main(int argc, char *argv[]) +{ + if(3==argc) + printf("PID %u\n", kfi_getPid(argv[1], atoi(argv[2]))); + else + printf("Usage: %s <process> <parent-process-id>\n", argv[0]); + return 0; +} +#endif |