> Message: 1
> Date: Sun, 14 Mar 2010 05:01:24 PDT
> From: Ivan Petrov <free...@abv.bg>
> To: opensolaris-code@opensolaris.org
> Subject: [osol-code] Usage of psinfo_t from procfs.h
> Message-ID: <1549729909.41268568114096.javamail.tweb...@sf-app1>
> Content-Type: text/plain; charset=UTF-8
> 
> Hi,
> I'm trying to write a small piece of code that should be capable of getting 
the command line arguments for a given process. Similar to the ps(1) tool. What 
I can't figure out is how exactly to use the pr_argv field of the psinfo_t 
struct...
> Here's the code:
> 
[ snip ]
> 
> so when I execute the code like that:
> 
> $ ./a.out /proc/690/psinfo
> 
> I get something like:
> 
> arg vector addr: 134512240
> cmd line:
> 
> I guess I can't just access what's on that address like that as it's outside 
my process. Can you tell me how could I do what I want? 
> Yes I know I can use ps(1) but I wanna do it with my little piece of code if 
possible.

The pr_argv field of the psinfo_t structure contains the address
in the target process of its array of pointers to argument strings.

You can't dereference it directly.  You have to read the array
from the target process's address space using /proc/<pid>/as .

And that's just the beginning.  Then you have to read the individual
strings from the target process using their target process addresses
contained in the array of pointers you just read.

And since you don't know how long each string is, you have to make
a guess, read the memory, and test if what you just read contains
a null character.  If not, you have to increase your guess and try
again, until you actually read memory containing a null character.

Attached is a complete program to do all this.

Enjoy,
Roger Faulkner
/*
 * compile:
 *	cc -m64 -O -o pargs pargs.c
 * use:
 *	./pargs pid
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <procfs.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types32.h>

int
main(int argc, char *argv[])
{
	psinfo_t pinfo;
	char procfile[128];
	int fd, i;
	uintptr_t addrArgs;
	uintptr_t *Argvec;
	int Argcount;
	char *Arg;
	size_t Arglen;

	if (argc != 2 || strlen(argv[1]) > 100) {
		(void) fprintf(stderr, "usage: %s pid\n", argv[0]);
		exit(1);
	}

	(void) strcpy(procfile, "/proc/");
	(void) strcat(procfile, argv[1]);
	(void) strcat(procfile, "/psinfo");
	if ((fd = open(procfile, O_RDONLY)) < 0) {
		(void) fprintf(stderr, "Error opening %s: ", procfile);
		perror(NULL);
		exit(1);
	}
	(void) read(fd, &pinfo, sizeof (psinfo_t));
	addrArgs = pinfo.pr_argv;
	Argcount = pinfo.pr_argc;
	(void) close(fd);
	(void) strcpy(procfile, "/proc/");
	(void) strcat(procfile, argv[1]);
	(void) strcat(procfile, "/as");
	if ((fd = open(procfile, O_RDONLY)) < 0) {
		(void) fprintf(stderr, "Error opening %s: ", procfile);
		perror(NULL);
		exit(1);
	}
	Argvec = malloc(Argcount * sizeof (uintptr_t));
	if (pinfo.pr_dmodel == PR_MODEL_NATIVE) {
		(void) pread(fd, Argvec, Argcount * sizeof (uintptr_t),
		    addrArgs);
	} else {	/* we are 64-bit, target is 32-bit */
		caddr32_t *Argvec32 = (caddr32_t *)Argvec;
		(void) pread(fd, Argvec32, Argcount * sizeof (caddr32_t),
		    addrArgs);
		/* convert from 32-bit to 64-bit in place */
		for (i = Argcount - 1; i >= 0; --i)
			Argvec[i] = Argvec32[i];
	}
	Arglen = 16;	/* initial guess */
	Arg = malloc(Arglen+1);
	for (i = 0; i < Argcount; i++) {
		if (pread(fd, Arg, Arglen, Argvec[i]) < 0)
			continue;
		Arg[Arglen] = '\0';
		if (strlen(Arg) == Arglen) {	/* need a bigger buffer */
			Arglen *= 2;
			Arg = realloc(Arg, Arglen + 1);
			i--;
			continue;
		}
		(void) printf("argv[%d]: %s\n", i, Arg);
	}
	(void) close(fd);
	return (0);
}
_______________________________________________
opensolaris-code mailing list
opensolaris-code@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code

Reply via email to