Click to See Complete Forum and Search --> : C - Get another process id


tecknophreak
10-08-2003, 04:44 PM
I know how to get a single process's id, getpid, but is it possible to get another process's id? I'm guessing there is since ps can do it.

After a little looking around in /proc, I can get the name of the process by looking at /proc/$pid/cmdline. But this would require me to:


string prog("man");
vector<string> procs;
procs = getdirectorylisting("/proc");

for (int i = 0; i < procs.size(); ++i) {
if (isalpha(procs[i][0])) {
if (prog == getprogramname(procs[i])) {
return procs[i];
}
}
}


^ of course pseudo code. getprogramname would return the first string found in /proc/$pid/cmdline.

Hopefully, there is already a program out there which does this.

bwkaz
10-08-2003, 06:55 PM
Sure there is. It's named pidof

Run pidof bash or pidof X (or, in your case, pidof man) sometime.

Of course, you'll have to figure out how to spawn the pidof process on your own. If you've already got the Gtk libraries in this program, then glib's g_spawn_* functions will probably be useful (esp. g_spawn_async(), IIRC).

tecknophreak
10-08-2003, 07:03 PM
Well, I meant from C/C++. Anyway, here's some C code I whipped up.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>


// Returns the pid of the first process found in /proc
// However, the procs aren't in order
// Shame getpid is already taken...
int getpidof(char *process) {
DIR *dp;
struct dirent *entry;
struct stat statbuf;

if ((dp = opendir("/proc")) == NULL) {
fprintf(stderr, "Cannot open directory /proc\n");
return -1;
}
chdir("/proc");

while ((entry = readdir(dp)) != NULL) {
// Get information about the file/folder
lstat(entry->d_name, &statbuf);
// Files under /proc which start with a digit are processes
if (S_ISDIR(statbuf.st_mode) && isdigit(entry->d_name[0])) {
// 14 chars for /proc//status + 0
char procpath[14 + strlen(entry->d_name)];
char procname[50];
FILE *file;

strcpy(procpath, "/proc/");
strcat(procpath, entry->d_name);
strcat(procpath, "/status");
file = fopen(procpath, "r");

// Get the second string in the file,
// this is where the process name is
fscanf(file, "%s", procname);
fscanf(file, "%s", procname);
fclose(file);
if (strcmp(procname, process) == 0) {
return atoi(entry->d_name);
}
}
}
return -1;
}



int main(int argc, char **argv) {
if (argc != 2) {
printf("Usage: getpid programname\n");
return 0;
}
printf("%s: %i\n", argv[1], getpidof(argv[1]));
}

tecknophreak
10-09-2003, 10:25 AM
Of course it would be easier to use popen to read the output from pidof, but where's the fun in that? ;) Also, I've read that popen isn't that robust, so I'm trying to keep it out of my code.

Stuka
10-09-2003, 11:11 AM
Well, if popen isn't that robust, just use pipe, and spawn the process, and dup stdout, and...oh, wait, you don't wanna rewrite bash, do ya? ;)

tecknophreak
10-09-2003, 11:34 AM
nah, I'd rather re-write pidof. I'm just kinda surprised there isn't already a function for this, or that we don't know where it is.

Whipping Boy
10-09-2003, 06:07 PM
Correct me if I'm wrong, but isn't using /proc non-portable?

tecknophreak
10-09-2003, 08:04 PM
I'm pretty sure it isn't portable, but I don't need it to be. To date, I only have one program which I'll have to port over. I hardly ever program for dos/windows, even then it's usually only client software.

bwkaz
10-09-2003, 09:59 PM
The /proc/<PID> directories exist on most Unix variants, and /proc/self may be on some of them as well.

The other /proc files (like stuff under /proc/sys/, or /proc/mounts, or /proc/meminfo) are not. Or at least, they didn't exist on whatever version of Solaris they had in the labs at school.