diff options
Diffstat (limited to 'xserver/os/client.c')
-rw-r--r-- | xserver/os/client.c | 118 |
1 files changed, 101 insertions, 17 deletions
diff --git a/xserver/os/client.c b/xserver/os/client.c index b5349778b..fbccf22ed 100644 --- a/xserver/os/client.c +++ b/xserver/os/client.c @@ -59,6 +59,20 @@ #include "os.h" #include "dixstruct.h" +#ifdef __sun +#include <errno.h> +#include <procfs.h> +#endif + +#ifdef __OpenBSD__ +#include <sys/param.h> +#include <sys/sysctl.h> +#include <sys/types.h> + +#include <kvm.h> +#include <limits.h> +#endif + /** * Try to determine a PID for a client from its connection * information. This should be called only once when new client has @@ -117,8 +131,6 @@ void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) { char path[PATH_MAX + 1]; int totsize = 0; - int cmdsize = 0; - int argsize = 0; int fd = 0; if (cmdname) @@ -129,6 +141,80 @@ void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) if (pid == -1) return; +#ifdef __sun /* Solaris */ + /* Solaris does not support /proc/pid/cmdline, but makes information + * similar to what ps shows available in a binary structure in the + * /proc/pid/psinfo file. */ + if (snprintf(path, sizeof(path), "/proc/%d/psinfo", pid) < 0) + return; + fd = open(path, O_RDONLY); + if (fd < 0) + { + ErrorF ("Failed to open %s: %s\n", path, strerror(errno)); + return; + } + else + { + psinfo_t psinfo = { 0 }; + char *sp; + + totsize = read(fd, &psinfo, sizeof(psinfo_t)); + close(fd); + if (totsize <= 0) + return; + + /* pr_psargs is the first PRARGSZ (80) characters of the command + * line string - assume up to the first space is the command name, + * since it's not delimited. While there is also pr_fname, that's + * more limited, giving only the first 16 chars of the basename of + * the file that was exec'ed, thus cutting off many long gnome + * command names, or returning "isapython2.6" for all python scripts. + */ + psinfo.pr_psargs[PRARGSZ-1] = '\0'; + sp = strchr(psinfo.pr_psargs, ' '); + if (sp) + *sp++ = '\0'; + + if (cmdname) + *cmdname = strdup(psinfo.pr_psargs); + + if (cmdargs && sp) + *cmdargs = strdup(sp); + } +#elif defined(__OpenBSD__) + /* on OpenBSD use kvm_getargv() */ + { + kvm_t *kd; + char errbuf[_POSIX2_LINE_MAX]; + char **argv; + struct kinfo_proc *kp; + size_t len = 0; + int i, n; + + kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf); + if (kd == NULL) + return; + kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &n); + if (n != 1) + return; + argv = kvm_getargv(kd, kp, 0); + *cmdname = strdup(argv[0]); + i = 1; + while (argv[i] != NULL) { + len += strlen(argv[i]) + 1; + i++; + } + *cmdargs = calloc(1, len); + i = 1; + while (argv[i] != NULL) { + strlcat(*cmdargs, argv[i], len); + strlcat(*cmdargs, " ", len); + i++; + } + kvm_close(kd); + } +#else /* Linux using /proc/pid/cmdline */ + /* Check if /proc/pid/cmdline exists. It's not supported on all * operating systems. */ if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0) @@ -146,23 +232,20 @@ void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) path[totsize - 1] = '\0'; /* Contruct the process name without arguments. */ - cmdsize = strlen(path) + 1; if (cmdname) { - char *name = malloc(cmdsize); - if (name) - { - strncpy(name, path, cmdsize); - name[cmdsize - 1] = '\0'; - *cmdname = name; - } + *cmdname = strdup(path); } /* Construct the arguments for client process. */ - argsize = totsize - cmdsize; - if (cmdargs && (argsize > 0)) + if (cmdargs) { - char *args = malloc(argsize); + int cmdsize = strlen(path) + 1; + int argsize = totsize - cmdsize; + char *args = NULL; + + if (argsize > 0) + args = malloc(argsize); if (args) { int i = 0; @@ -175,6 +258,7 @@ void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) *cmdargs = args; } } +#endif } /** @@ -198,9 +282,9 @@ void ReserveClientIds(struct _Client *client) DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, &client->clientIds->cmdargs); DebugF("client(%lx): Reserved pid(%d).\n", - client->clientAsMask, client->clientIds->pid); + (unsigned long) client->clientAsMask, client->clientIds->pid); DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n", - client->clientAsMask, + (unsigned long) client->clientAsMask, client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); #endif /* CLIENTIDS */ @@ -222,9 +306,9 @@ void ReleaseClientIds(struct _Client *client) return; DebugF("client(%lx): Released pid(%d).\n", - client->clientAsMask, client->clientIds->pid); + (unsigned long) client->clientAsMask, client->clientIds->pid); DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n", - client->clientAsMask, + (unsigned long) client->clientAsMask, client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); |