⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proc_arg.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
字号:
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)proc_arg.c	1.7	04/08/16 SMI"#include <sys/types.h>#include <sys/stat.h>#include <libgen.h>#include <limits.h>#include <alloca.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <ctype.h>#include <errno.h>#include <dirent.h>#include "libproc.h"static intopen_psinfo(const char *arg, int *perr){	/*	 * Allocate enough space for "/proc/" + arg + "/psinfo"	 */	char *path = alloca(strlen(arg) + 14);	struct stat64 st;	int fd;	if (strchr(arg, '/') == NULL) {		(void) strcpy(path, "/proc/");		(void) strcat(path, arg);	} else		(void) strcpy(path, arg);	(void) strcat(path, "/psinfo");	/*	 * Attempt to open the psinfo file, and return the fd if we can	 * confirm this is a regular file provided by /proc.	 */	if ((fd = open64(path, O_RDONLY)) >= 0) {		if (fstat64(fd, &st) != 0 || !S_ISREG(st.st_mode) ||		    strcmp(st.st_fstype, "proc") != 0) {			(void) close(fd);			fd = -1;		}	} else if (errno == EACCES || errno == EPERM)		*perr = G_PERM;	return (fd);}static intopen_core(const char *arg, int *perr){#ifdef _BIG_ENDIAN	uchar_t order = ELFDATA2MSB;#else	uchar_t order = ELFDATA2LSB;#endif	GElf_Ehdr ehdr;	int fd;	int is_noelf = -1;	/*	 * Attempt to open the core file, and return the fd if we can confirm	 * this is an ELF file of type ET_CORE.	 */	if ((fd = open64(arg, O_RDONLY)) >= 0) {		if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) {			(void) close(fd);			fd = -1;		} else if ((is_noelf = memcmp(&ehdr.e_ident[EI_MAG0], ELFMAG,			    SELFMAG)) != 0 || ehdr.e_type != ET_CORE) {				(void) close(fd);				fd = -1;				if (is_noelf == 0 &&				    ehdr.e_ident[EI_DATA] != order)					*perr = G_ISAINVAL;		}	} else if (errno == EACCES || errno == EPERM)		*perr = G_PERM;	return (fd);}/* * Make the error message precisely match the type of arguments the caller * wanted to process.  This ensures that a tool which only accepts pids does * not produce an error message saying "no such process or core file 'foo'". */static intopen_error(int oflag){	if ((oflag & PR_ARG_ANY) == PR_ARG_PIDS)		return (G_NOPROC);	if ((oflag & PR_ARG_ANY) == PR_ARG_CORES)		return (G_NOCORE);	return (G_NOPROCORCORE);}static void *proc_grab_common(const char *arg, const char *path, int oflag, int gflag,    int *perr, const char **lwps, psinfo_t *psp){	psinfo_t psinfo;	char *core;	int fd;	char *slash;	struct ps_prochandle *Pr;	*perr = 0;	if (lwps)		*lwps = NULL;	if (lwps != NULL && (slash = strrchr(arg, '/')) != NULL) {		/*		 * Check to see if the user has supplied an lwp range.  First,		 * try to grab it as a pid/lwp combo.		 */		*slash = '\0';		if ((oflag & PR_ARG_PIDS) &&		    (fd = open_psinfo(arg, perr)) != -1) {			if (read(fd, &psinfo,			    sizeof (psinfo_t)) == sizeof (psinfo_t)) {				(void) close(fd);				*lwps = slash + 1;				*slash = '/';				if (proc_lwp_range_valid(*lwps) != 0) {					*perr = G_BADLWPS;					return (NULL);				}				if (psp) {					*psp = psinfo;					return (psp);				} else  {					return (Pgrab(psinfo.pr_pid, gflag,					    perr));				}			}			(void) close(fd);		}		/*		 * Next, try grabbing it as a corefile.		 */		if ((oflag & PR_ARG_CORES) &&		    (fd = open_core(arg, perr)) != -1) {			*lwps = slash + 1;			*slash = '/';			if (proc_lwp_range_valid(*lwps) != 0) {				*perr = G_BADLWPS;				return (NULL);			}			core = alloca(strlen(arg) + 1);			(void) strcpy(core, arg);			if ((Pr = Pfgrab_core(fd, path == NULL ?			    dirname(core) : path, perr)) != NULL) {				if (psp) {					(void) memcpy(psp, Ppsinfo(Pr),					    sizeof (psinfo_t));					Prelease(Pr, 0);					return (psp);				} else {					return (Pr);				}			}		}		*slash = '/';	}	if ((oflag & PR_ARG_PIDS) && (fd = open_psinfo(arg, perr)) != -1) {		if (read(fd, &psinfo, sizeof (psinfo_t)) == sizeof (psinfo_t)) {			(void) close(fd);			if (psp) {				*psp = psinfo;				return (psp);			} else {				return (Pgrab(psinfo.pr_pid, gflag, perr));			}		}		/*		 * If the read failed, the process may have gone away;		 * we continue checking for core files or fail with G_NOPROC		 */		(void) close(fd);	}	if ((oflag & PR_ARG_CORES) && (fd = open_core(arg, perr)) != -1) {		core = alloca(strlen(arg) + 1);		(void) strcpy(core, arg);		if ((Pr = Pfgrab_core(fd, path == NULL ? dirname(core) : path,		    perr)) != NULL) {			if (psp) {				(void) memcpy(psp, Ppsinfo(Pr),				    sizeof (psinfo_t));				Prelease(Pr, 0);				return (psp);			} else {				return (Pr);			}		}	}	/*	 * We were unable to open the corefile.  If we have no meaningful	 * information, report the (ambiguous) error from open_error().	 */	if (*perr == 0)		*perr = open_error(oflag);	return (NULL);}struct ps_prochandle *proc_arg_xgrab(const char *arg, const char *path, int oflag, int gflag,    int *perr, const char **lwps){	return (proc_grab_common(arg, path, oflag, gflag, perr, lwps, NULL));}struct ps_prochandle *proc_arg_grab(const char *arg, int oflag, int gflag, int *perr){	return (proc_grab_common(arg, NULL, oflag, gflag, perr, NULL, NULL));}pid_tproc_arg_psinfo(const char *arg, int oflag, psinfo_t *psp, int *perr){	psinfo_t psinfo;	if (psp == NULL)		psp = &psinfo;	if (proc_grab_common(arg, NULL, oflag, 0, perr, NULL, psp) == NULL)		return (-1);	else		return (psp->pr_pid);}pid_tproc_arg_xpsinfo(const char *arg, int oflag, psinfo_t *psp, int *perr,    const char **lwps){	psinfo_t psinfo;	if (psp == NULL)		psp = &psinfo;	if (proc_grab_common(arg, NULL, oflag, 0, perr, lwps, psp) == NULL)		return (-1);	else		return (psp->pr_pid);}/* * Convert psinfo_t.pr_psargs string into itself, replacing unprintable * characters with space along the way.  Stop on a null character. */voidproc_unctrl_psinfo(psinfo_t *psp){	char *s = &psp->pr_psargs[0];	size_t n = PRARGSZ;	int c;	while (n-- != 0 && (c = (*s & UCHAR_MAX)) != '\0') {		if (!isprint(c))			c = ' ';		*s++ = (char)c;	}	*s = '\0';}static intproc_lwp_get_range(char *range, id_t *low, id_t *high){	if (*range == '-')		*low = 0;	else		*low = (id_t)strtol(range, &range, 10);	if (*range == '\0' || *range == ',') {		*high = *low;		return (0);	}	if (*range != '-') {		return (-1);	}	range++;	if (*range == '\0')		*high = INT_MAX;	else		*high = (id_t)strtol(range, &range, 10);	if (*range != '\0' && *range != ',') {		return (-1);	}	if (*high < *low) {		id_t tmp = *high;		*high = *low;		*low = tmp;	}	return (0);}/* * Determine if the specified lwpid is in the given set of lwpids. * The set can include multiple lwpid ranges separated by commas * and has the following syntax: * * 	lwp_range[,lwp_range]* * * where lwp_range is specifed as: * * 	-n			lwpid <= n * 	n-m			n <= lwpid <= m * 	n-			lwpid >= n * 	n			lwpid == n */intproc_lwp_in_set(const char *set, lwpid_t lwpid){	id_t low, high;	id_t id = (id_t)lwpid;	char *comma;	char *range = (char *)set;	/*	 * A NULL set indicates that all LWPs are valid.	 */	if (set == NULL)		return (1);	while (range != NULL) {		comma = strchr(range, ',');		if (comma != NULL)			*comma = '\0';		if (proc_lwp_get_range(range, &low, &high) != 0) {			if (comma != NULL)				*comma = ',';			return (0);		}		if (comma != NULL) {			*comma = ',';			range = comma + 1;		} else {			range = NULL;		}		if (id >= low && id <= high)			return (1);	}	return (0);}intproc_lwp_range_valid(const char *set){	char *comma;	char *range = (char *)set;	id_t low, high;	int ret;	if (range == NULL || *range == '\0' || *range == ',')		return (-1);	while (range != NULL) {		comma = strchr(range, ',');		if (comma != NULL)			*comma = '\0';		if ((ret = proc_lwp_get_range(range, &low, &high)) != 0) {			if (comma != NULL)				*comma = ',';			return (ret);		}		if (comma != NULL) {			*comma = ',';			range = comma + 1;		} else {			range = NULL;		}	}	return (0);}/* * Walk all processes or LWPs in /proc and call func() for each. * Stop calling func() if it returns non 0 value and return it. */intproc_walk(proc_walk_f *func, void *arg, int flag){	DIR *procdir;	struct dirent *dirent;	char *errptr;	char pidstr[80];	psinfo_t psinfo;	lwpsinfo_t *lwpsinfo;	prheader_t prheader;	void *buf;	char *ptr;	int bufsz;	id_t pid;	int fd, i;	int ret = 0;	if (flag != PR_WALK_PROC && flag != PR_WALK_LWP) {		errno = EINVAL;		return (-1);	}	if ((procdir = opendir("/proc")) == NULL)		return (-1);	while (dirent = readdir(procdir)) {		if (dirent->d_name[0] == '.')	/* skip . and .. */			continue;		pid = (id_t)strtol(dirent->d_name, &errptr, 10);		if (errptr != NULL && *errptr != '\0')			continue;		/* PR_WALK_PROC case */		(void) snprintf(pidstr, sizeof (pidstr),		    "/proc/%ld/psinfo", pid);		fd = open(pidstr, O_RDONLY);		if (fd < 0)			continue;		if (read(fd, &psinfo, sizeof (psinfo)) != sizeof (psinfo)) {			(void) close(fd);			continue;		}		(void) close(fd);		if (flag == PR_WALK_PROC) {			if ((ret = func(&psinfo, &psinfo.pr_lwp, arg)) != 0)				break;			continue;		}		/* PR_WALK_LWP case */		(void) snprintf(pidstr, sizeof (pidstr),		    "/proc/%ld/lpsinfo", pid);		fd = open(pidstr, O_RDONLY);		if (fd < 0)			continue;		if (read(fd, &prheader, sizeof (prheader)) !=		    sizeof (prheader)) {			(void) close(fd);			continue;		}		bufsz = prheader.pr_nent * prheader.pr_entsize;		if ((buf = malloc(bufsz)) == NULL) {			(void) close(fd);			ret = -1;			break;		}		ptr = buf;		if (pread(fd, buf, bufsz, sizeof (prheader)) != bufsz) {			free(buf);			(void) close(fd);			continue;		}		(void) close(fd);		for (i = 0; i < prheader.pr_nent;		    i++, ptr += prheader.pr_entsize) {			/*LINTED ALIGNMENT*/			lwpsinfo = (lwpsinfo_t *)ptr;			if ((ret = func(&psinfo, lwpsinfo, arg)) != 0) {				free(buf);				break;			}		}		free(buf);	}	(void) closedir(procdir);	return (ret);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -