diff options
author | Michael I. Bushnell <mib@gnu.org> | 1994-07-21 19:03:46 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1994-07-21 19:03:46 +0000 |
commit | 1cde8b2682dc438ef0aafa37c4a8ca9863b1e33f (patch) | |
tree | 5eeba5d1f8aa7e8e559805e67b2203f4a1a0fd98 /utils | |
parent | 3e0f07c7d45f5e6ba6cff0215656db105a5e20af (diff) |
Initial revision
Diffstat (limited to 'utils')
-rw-r--r-- | utils/old-ps.c | 152 | ||||
-rw-r--r-- | utils/shd.c | 366 | ||||
-rw-r--r-- | utils/su.c | 461 |
3 files changed, 979 insertions, 0 deletions
diff --git a/utils/old-ps.c b/utils/old-ps.c new file mode 100644 index 00000000..0ff927e3 --- /dev/null +++ b/utils/old-ps.c @@ -0,0 +1,152 @@ +/* + Copyright (C) 1994 Free Software Foundation + + 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 <hurd.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> + +/* return a string describing the amount of memory SIZE represents. */ +char * +mem_str (vm_size_t size) +{ + char *ret = malloc (10); + char *spec=" KMG"; + int dec = 0; + + while (size > 1000) + { + dec = size % 1000; + size /= 1000; + spec++; + } + + if (size >= 100) + sprintf (ret, "%d%c", size, *spec); + else if (size >= 10) + sprintf (ret, "%d.%d%c", size, dec / 100, *spec); + else + sprintf (ret, "%d.%d%c", size, dec / 10, *spec); + + return ret; +} + +/* Return a string representing time T. */ +char * +time_str (time_value_t *t) +{ + char *ret = malloc (20); + int time; + + time = t->seconds * 1000000 + t->microseconds; + sprintf (ret, "%.2f", (double)time / 1000000.0 ); + return ret; +} + +/* Print a string describing the args of proc PID */ +void +print_args_str (process_t proc, pid_t pid) +{ + char *args; + u_int nargs = 0; + char *p; + error_t err; + + err = proc_getprocargs (proc, pid, &args, &nargs); + if (err) + return; + p = args; + while (p - args < nargs) + { + printf ("%s ", p); + p = strchr (p, '\0') + 1; + } + vm_deallocate (mach_task_self (), (vm_address_t) args, nargs); +} + + +/* Very simple PS */ +int +main () +{ + process_t proc; + pid_t pids[20]; + pid_t *pp = pids; + u_int npids = 20; + int ind; + struct thread_basic_info tbi; + struct thread_sched_info tsi; + +#if 0 + stdout = mach_open_devstream (getdport (1), "w"); +#endif + + puts ("PID\tUSER\tPP\tPG\tSS\tVMem\tRSS\tPRI\t%CPU\tUser\tSystem\tArgs"); + proc = getproc (); + proc_getallpids (proc, &pp, &npids); + for (ind = 0; ind < npids; ind++) + { + int procinfobuf[0]; + struct procinfo *pi = (struct procinfo *) procinfobuf; + u_int pisize = 0; + int i; + + proc_getprocinfo (proc, pp[ind], (int **)&pi, &pisize); + + if (pi->state & PI_NOPARENT) + continue; + + bzero (&tbi, sizeof tbi); + bzero (&tsi, sizeof tsi); + for (i = 0; i < pi->nthreads; i++) + { + tsi.base_priority += pi->threadinfos[i].pis_si.base_priority; + tsi.cur_priority += pi->threadinfos[i].pis_si.cur_priority; + tbi.cpu_usage += pi->threadinfos[i].pis_bi.cpu_usage; + tbi.user_time.seconds += pi->threadinfos[i].pis_bi.user_time.seconds; + tbi.user_time.microseconds + += pi->threadinfos[i].pis_bi.user_time.microseconds; + tbi.system_time.seconds + += pi->threadinfos[i].pis_bi.system_time.seconds; + tbi.system_time.microseconds + += pi->threadinfos[i].pis_bi.system_time.microseconds; + } + tsi.base_priority /= pi->nthreads; + tsi.cur_priority /= pi->nthreads; + tbi.user_time.seconds += tbi.user_time.microseconds / 1000000; + tbi.user_time.microseconds %= 1000000; + tbi.system_time.seconds += tbi.system_time.microseconds / 1000000; + tbi.system_time.microseconds %= 1000000; + printf ("%d\t%d\t%d\t%d\t%d\t%s\t%s\t%d/%d\t%d\t%s\t%s\t", + pp[ind], + (pi->state & PI_NOTOWNED) ? -1 : pi->owner, + pi->ppid, + pi->pgrp, + pi->session, + mem_str (pi->taskinfo.virtual_size), + mem_str (pi->taskinfo.resident_size), + tsi.base_priority, + tsi.cur_priority, + tbi.cpu_usage, + time_str (&tbi.user_time), + time_str (&tbi.system_time)); + print_args_str (proc, pp[ind]); + putchar ('\n'); + } + return 0; +} diff --git a/utils/shd.c b/utils/shd.c new file mode 100644 index 00000000..c85ff07d --- /dev/null +++ b/utils/shd.c @@ -0,0 +1,366 @@ +/* + Copyright (C) 1994 Free Software Foundation + + 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 <sys/types.h> +#include <hurd.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <device/device.h> +#include <unistd.h> +#include <errno.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <stdlib.h> +#include <hurd/exec.h> + +mach_port_t proc; +int pause_startup = 0; + +void +reap (pid_t waitfor) +{ + pid_t pid; + int status; + + while (1) + { + pid = waitpid (WAIT_ANY, &status, WUNTRACED | (waitfor ? 0 : WNOHANG)); + + if (pid == -1) + { + if (errno != ESRCH && errno != EWOULDBLOCK) + perror ("waitpid"); + return; + } + else if (WIFEXITED (status)) + printf ("PID %d exit status %d\n", + pid, WEXITSTATUS (status)); + else if (WIFSIGNALED (status)) + printf ("PID %d %s\n", + pid, strsignal (WTERMSIG (status))); + else if (WIFSTOPPED (status)) + printf ("PID %d stopped: %s\n", + pid, strsignal (WSTOPSIG (status))); + else + printf ("PID %d bizarre status %#x\n", pid, status); + + if (pid == waitfor) + waitfor = 0; + } +} + +pid_t +run (char **argv, int fd0, int fd1) +{ + file_t file; + char *program; + + if (strchr (argv[0], '/') != NULL) + program = argv[0]; + else + { + size_t len = strlen (argv[0]); + const char bin[] = "/bin/"; + program = alloca (sizeof bin + len); + memcpy (program, bin, sizeof bin - 1); + memcpy (&program[sizeof bin - 1], argv[0], len + 1); + } + + file = path_lookup (program, O_EXEC, 0); + if (file == MACH_PORT_NULL) + { + perror (program); + return -1; + } + else + { + task_t task; + pid_t pid; + + if (errno = task_create (mach_task_self (), 0, &task)) + { + perror ("task_create"); + pid = -1; + } + else + { + int save0, save1; + + inline int movefd (int from, int to, int *save) + { + if (from == to) + return 0; + *save = dup (to); + if (*save < 0) + { + perror ("dup"); + return -1; + } + if (dup2 (from, to) != to) + { + perror ("dup2"); + return -1; + } + close (from); + return 0; + } + inline int restorefd (int from, int to, int *save) + { + if (from == to) + return 0; + if (dup2 (*save, to) != to) + { + perror ("dup2"); + return -1; + } + close (*save); + return 0; + } + + pid = task2pid (task); + if (pid == -1) + perror ("task2pid"), pid = 0; + if (errno = proc_child (proc, task)) + perror ("proc_child"); + if (pause_startup) + { + printf ("Pausing..."); + fflush (stdout); + getchar (); + } + + if (movefd (fd0, 0, &save0) || + movefd (fd1, 1, &save1)) + return -1; + + errno = _hurd_exec (task, file, argv, environ); + + if (restorefd (fd0, 0, &save0) || + restorefd (fd1, 1, &save1)) + return -1; + + if (errno) + { + perror ("_hurd_exec"); + if (errno = task_terminate (task)) + perror ("task_terminate"); + } + mach_port_deallocate (mach_task_self (), task); + + } + mach_port_deallocate (mach_task_self (), file); + + return pid; + } +} + +void +command (int argc, char **argv) +{ + pid_t pid; + int bg; + int i, start; + int fds[2] = { 0, 1 }; + + if (bg = !strcmp (argv[argc - 1], "&")) + argv[--argc] = NULL; + + start = 0; + for (i = 1; i < argc; ++i) + if (! strcmp (argv[i], "|")) + { + int fd0 = fds[0]; + argv[i] = NULL; + if (pipe (fds)) + { + perror ("pipe"); + return; + } + pid = run (argv + start, fd0, fds[1]); + if (pid < 0) + return; + start = i + 1; + } + + pid = run (argv + start, fds[0], 1); + + if (fds[0] != 0) + close (fds[0]); + if (fds[1] != 1) + close (fds[1]); + + reap (bg ? 0 : pid); +} + + +int +main () +{ + char *linebuf = NULL; + size_t linebufsize = 0; + + proc = getproc (); + assert (proc); + +#if 0 + { + error_t err; + mach_port_t outp; + mach_port_t hostp, masterd; + err = proc_getprivports (proc, &hostp, &masterd); + assert (!err); + + err = device_open (masterd, D_WRITE|D_READ, "console", &outp); + assert (!err); + + stdin = mach_open_devstream (outp, "r"); + stdout = stderr = mach_open_devstream (outp, "w+"); + } +#endif + + /* Kludge to give boot a port to the auth server. */ + exec_init (getdport (0), getauth (), + MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); + + atexit ((void (*) (void)) &sync); + + while (1) + { + ssize_t n; + + sync (); + printf ("# "); + fflush (stdout); + n = getline (&linebuf, &linebufsize, stdin); + if (n == -1) + { + if (feof (stdin)) + return 0; + perror ("getline"); + continue; + } + + if (linebuf[n - 1] == '\n') + linebuf[--n] = '\0'; + + if (n > 0) + { + char *argv[(n + 1) / 2 + 1]; + int argc; + char *line, *p; + + line = linebuf; + argc = 0; + while ((p = strsep (&line, " \t\n\f\v")) != NULL) + argv[argc++] = p; + argv[argc] = NULL; + + if (!strcmp (argv[0], "exit")) + { + reap (0); + exit (0); + } + else if (!strcmp (argv[0], "pause")) + pause_startup = 1; + else if (!strcmp (argv[0], "nopause")) + pause_startup = 0; + else if (!strcmp (argv[0], "kill")) + { + if (argc == 1) + fprintf (stderr, "Usage: kill PID ...\n"); + else + { + int pid; + task_t task; + int i; + for (i = 1; i < argc; i++) + { + pid = atoi (argv[i]); + printf ("Killing pid %d\n", pid); + if (pid) + { + proc_pid2task (proc, pid, &task); + task_terminate (task); + mach_port_deallocate (mach_task_self (), task); + } + } + } + } + else if (!strcmp (argv[0], "cd")) + { + if (argc != 2) + fprintf (stderr, "Usage: cd DIRECTORY\n"); + else if (chdir (argv[1])) + perror ("chdir"); + } + else if (!strcmp (argv[0], "exec")) + { + if (argc == 1) + fprintf (stderr, "Usage: exec PROGRAM [ARGS...]\n"); + else + { + char *program; + if (strchr (argv[1], '/') != NULL) + program = argv[1]; + else + { + size_t len = strlen (argv[1]); + const char bin[] = "/bin/"; + program = alloca (sizeof bin + len); + memcpy (program, bin, sizeof bin - 1); + memcpy (&program[sizeof bin - 1], argv[1], len + 1); + } + if (execv (program, &argv[1]) == 0) + fprintf (stderr, "execv (%s) returned 0!\n", program); + else + perror ("execv"); + } + } + else if (!strcmp (argv[0], "setenv")) + { + if (argc != 3) + fprintf (stderr, "Usage: setenv VAR VALUE\n"); + else if (setenv (argv[1], argv[2], 1)) + perror ("setenv"); + } + else if (!strcmp (argv[0], "fork")) + { + pid_t pid = fork (); + switch (pid) + { + case -1: + perror ("fork"); + break; + case 0: + printf ("I am the child, PID %d.\n", (int) getpid ()); + break; + default: + printf ("I am the parent of child with PID %d.\n", pid); + reap (argc == 2 && !strcmp (argv[1], "&") ? 0 : pid); + break; + } + } + else + command (argc, argv); + } + reap (0); + fflush (stderr); + } +} + + diff --git a/utils/su.c b/utils/su.c new file mode 100644 index 00000000..3bff70ad --- /dev/null +++ b/utils/su.c @@ -0,0 +1,461 @@ +/* `su' for GNU Hurd. + Copyright (C) 1994 Free Software Foundation + Written by Roland McGrath. + +This file is part of the GNU Hurd. + +The GNU Hurd 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. + +The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + Unlike Unix su, this program does not spawn a subshell. Instead, it + adds or removes (with the -r flag) auth rights to all the processes in + the current login. Note that the addition and removal of rights to a + particular process is voluntary; the process doesn't get them unless + it's listening for the right rpc (which the C library normally does), + and it doesn't have to release any of the rights it has when requested + (though the C library does this automatically in most programs). + + The -r flag allows you to easily be authorized or not authorized for any + number of users (uids and gid sets). This program is not intelligent, + however. The -r flag always removes whatever gids the specified user + has. If some other user you have obtained authorization for has some of + the same gids, it will remove them. The C library could be intelligent + enough to look up the groups of all the uids it has, and make sure it + has at least those. */ + +#include <stdlib.h> +#include <hurd.h> +#include <pwd.h> +#include <grp.h> +#include <termios.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <getopt.h> +#include <hurd/msg.h> +#include <assert.h> + +process_t proc; /* Our proc server port. */ + +/* Command line flags. */ +int remove_ids = 0; /* -r: Remove ids instead of adding them. */ + +const struct option longopts[] = + { + { "remove", 0, 0, 'r' }, + { "uid", 0, 0, 'u' }, + { "gid", 0, 0, 'g' }, + { "loginuser", 0, 0, 'l' }, + { "pid", 0, 0, 'p' }, + { "pgrp", 0, 0, 'G' }, + { "loginid", 0, 0, 'i' }, + { 0, } + }; + +/* These functions return a malloc'd array of ids that can be passed to + make_auth_handle or used in del_auth messages. They check authorization + and return NULL on failure. */ +unsigned int *get_uid (const char *user); /* From a named user or UID. */ +unsigned int *get_gid (const char *user); /* From a named group or GID. */ +unsigned int *get_user (const char *user); /* All ids for a named user. */ + +int apply_ids (unsigned int *ids, pid_t, int); +int apply_ids_to_pids (unsigned int *ids, unsigned int, pid_t *, int); +int apply_ids_to_pgrp (unsigned int *ids, pid_t); +int apply_ids_to_loginid (unsigned int *ids, int); + +int check_password (const char *name, const char *password); + + +int +main (int argc, char **argv) +{ + int c; + int status; + enum { user, group, loginuser, loginid, pid, pgrp } mode = loginuser; + unsigned int *idsets[argc]; + unsigned int ididx = 0, loginidx = 0, pididx = 0, pgrpidx = 0; + int loginids[argc]; + pid_t pids[argc], pgrps[argc]; + unsigned int i, j; + + proc = getproc (); /* Used often. */ + + while ((c = getopt_long (argc, argv, "--rgulpiG", longopts, NULL)) != EOF) + switch (c) + { + case 'r': + remove_ids = 1; + break; + + case 'u': + mode = user; + break; + case 'g': + mode = group; + break; + case 'l': + mode = loginuser; + break; + case 'p': + mode = pid; + break; + case 'i': + mode = loginid; + break; + case 'G': + mode = pgrp; + break; + + case '\0': /* Non-option argument. */ + switch (mode) + { + case user: + idsets[ididx++] = get_uid (optarg); + break; + case group: + idsets[ididx++] = get_gid (optarg); + break; + case loginuser: + idsets[ididx++] = get_user (optarg); + break; + + case pid: + pids[pididx++] = atoi (optarg); + break; + case loginid: + loginids[loginidx++] = atoi (optarg); + break; + case pgrp: + pgrps[pgrpidx++] = atoi (optarg); + break; + } + break; + + case '?': + default: + fprintf (stderr, "Usage: %s [-r|--remove]\n\ + [-u|--uid UID...] [-g|--gid GID...] [-l|--loginuser USER...]\n\ + [-p|--pid PID...] [-i|--loginid ID...] [-G|--pgrp PGRP...]\n", + program_invocation_short_name); + exit (1); + } + + if (ididx == 0) + /* No ids specified; default is "su root". */ + idsets[ididx++] = get_user ("root"); + + if (pididx == 0 && loginidx == 0 && pgrpidx == 0) + /* No processes specified; default is current login collection. */ + if (errno = proc_getloginid (proc, getpid (), &loginids[loginidx++])) + { + perror ("proc_getloginid"); + return 1; + } + + status = 0; + + for (j = 0; j < ididx; ++j) + status |= apply_ids_to_pids (idsets[j], pididx, pids, 0); + + for (i = 0; i < loginidx; ++i) + { + for (j = 0; j < loginidx; ++j) + status |= apply_ids_to_loginid (idsets[j], loginids[i]); + } + + for (i = 0; i < pgrpidx; ++i) + { + for (j = 0; j < pgrpidx; ++j) + status |= apply_ids_to_loginid (idsets[j], pgrps[i]); + } + + + return status; +} + +/* Turn USER into a list of ids, giving USER's primary uid and gid from the + passwd file and all the groups that USER appears in in the group file. */ + +unsigned int * +get_user (const char *user) +{ + struct passwd *p; + unsigned int ngids, *ids; + + p = getpwnam (user); + if (p == NULL) + { + fprintf (stderr, "%s: User `%s' not found\n", + program_invocation_short_name, user); + return NULL; + } + + if (! check_password (user, p->pw_passwd)) + return NULL; + + /* We don't need to change our own gids, but it doesn't really hurt, + and initgroups does all the work for us. */ + if (initgroups (user, p->pw_gid) < 0) + { + perror ("initgroups"); + return NULL; + } + ngids = getgroups (0, NULL); + if ((int) ngids < 0) + { + getgroups_lost: + perror ("getgroups"); + return NULL; + } + assert (sizeof (*ids) == sizeof (gid_t)); + ids = malloc ((3 + ngids) * sizeof (*ids)); + ids[0] = 1; + ids[1] = p->pw_uid; + ids[2] = getgroups (ngids, &ids[3]); + if ((int) ids[2] < 0) + goto getgroups_lost; + + return ids; +} + +/* Return an id list containing just the uid of USER. */ + +unsigned int * +get_uid (const char *user) +{ + struct passwd *p; + unsigned int *ids; + uid_t uid; + char *uend; + + uid = strtoul (user, &uend, 10); + if (uend && *uend == '\0') + { + if (remove_ids || getuid () == 0) + /* No need to verify. */ + p = NULL; + else + { + p = getpwuid (uid); + if (p == NULL) + { + fprintf (stderr, "%s: UID %u not found\n", + program_invocation_short_name, uid); + return NULL; + } + } + } + else + { + p = getpwnam (user); + if (p == NULL) + { + fprintf (stderr, "%s: User `%s' not found\n", + program_invocation_short_name, user); + return NULL; + } + } + + if (p != NULL && ! check_password (user, p->pw_passwd)) + return NULL; + + ids = malloc (3 * sizeof (*ids)); + ids[0] = 1; + ids[1] = p->pw_uid; + ids[2] = 0; + + return ids; +} + +/* Return an id list containing just the gid of GROUP. */ + +unsigned int * +get_gid (const char *group) +{ + struct group *g; + unsigned int *ids; + gid_t gid; + char *gend; + + gid = strtoul (group, &gend, 10); + if (gend && *gend == '\0') + { + if (remove_ids || getuid () == 0) + /* No need to verify. */ + g = NULL; + else + { + g = getgrgid (gid); + if (g == NULL) + { + fprintf (stderr, "%s: GID %u not found\n", + program_invocation_short_name, gid); + return NULL; + } + } + } + else + { + g = getgrnam (group); + if (g == NULL) + { + fprintf (stderr, "%s: Group `%s' not found\n", + program_invocation_short_name, group); + return NULL; + } + } + + if (g != NULL && ! check_password (group, g->gr_passwd)) + return NULL; + + ids = malloc (3 * sizeof (*ids)); + ids[0] = 0; + ids[1] = 1; + ids[2] = g->gr_gid; + + return ids; +} + +/* Add or delete (under -r) the ids indicated by IDS to/from PID. If + IGNORE_BAD_PID is nonzero, return success if PID does not exist. + Returns zero if successful, nonzero on error (after printing message). */ + +int +apply_ids (unsigned int *ids, pid_t pid, int ignore_bad_pid) +{ + error_t err; + auth_t auth; + + if (! ids) + return 0; + + if (! remove_ids) + if (errno = auth_makeauth (getauth (), NULL, MACH_MSG_TYPE_COPY_SEND, 0, + &ids[1], ids[0], NULL, 0, + &ids[1 + ids[0] + 1], ids[1 + ids[0]], NULL, 0, + &auth)) + { + perror ("auth_makeauth"); + return 1; + } + + err = HURD_MSGPORT_RPC (proc_getmsgport (proc, pid, &msgport), + proc_pid2task (proc, pid, &refport), + remove_ids ? + del_auth (msgport, refport, + &ids[1], ids[0], + &ids[1 + ids[0] + 1], + ids[1 + ids[0]]) : + add_auth (msgport, auth)); + if (err && + (!ignore_bad_pid || (err != ESRCH && err != MIG_SERVER_DIED))) + { + fprintf (stderr, "%s: error in %s_auth from PID %d: %s\n", + program_invocation_short_name, + remove_ids ? "del" : "add", pid, strerror (err)); + return 1; + } + else + return 0; +} + +int +apply_ids_to_pids (unsigned int *ids, unsigned int npids, pid_t pids[], + int ignore_bad_pid) +{ + int status = 0; + unsigned int i; + + for (i = 0; i < npids; ++i) + status |= apply_ids (ids, pids[i], ignore_bad_pid); + + return status; +} + +int +apply_ids_to_loginid (unsigned int *ids, int loginid) +{ + unsigned int npids = 20; + pid_t pidbuf[20], *pids = pidbuf; + int status; + error_t err; + + if (err = proc_getloginpids (proc, loginid, &pids, &npids)) + { + fprintf (stderr, "%s: proc_getloginpids failed for loginid %d: %s\n", + program_invocation_short_name, loginid, strerror (err)); + return 1; + } + + status = apply_ids_to_pids (ids, npids, pids, 1); + + if (pids != pidbuf) + vm_deallocate (mach_task_self (), + (vm_address_t) pids, npids * sizeof (pid_t)); + + return status; +} + +int +apply_ids_to_pgrp (unsigned int *ids, pid_t pgrp) +{ + unsigned int npids = 20; + pid_t pidbuf[20], *pids = pidbuf; + int status; + error_t err; + + if (err = proc_getpgrppids (proc, pgrp, &pids, &npids)) + { + fprintf (stderr, "%s: proc_getpgrppids failed for pgrp %d: %s\n", + program_invocation_short_name, pgrp, strerror (err)); + return 1; + } + + status = apply_ids_to_pids (ids, npids, pids, 1); + + if (pids != pidbuf) + vm_deallocate (mach_task_self (), + (vm_address_t) pids, npids * sizeof (pid_t)); + + return status; +} + +/* Return 1 if the user gives the correct password matching the encrypted + string PASSWORD, 0 if not. Return 1 without asking for a password if + run by uid 0 or if PASSWORD is an empty password, and always under -r. + Always prints a message before returning 0. */ + +int +check_password (const char *name, const char *password) +{ + extern char *crypt (const char salt[2], const char *string); + char *unencrypted, *encrypted; + static char *prompt = NULL; + + if (remove_ids || getuid () == 0 || password == NULL || password[0] == '\0') + return 1; + + asprintf (&prompt, "%s's Password:", name); + unencrypted = getpass (prompt); + encrypted = crypt (unencrypted, password); + memset (unencrypted, 0, strlen (unencrypted)); /* Paranoia may destroya. */ + + if (!strcmp (encrypted, password)) + return 1; + + fprintf (stderr, "%s: Access denied for `%s'\n", + program_invocation_short_name, name); + return 0; +} |