diff options
author | Miles Bader <miles@gnu.org> | 1997-05-26 23:19:36 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1997-05-26 23:19:36 +0000 |
commit | fa3f1f47cbee8d8cd572f6986583c8e95f85a562 (patch) | |
tree | e7042967740a55d44b8dd873368cbb305849a10e /utils/pids.c | |
parent | b4447ed54831cbf4b49b96ed841faaacec6e26b6 (diff) |
Initial checkin
Diffstat (limited to 'utils/pids.c')
-rw-r--r-- | utils/pids.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/utils/pids.c b/utils/pids.c new file mode 100644 index 00000000..ea759247 --- /dev/null +++ b/utils/pids.c @@ -0,0 +1,232 @@ +/* Pid parsing/frobbing + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <argp.h> +#include <hurd.h> +#include <hurd/process.h> +#include <mach.h> + +#include "parse.h" +#include "pids.h" + +static process_t _proc_server = MACH_PORT_NULL; + +/* Return this process's proc server. */ +static inline process_t +proc_server () +{ + if (_proc_server == MACH_PORT_NULL) + _proc_server = getproc (); + return _proc_server; +} + +/* Add the pids returned in vm_allocated memory by calling PIDS_FN with ID as + an argument to PIDS and NUM_PIDS, reallocating it in malloced memory. */ +error_t +add_fn_pids (pid_t **pids, size_t *num_pids, unsigned id, + error_t (*pids_fn)(process_t proc, pid_t id, + pid_t **pids, unsigned *num_pids)) +{ + size_t num_new_pids = 25; + pid_t _new_pids[num_new_pids], *new_pids = _new_pids; + error_t err = (*pids_fn)(proc_server (), id, &new_pids, &num_new_pids); + + if (! err) + { + size_t new_sz = *num_pids + num_new_pids; + pid_t *new = realloc (*pids, new_sz * sizeof (pid_t)); + if (new) + { + bcopy (new_pids, new + (*num_pids * sizeof (pid_t)), + num_new_pids * sizeof (pid_t)); + *pids = new; + *num_pids = new_sz; + } + else + err = ENOMEM; + if (new_pids != _new_pids) + vm_deallocate (mach_task_self (), (vm_address_t)new_pids, + num_new_pids * sizeof (pid_t)); + } + + return err; +} + +/* Add PID to PIDS and NUM_PIDS, reallocating it in malloced memory. */ +error_t +add_pid (pid_t **pids, size_t *num_pids, pid_t pid) +{ + size_t new_sz = *num_pids + 1; + pid_t *new = realloc (*pids, new_sz * sizeof (pid_t)); + + if (new) + { + new[new_sz - 1] = pid; + *pids = new; + *num_pids = new_sz; + return 0; + } + else + return ENOMEM; +} + +struct pids_parse_state +{ + struct pids_argp_params *params; + struct argp_state *state; +}; + +/* Returns our session id. */ +static pid_t +current_sid (struct argp_state *state) +{ + pid_t sid = -1; + error_t err = proc_getsid (proc_server (), getpid (), &sid); + if (err) + argp_failure (state, 2, err, "Couldn't get current session id"); + return sid; +} + +/* Returns our login collection id. */ +static pid_t +current_lid (struct argp_state *state) +{ + pid_t lid = -1; + error_t err = proc_getloginid (proc_server (), getpid (), &lid); + if (err) + argp_failure (state, 2, err, "Couldn't get current login collection"); + return lid; +} + +/* Add a specific process to be printed out. */ +static error_t +parse_pid (unsigned pid, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = add_pid (params->pids, params->num_pids, pid); + if (err) + argp_failure (state, 2, err, "%d: Cannot add process", pid); + return err; +} + +/* Print out all process from the given session. */ +static error_t +parse_sid (unsigned sid, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = + add_fn_pids (params->pids, params->num_pids, sid, proc_getsessionpids); + if (err) + argp_failure (state, 2, err, "%d: Cannot add session", sid); + return err; +} + +/* Print out all process from the given login collection. */ +static error_t +parse_lid (unsigned lid, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = + add_fn_pids (params->pids, params->num_pids, lid, proc_getloginpids); + if (err) + argp_failure (state, 2, err, "%d: Cannot add login collection", lid); + return err; +} + +/* Print out all process from the given process group. */ +static error_t +parse_pgrp (unsigned pgrp, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = + add_fn_pids (params->pids, params->num_pids, pgrp, proc_getpgrppids); + if (err) + argp_failure (state, 2, err, "%d: Cannot add process group", pgrp); + return err; +} + +#define OA OPTION_ARG_OPTIONAL + +/* Options for PIDS_ARGP. */ +static const struct argp_option options[] = +{ + {"login", 'L', "LID", OA, "Processes from the login" + " collection LID (which defaults that of" + " the current process)"}, + {"lid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, + {"pid", 'p', "PID", 0, "The process PID"}, + {"pgrp", 'P', "PGRP", 0, "Processes in process group PGRP"}, + {"session", 'S', "SID", OA, "Processes from the session SID" + " (which defaults to that of the" + " current process)"}, + {"sid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, + {0, 0} +}; + +/* Parse one option/arg for PIDS_ARGP. */ +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + + switch (key) + { + case 'p': + return + parse_numlist (arg, parse_pid, NULL, NULL, "process id", state); + case 'S': + return + parse_numlist (arg, parse_sid, current_sid, NULL, "session id", state); + case 'L': + return + parse_numlist (arg, parse_lid, current_lid, NULL, "login collection", + state); + case 'P': + return + parse_numlist (arg, parse_pgrp, NULL, NULL, "process group", state); + + case ARGP_KEY_ARG: + if (params->parse_pid_args) + return parse_numlist (arg, parse_pid, NULL, NULL, "process id", state); + /* Else fall through */ + + default: + return ARGP_ERR_UNKNOWN; + } +} + +/* Filtering of help output strings for PIDS_ARGP. */ +static char * +help_filter (int key, const char *text, void *input) +{ + struct pids_argp_params *params = input; + + /* Describe the optional behavior of parsing normal args as pids. */ + if (key == ARGP_KEY_HELP_ARGS_DOC && params->parse_pid_args) + return strdup ("[PID...]"); + + return (char *)text; +} + +/* A parser for selecting a set of pids. */ +struct argp pids_argp = { options, parse_opt, 0, 0, 0, help_filter }; |