aboutsummaryrefslogtreecommitdiff
path: root/libshouldbeinlibc
diff options
context:
space:
mode:
Diffstat (limited to 'libshouldbeinlibc')
-rw-r--r--libshouldbeinlibc/=argz.c190
-rw-r--r--libshouldbeinlibc/=argz.h89
-rw-r--r--libshouldbeinlibc/=envz.c171
-rw-r--r--libshouldbeinlibc/=envz.h55
-rw-r--r--libshouldbeinlibc/=line.c147
-rw-r--r--libshouldbeinlibc/=line.h128
-rw-r--r--libshouldbeinlibc/=path-lookup.c120
-rw-r--r--libshouldbeinlibc/ChangeLog614
-rw-r--r--libshouldbeinlibc/Makefile20
-rw-r--r--libshouldbeinlibc/argp-help.c908
-rw-r--r--libshouldbeinlibc/argp-parse.c662
-rw-r--r--libshouldbeinlibc/argp-pvh.c30
-rw-r--r--libshouldbeinlibc/argp.h356
-rw-r--r--libshouldbeinlibc/cacheq.c9
-rw-r--r--libshouldbeinlibc/exec-reauth.c20
-rw-r--r--libshouldbeinlibc/fsysops.c11
-rw-r--r--libshouldbeinlibc/idvec-auth.c40
-rw-r--r--libshouldbeinlibc/idvec-funcs.c2
-rw-r--r--libshouldbeinlibc/idvec-impgids.c127
-rw-r--r--libshouldbeinlibc/idvec-rep.c164
-rw-r--r--libshouldbeinlibc/idvec-verify.c362
-rw-r--r--libshouldbeinlibc/idvec.c189
-rw-r--r--libshouldbeinlibc/idvec.h151
-rw-r--r--libshouldbeinlibc/localhost.c23
-rw-r--r--libshouldbeinlibc/maptime-funcs.c5
-rw-r--r--libshouldbeinlibc/maptime.c67
-rw-r--r--libshouldbeinlibc/maptime.h27
-rw-r--r--libshouldbeinlibc/options.c231
-rw-r--r--libshouldbeinlibc/options.h79
-rw-r--r--libshouldbeinlibc/portinfo.c52
-rw-r--r--libshouldbeinlibc/portinfo.h2
-rw-r--r--libshouldbeinlibc/portxlate.c33
-rw-r--r--libshouldbeinlibc/timefmt.c1
-rw-r--r--libshouldbeinlibc/ugids-argp.c175
-rw-r--r--libshouldbeinlibc/ugids-auth.c53
-rw-r--r--libshouldbeinlibc/ugids-imply.c (renamed from libshouldbeinlibc/argp-pv.c)30
-rw-r--r--libshouldbeinlibc/ugids-merge.c109
-rw-r--r--libshouldbeinlibc/ugids-posix.c95
-rw-r--r--libshouldbeinlibc/ugids-rep.c118
-rw-r--r--libshouldbeinlibc/ugids-subtract.c130
-rw-r--r--libshouldbeinlibc/ugids-verify-auth.c190
-rw-r--r--libshouldbeinlibc/ugids-verify.c70
-rw-r--r--libshouldbeinlibc/ugids-xinl.c23
-rw-r--r--libshouldbeinlibc/ugids.c97
-rw-r--r--libshouldbeinlibc/ugids.h229
-rw-r--r--libshouldbeinlibc/wire.c65
-rw-r--r--libshouldbeinlibc/xportinfo.c13
47 files changed, 2429 insertions, 4053 deletions
diff --git a/libshouldbeinlibc/=argz.c b/libshouldbeinlibc/=argz.c
deleted file mode 100644
index fd90a1e2..00000000
--- a/libshouldbeinlibc/=argz.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Routines for dealing with '\0' separated arg vectors.
-
- Copyright (C) 1995 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 <string.h>
-#include <errno.h>
-
-/* ---------------------------------------------------------------- */
-
-/* Make a '\0' separated arg vector from a unix argv vector, returning it in
- ARGZ, and the total length in LEN. If a memory allocation error occurs,
- ENOMEM is returned, otherwise 0. */
-error_t
-argz_create(char **argv, char **argz, int *len)
-{
- int tlen = 0;
- char **argp;
-
- for (argp = argv; *argp != NULL; argp++)
- tlen += strlen(*argp) + 1;
-
- *len = tlen;
-
- if (tlen == 0)
- *argz = NULL;
- else
- {
- *argz = malloc(tlen);
- if (*argz == NULL)
- return ENOMEM;
-
- while (tlen > 0)
- {
- tlen -= strlen(*--argp) + 1;
- strcpy(*argz + tlen, *argp);
- }
- }
-
- return 0;
-}
-
-/* ---------------------------------------------------------------- */
-
-/* Returns the number of strings in ARGZ. */
-int
-argz_count (char *argz, int len)
-{
- int count = 0;
- while (len > 0)
- {
- int part_len = strlen(argz);
- argz += part_len + 1;
- len -= part_len + 1;
- count++;
- }
- return count;
-}
-
-/* ---------------------------------------------------------------- */
-
-/* Puts pointers to each string in ARGZ into ARGV, which must be large enough
- to hold them all. */
-void
-argz_extract (char *argz, int len, char **argv)
-{
- while (len > 0)
- {
- int part_len = strlen(argz);
- *argv++ = argz;
- argz += part_len + 1;
- len -= part_len + 1;
- }
-}
-
-/* ---------------------------------------------------------------- */
-
-/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
- except the last into the character SEP. */
-void
-argz_stringify(char *argz, int len, int sep)
-{
- while (len > 0)
- {
- int part_len = strlen(argz);
- argz += part_len;
- len -= part_len + 1;
- if (len > 0)
- *argz++ = sep;
- }
-}
-
-/* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
-error_t
-argz_append (char **argz, unsigned *argz_len, char *buf, unsigned buf_len)
-{
- unsigned new_argz_len = *argz_len + buf_len;
- char *new_argz = realloc (*argz, new_argz_len);
- if (new_argz)
- {
- bcopy (buf, new_argz + *argz_len, buf_len);
- *argz = new_argz;
- *argz_len = new_argz_len;
- return 0;
- }
- else
- return ENOMEM;
-}
-
-/* Add STR to the argz vector in ARGZ & ARGZ_LEN. This should be moved into
- argz.c in libshouldbelibc. */
-error_t
-argz_add (char **argz, unsigned *argz_len, char *str)
-{
- return argz_append (argz, argz_len, str, strlen (str) + 1);
-}
-
-/* Delete ENTRY from ARGZ & ARGZ_LEN, if any. */
-void
-argz_delete (char **argz, unsigned *argz_len, char *entry)
-{
- if (entry)
- /* Get rid of the old value for NAME. */
- {
- unsigned entry_len = strlen (entry) + 1;
- *argz_len -= entry_len;
- bcopy (entry + entry_len, entry, *argz_len - (entry - *argz));
- if (*argz_len == 0)
- {
- free (*argz);
- *argz = 0;
- }
- }
-}
-
-/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
- existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
- Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
- ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
- in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
- ARGZ, ENOMEM is returned, else 0. */
-error_t
-argz_insert (char **argz, unsigned *argz_len, char *before, char *entry)
-{
- if (! before)
- return argz_add (argz, argz_len, entry);
-
- if (before < *argz || before >= *argz + *argz_len)
- return EINVAL;
-
- if (before > *argz)
- /* Make sure before is actually the beginning of an entry. */
- while (before[-1])
- before--;
-
- {
- unsigned after_before = *argz_len - (before - *argz);
- unsigned entry_len = strlen (entry) + 1;
- unsigned new_argz_len = *argz_len + entry_len;
- char *new_argz = realloc (*argz, new_argz_len);
-
- if (new_argz)
- {
- before = new_argz + (before - *argz);
- bcopy (before, before + entry_len, after_before);
- bcopy (entry, before, entry_len);
- *argz = new_argz;
- *argz_len = new_argz_len;
- return 0;
- }
- else
- return ENOMEM;
- }
-}
diff --git a/libshouldbeinlibc/=argz.h b/libshouldbeinlibc/=argz.h
deleted file mode 100644
index 1de0cd64..00000000
--- a/libshouldbeinlibc/=argz.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Routines for dealing with '\0' separated arg vectors.
-
- Copyright (C) 1995 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. */
-
-#ifndef __ARGZ_H__
-#define __ARGZ_H__
-
-/* Make a '\0' separated arg vector from a unix argv vector, returning it in
- ARGZ, and the total length in LEN. If a memory allocation error occurs,
- ENOMEM is returned, otherwise 0. The result can be destroyed using free. */
-error_t argz_create(char **argv, char **argz, int *len);
-
-/* Returns the number of strings in ARGZ. */
-int argz_count (char *argz, int len);
-
-/* Puts pointers to each string in ARGZ into ARGV, which must be large enough
- to hold them all. */
-void argz_extract (char *argz, int len, char **argv);
-
-/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
- except the last into the character SEP. */
-void argz_stringify(char *argz, int len, int sep);
-
-/* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
-error_t
-argz_append (char **argz, unsigned *argz_len, char *buf, unsigned buf_len);
-
-/* Add STR to the argz vector in ARGZ & ARGZ_LEN. This should be moved into
- argz.c in libshouldbelibc. */
-error_t argz_add (char **argz, unsigned *argz_len, char *str);
-
-/* Delete ENTRY from ARGZ & ARGZ_LEN, if any. */
-void argz_delete (char **argz, unsigned *argz_len, char *entry);
-
-/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
- existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
- Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
- ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
- in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
- ARGZ, ENOMEM is returned, else 0. */
-error_t
-argz_insert (char **argz, unsigned *argz_len, char *before, char *entry);
-
-/* Returns the next entry in ARGZ & ARGZ_LEN after ENTRY, or NULL if there
- are no more. If entry is NULL, then the first entry is returned. This
- behavior allows two convenient iteration styles:
-
- char *entry = 0;
- while (entry = argz_next (argz, argz_len, entry))
- ...;
-
- or
-
- char *entry;
- for (entry = argz; entry; entry = argz_next (argz, argz_len, entry))
- ...;
-*/
-extern inline char *
-argz_next (char *argz, unsigned argz_len, char *entry)
-{
- if (entry)
- if (entry >= argz + argz_len)
- return 0;
- else
- return entry + strlen (entry) + 1;
- else
- if (argz_len > 0)
- return argz;
- else
- return 0;
-}
-
-#endif /* __ARGZ_H__ */
diff --git a/libshouldbeinlibc/=envz.c b/libshouldbeinlibc/=envz.c
deleted file mode 100644
index 4d0816e4..00000000
--- a/libshouldbeinlibc/=envz.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* Routines for dealing with '\0' separated environment vectors
-
- Copyright (C) 1995, 1996 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 <malloc.h>
-#include <string.h>
-
-#include "envz.h"
-
-/* The character separating names from values in an envz. */
-#define SEP '='
-
-/* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none.
- If NAME contains the separator character, only the portion before it is
- used in the comparison. */
-char *
-envz_entry (char *envz, unsigned envz_len, char *name)
-{
- while (envz_len)
- {
- char *p = name;
- char *entry = envz; /* Start of this entry. */
-
- /* See how far NAME and ENTRY match. */
- while (envz_len && *p == *envz && *p && *p != SEP)
- p++, envz++, envz_len--;
-
- if ((*envz == '\0' || *envz == SEP) && (*p == '\0' || *p == SEP))
- /* Bingo! */
- return entry;
-
- /* No match, skip to the next entry. */
- while (envz_len && *envz)
- envz++, envz_len--;
- if (envz_len)
- envz++, envz_len--; /* skip '\0' */
- }
-
- return 0;
-}
-
-/* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0
- if there is none. */
-char *
-envz_get (char *envz, unsigned envz_len, char *name)
-{
- char *entry = envz_entry (envz, envz_len, name);
- if (entry)
- {
- while (*entry && *entry != SEP)
- entry++;
- if (*entry)
- entry++;
- else
- entry = 0; /* A null entry. */
- }
- return entry;
-}
-
-/* Remove the entry for NAME from ENVZ & ENVZ_LEN, if any. */
-void
-envz_remove (char **envz, unsigned *envz_len, char *name)
-{
- char *entry = envz_entry (*envz, *envz_len, name);
- if (entry)
- argz_delete (envz, envz_len, entry);
-}
-
-/* Adds an entry for NAME with value VALUE to ENVZ & ENVZ_LEN. If an entry
- with the same name already exists in ENVZ, it is removed. If VALUE is
- NULL, then the new entry will a special null one, for which envz_get will
- return NULL, although envz_entry will still return an entry; this is handy
- because when merging with another envz, the null entry can override an
- entry in the other one. Null entries can be removed with envz_strip (). */
-error_t
-envz_add (char **envz, unsigned *envz_len, char *name, char *value)
-{
- envz_remove (envz, envz_len, name);
-
- if (value)
- /* Add the new value, if there is one. */
- {
- unsigned name_len = strlen (name);
- unsigned value_len = strlen (value);
- unsigned old_envz_len = *envz_len;
- unsigned new_envz_len = old_envz_len + name_len + 1 + value_len + 1;
- char *new_envz = realloc (*envz, new_envz_len);
-
- if (new_envz)
- {
- bcopy (name, new_envz + old_envz_len, name_len);
- new_envz[old_envz_len + name_len] = SEP;
- bcopy (value, new_envz + old_envz_len + name_len + 1, value_len);
- new_envz[new_envz_len - 1] = 0;
-
- *envz = new_envz;
- *envz_len = new_envz_len;
-
- return 0;
- }
- else
- return ENOMEM;
- }
- else
- /* Add a null entry. */
- return argz_add (envz, envz_len, name);
-}
-
-/* Adds each entry in ENVZ2 to ENVZ & ENVZ_LEN, as if with envz_add(). If
- OVERRIDE is true, then values in ENVZ2 will supercede those with the same
- name in ENV, otherwise not. */
-error_t
-envz_merge (char **envz, unsigned *envz_len, char *envz2, unsigned envz2_len,
- int override)
-{
- error_t err = 0;
-
- while (envz2_len && ! err)
- {
- char *old = envz_entry (*envz, *envz_len, envz2);
- size_t new_len = strlen (envz2) + 1;
-
- if (! old)
- err = argz_append (envz, envz_len, envz2, new_len);
- else if (override)
- {
- argz_delete (envz, envz_len, old);
- err = argz_append (envz, envz_len, envz2, new_len);
- }
-
- envz2 += new_len;
- envz2_len -= new_len;
- }
-
- return err;
-}
-
-/* Remove null entries. */
-void
-envz_strip (char **envz, unsigned *envz_len)
-{
- char *entry = *envz;
- unsigned left = *envz_len;
- while (left)
- {
- unsigned entry_len = strlen (entry) + 1;
- left -= entry_len;
- if (! index (entry, SEP))
- /* Null entry. */
- bcopy (entry, entry + entry_len, left);
- else
- entry += entry_len;
- }
- *envz_len = entry - *envz;
-}
diff --git a/libshouldbeinlibc/=envz.h b/libshouldbeinlibc/=envz.h
deleted file mode 100644
index 55224c72..00000000
--- a/libshouldbeinlibc/=envz.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Routines for dealing with '\0' separated environment vectors
-
- Copyright (C) 1995 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. */
-
-#ifndef __ENVZ_H__
-#define __ENVZ_H__
-
-#include <errno.h>
-
-/* Envz's are argz's too, and should be created etc., using the same
- routines. */
-#include <argz.h>
-
-/* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none. */
-char *envz_entry (char *envz, unsigned envz_len, char *name);
-
-/* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0
- if there is none. */
-char *envz_get (char *envz, unsigned envz_len, char *name);
-
-/* Adds an entry for NAME with value VALUE to ENVZ & ENVZ_LEN. If an entry
- with the same name already exists in ENVZ, it is removed. If VALUE is
- NULL, then the new entry will a special null one, for which envz_get will
- return NULL, although envz_entry will still return an entry; this is handy
- because when merging with another envz, the null entry can override an
- entry in the other one. Null entries can be removed with envz_strip (). */
-error_t envz_add (char **envz, unsigned *envz_len, char *name, char *value);
-
-/* Adds each entry in ENVZ2 to ENVZ & ENVZ_LEN, as if with envz_add(). If
- OVERRIDE is true, then values in ENVZ2 will supercede those with the same
- name in ENV, otherwise not. */
-error_t
-envz_merge (char **envz, unsigned *envz_len, char *envz2, unsigned envz2_len,
- int override);
-
-/* Remove null entries. */
-void envz_strip (char **envz, unsigned *envz_len);
-
-#endif /* __ENVZ_H__ */
diff --git a/libshouldbeinlibc/=line.c b/libshouldbeinlibc/=line.c
deleted file mode 100644
index 1c8eab8e..00000000
--- a/libshouldbeinlibc/=line.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Simple output formatting functions
-
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <malloc.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <line.h>
-
-/* Return a new line structure, which will output to STREAM. WIDTH is the
- maximum number of characters per line. If enough memory can't be
- allocated, 0 is returned. */
-struct line *
-make_line (FILE *stream, unsigned width)
-{
- struct line *line = malloc (sizeof (struct line));
- if (line)
- {
- line->buf = malloc (width + 2);
- if (line->buf)
- {
- line->max = line->buf + width;
- line->point = line->buf;
- line->stream = stream;
- }
- else
- {
- free (line);
- line = 0;
- }
- }
- return line;
-}
-
-/* Free LINE and any resources it uses. */
-void
-line_free (struct line *line)
-{
- if (line->point > line->buf)
- line_newline (line, 0);
- free (line->buf);
- free (line);
-}
-
-/* Adds the text in STR to LINE, wrapping words as necessary to fit.
- LMARGIN is the left margin used when wrapping; whitespace is deleted at
- wrap-points. Newlines in STR are honoured by adding a newline and
- indenting to LMARGIN; any following whitespace is kept. */
-void
-line_fill (struct line *line, const char *str, unsigned lmargin)
-{
- while (*str)
- {
- const char *word_end = str;
-
- while (*word_end == ' ')
- word_end++;
-
- if (*word_end == '\n')
- {
- if (line_column (line) > lmargin)
- line_newline (line, lmargin);
- str = word_end + 1;
- }
- else if (*word_end)
- {
- const char *word_start = word_end;
- while (*word_end && !isspace (*word_end))
- word_end++;
- if (line_left (line, word_end - str) >= 0)
- {
- line_write (line, str, word_end - str);
- str = word_end;
- }
- else
- /* Word won't fit on the current line, move to the next one. */
- {
- line_newline (line, lmargin);
- str = word_start; /* Omit spaces when wrapping. */
- }
- }
- }
-}
-
-/* Clean up after a printf to LINE, to take care of any newlines that might
- have been added. ADDED is the amount the printf has added to the line.
- We take care of updating LINE's point. */
-void
-_line_cleanup_printf (struct line *line, unsigned added)
-{
- char *point = line->point, *new_point = point + added, *last_nl = new_point;
-
- while (last_nl > point)
- if (*--last_nl == '\n')
- /* There's a newline; deal. */
- {
- last_nl++;
- fwrite (line->buf, 1, last_nl - line->buf, line->stream);
- if (last_nl < new_point)
- bcopy (last_nl, line->buf, new_point - last_nl);
- new_point -= (last_nl - line->buf);
- break;
- }
-
- line->point = new_point;
-}
-
-/* Add STR, of length LEN, to LINE. */
-void
-line_write (struct line *line, const char *str, unsigned len)
-{
- const char *end = memchr (str, '\n', len) ?: str + len;
- unsigned line_len = end - str;
- char *p = line->point, *max = line->max;
- if (line_len > max - p)
- line_len = max - p;
- bcopy (str, p, line_len);
- p += line_len;
- if (line_len == len)
- line->point = p;
- else
- {
- char *buf = line->buf;
- fwrite (buf, 1, p - buf, line->stream);
- line->point = buf;
- line_write (line, end + 1, len - line_len - 1);
- }
-}
diff --git a/libshouldbeinlibc/=line.h b/libshouldbeinlibc/=line.h
deleted file mode 100644
index 54ab15de..00000000
--- a/libshouldbeinlibc/=line.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Simple output formatting functions
-
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef __LINE_H__
-#define __LINE_H__
-
-#include <stdio.h>
-
-struct line
-{
- char *buf;
- char *point, *max;
- FILE *stream;
-};
-
-extern void
-_line_cleanup_printf (struct line *line, unsigned added);
-
-/* Printf FMT & ARGS to LINE. */
-/* XXX This implementation is kind of bogus because it pretends to deal with
- newlines in the output, but it just uses LINE's buffer for the output and
- anything past the end of the buffer will get chopped. A terminating
- newline will work ok though. */
-#define line_printf(line, fmt, args...) \
- ({ struct line *_line = (line); \
- _line_cleanup_printf (_line, \
- snprintf (_line->point, _line->max - _line->point, (fmt) , ##args)); \
- })
-
-/* Returns the amount of free space in line after adding AMOUNT characters to
- it (which will be negative if this would overflow). */
-extern inline int
-line_left (struct line *line, unsigned amount)
-{
- return line->max - line->point - amount;
-}
-
-/* Return the column position of LINE's output point, which starts at 0. */
-extern inline unsigned
-line_column (struct line *line)
-{
- return line->point - line->buf;
-}
-
-/* Add enough spaces to LINE to move the point to column TARGET. */
-
-
-extern inline void
-line_indent_to (struct line *line, int target)
-{
- while (line->point < line->buf + target && line->point < line->max)
- *line->point++ = ' ';
-}
-
-/* Emit the current contents of LINE and a newline to its stream, and fill
- LINE with LMARGIN spaces. */
-extern inline void
-line_newline (struct line *line, int lmargin)
-{
- *line->point++ = '\n';
- *line->point = '\0';
- fputs (line->buf, line->stream);
- line->point = line->buf;
- if (lmargin)
- line_indent_to (line, lmargin);
-}
-
-/* If LINE isn't before or at column position LMARGIN, then add a newline
- and indent to that position. */
-extern inline void
-line_freshline (struct line *line, int lmargin)
-{
- if (line_column (line) > lmargin)
- line_newline (line, lmargin);
-}
-
-/* Add a character to LINE, unless it's full. */
-extern inline int
-line_putc (struct line *line, int ch)
-{
- if (ch == '\n')
- line_newline (line, 0);
- else if (line->point < line->max)
- *line->point++ = ch;
- return ch;
-}
-
-/* Adds the text in STR to LINE, wrapping words as necessary to fit. LMARGIN
- is the left margin used when wrapping. */
-void line_fill (struct line *line, const char *str, unsigned lmargin);
-
-/* Add STR, of length LEN, to LINE. */
-void line_write (struct line *line, const char *str, unsigned len);
-
-/* Add STR to LINE. */
-extern inline void line_puts (struct line *line, const char *str)
-{
- line_write (line, str, strlen (str));
-}
-
-/* Return a new line structure, which will output to STREAM. WIDTH is the
- maximum number of characters per line. If enough memory can't be
- allocated, 0 is returned. */
-struct line *make_line (FILE *stream, unsigned width);
-
-/* Free LINE and any resources it uses. */
-void line_free (struct line *line);
-
-#endif /* __LINE_H__ */
diff --git a/libshouldbeinlibc/=path-lookup.c b/libshouldbeinlibc/=path-lookup.c
deleted file mode 100644
index b89f8d4d..00000000
--- a/libshouldbeinlibc/=path-lookup.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Filename lookup using a search path
-
- Copyright (C) 1995 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 <string.h>
-#include <hurd.h>
-#include <hurd/lookup.h>
-
-/* If FILE_NAME contains a '/', or PATH is NULL, call FUN with FILE_NAME, and
- return the result (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to
- NULL). Otherwise, call FUN repeatedly with FILE_NAME prefixed with each
- successive `:' separated element of PATH, returning whenever FUN returns
- 0 (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to the resulting
- prefixed path). If FUN never returns 0, return the first non-ENOENT
- return value, or ENOENT if there is none. */
-error_t
-file_name_path_scan (const char *file_name, const char *path,
- error_t (*fun)(const char *name),
- char **prefixed_name)
-{
- if (path == NULL || index (file_name, '/'))
- {
- if (prefixed_name)
- *prefixed_name = 0;
- return (*fun)(file_name);
- }
- else
- {
- error_t real_err = 0;
- size_t file_name_len = strlen (file_name);
-
- for (;;)
- {
- error_t err;
- const char *next = index (path, ':') ?: path + strlen (path);
- size_t pfx_len = next - path;
- char pfxed_name[pfx_len + 2 + file_name_len + 1];
-
- if (pfx_len == 0)
- pfxed_name[pfx_len++] = '.';
- else
- bcopy (path, pfxed_name, pfx_len);
- if (pfxed_name[pfx_len - 1] != '/')
- pfxed_name[pfx_len++] = '/';
- bcopy (file_name, pfxed_name + pfx_len, file_name_len + 1);
-
- err = (*fun)(pfxed_name);
- if (err == 0)
- {
- if (prefixed_name)
- *prefixed_name = strdup (pfxed_name);
- return 0;
- }
- if (!real_err && err != ENOENT)
- real_err = err;
-
- if (*next == '\0')
- return real_err ?: ENOENT;
- else
- path = next + 1;
- }
- }
-}
-
-/* Lookup FILE_NAME and return the node opened with FLAGS & MODE in result
- (see hurd_file_name_lookup for details), but a simple filename (without
- any directory prefixes) will be consectutively prefixed with the pathnames
- in the `:' separated list PATH until one succeeds in a successful lookup.
- If none succeed, then the first error that wasn't ENOENT is returned, or
- ENOENT if no other errors were returned. If PREFIXED_NAME is non-NULL,
- then if RESULT is looked up directly, *PREFIXED_NAME is set to NULL, and
- if it is looked up using a prefix from PATH, *PREFIXED_NAME is set to
- malloced storage containing the prefixed name. */
-error_t
-hurd_file_name_path_lookup (error_t (*use_init_port)
- (int which,
- error_t (*operate) (mach_port_t)),
- file_t (*get_dtable_port) (int fd),
- const char *file_name, const char *path,
- int flags, mode_t mode,
- file_t *result, char **prefixed_name)
-{
- error_t lookup (const char *name)
- {
- return
- __hurd_file_name_lookup (use_init_port, get_dtable_port,
- name, flags, mode, result);
- }
- return file_name_path_scan (file_name, path, lookup, prefixed_name);
-}
-
-mach_port_t
-file_name_path_lookup (const char *file_name, const char *path,
- int flags, mode_t mode, char **prefixed_name)
-{
- error_t err;
- file_t result;
-
- err = hurd_file_name_path_lookup (&_hurd_ports_use, &__getdport,
- file_name, path, flags, mode,
- &result, prefixed_name);
-
- return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
-}
diff --git a/libshouldbeinlibc/ChangeLog b/libshouldbeinlibc/ChangeLog
deleted file mode 100644
index ab2b938f..00000000
--- a/libshouldbeinlibc/ChangeLog
+++ /dev/null
@@ -1,614 +0,0 @@
-Wed Jul 31 15:24:09 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
-
- * wire.c (_start): No longer declared as weak, now that everything
- is getting recompiled anyway.
-
-Fri Jul 26 20:57:53 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_past_time): Always use WIDTH+1 as strftime's limit.
-
-Thu Jul 25 23:10:35 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_past_time): Terminate SEPS.
-
- * argp-help.c (hol_entry_help): Never return without restoring margins.
-
-Mon Jul 22 23:41:38 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_past_time): Try several separators when
- concatenating dates & times.
-
-Fri Jul 19 17:23:18 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (hol_usage): Allocate enough space in
- SHORT_NO_ARG_OPTS for the '\0' terminator.
-
-Tue Jul 16 00:24:18 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (argp_help): Set the lmargin after printing the
- start of the usage message, so that it won't get indented.
-
-Wed Jul 10 12:16:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_version_options, argp_version_parser): Use an
- uppercase 'V' for short version option.
-
- * argp-help.c (argp_help): "OPTIONS..." -> "OPTION...".
-
-Sat Jul 6 16:17:53 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_version_parser): Output ARGP_PROGRAM_VERSION
- to STATE->out_stream, not stdout. Supply that stream and STATE to
- ARGP_PROGRAM_VERSION_HOOK.
- * argp.h (argp_program_version_hook): Add argument types.
- * argp-pv.c (argp_program_version): Doc updated.
- * argp-pvh.c (argp_program_version_hook): Type & doc updated.
- "argp.h": New include.
-
-Fri Jul 5 17:13:12 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_past_time): Get rid of extraneous `f' in fmt string.
-
-Thu Jun 27 17:09:30 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Zero the CHILD_INPUTS vector.
-
-Fri Jun 21 17:15:31 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Use group_parse instead of calling
- group parser directly for long options.
-
-Wed Jun 19 13:11:15 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fsysops.c: New file.
- * Makefile (SRCS): Add fsysops.c.
-
-Tue Jun 18 21:09:52 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (argp_failure): If FMT is 0, don't print `: MSG'.
-
-Sun Jun 16 19:25:10 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * Makefile (SRCS): Remove line.c.
- (LCLHDRS): Remove line.h.
-
- * argp-help.c (argp_help, argp_state_help, argp_error, argp_failure):
- Handle null streams.
-
- * argp.h (struct argp_state): Add NAME, ERR_STREAM, & OUT_STREAM
- fields.
- (argp_failure): New declaration.
- (ARGP_NO_HELP, ARGP_NO_EXIT): Fix values (were hex, but with
- decimal value!).
- (argp_help): Add NAME argument.
- * argp-parse.c (argp_default_parser): Output to STATE->out_stream.
- (argp_parse): Initialize new fields in STATE.
- Output errors to STATE.err_stream. Handle null streams.
-
- * argp-help.c (argp_help): Add and use NAME argument.
- (argp_error): Use STATE->err_stream instead of STDERR.
- (argp_state_help): Supply NAME argument to argp_help.
- (argp_failure): New function.
-
-Thu May 30 18:10:35 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (indent_to): Terminate.
-
-Tue May 28 18:05:40 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_seconds): Don't print two decimal points.
-
-Wed May 22 00:11:24 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_default_parser): Break after --HANG.
-
- * argp-help.c (hol_usage): Prefix each option desc with a space.
- Do manual wrapping of descs with an embedded space.
- Don't set wrap margin (done elsewhere now).
- (argp_args_usage): Do manual line wrapping because of embedded spaces.
- (argp_help): Set wrap & left margins when printing usage.
-
- * argp-parse.c (argp_parse): Only print a `Try...' message if the
- error was a parsing error.
-
-Tue May 14 21:59:43 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (add_field): Correctly decrement *SECS by amount printed.
-
- * timefmt.c (fmt_named_interval): Use fraction digit in more cases.
- Always pick the last suffix if we can't find any that fits.
- Use new tv_ functions.
- (tv_is_zero, tv_is_ge): New functions.
-
-Fri May 10 23:17:38 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (ARGP_ERR_UNKNOWN): New define.
- * argp-parse.c (EBADKEY): New define.
- (argp_default_parser, argp_version_parser, argp_parse): Use
- EBADKEY instead of EINVAL. Turn any EBADKEY that makes it to the
- end back into EINVAL.
-
-Thu May 9 11:30:47 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * maptime.c (maptime_map): Use new file_get_storage_info interface.
-
- * argp-help.c (argp_help): Just assign STREAM instead of using 2 vars.
-
-Thu May 9 11:00:52 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * exec-reauth.c (exec_reauth): Use new args to
- auth_user_authenticate.
-
- * timefmt.c (fmt_past_time): Cast arg to localtime appropriately.
-
- * argp-help.c (argp_args_usage): add_usage_item -> fprintf.
- (argp_help): Don't shadow arg; change parm STREAM to be STREAMARG
- and adjust initialization of STREAM variable to use the renamed
- parm.
-
-Tue May 7 14:58:48 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_past_time): Suppress leading noise in some formats.
-
- * argp-help.c (hol_usage): Set the wmargin, not the lmargin.
- (hol_help): Set the wmargin as well as the lmargin.
- * argp-help.c <linewrap.h>: New include.
- (lmargin): Function deleted.
- (hol_entry_help, hol_usage): Use line_wrap_set_lmargin instead.
-
-Mon May 6 12:46:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c <line.h>: Include removed.
- (lmargin, indent_to): New functions.
- (argp_usage_arg): Function removed.
- (hol_entry_help, hol_help, hol_usage, argp_args_usage, argp_doc,
- argp_help): Use stdio streams and line_wrap_ functions instead of
- line_ functions.
-
-Sat May 4 05:32:28 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
-
- * rwlock.h: Moved to ../libthreads.
- * Makefile (LCLHDRS): Remove rwlock.h.
-
-Fri May 3 18:10:41 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
-
- * path-lookup.c: File removed.
- * Makefile (SRCS): Remove path-lookup.c.
-
- * argz.c, argz.h, envz.c, envz.h: Files removed.
- * Makefile (SRCS): Remove argz.c, envz.c.
- (LCLHDRS): Remove argz.h, envz.h.
-
-Thu May 2 00:31:32 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (_argp_hang): New variable.
- (OPT_HANG): New macro.
- (argp_default_options, argp_default_parser): Add hidden --HANG option.
- (argp_default_parser): New function.
- (argp_version_options, argp_version_argp): New variables.
- (argp_parse): Use ARGP_VERSION_ARGP when appropiate.
- * argp.h (argp_program_version, argp_program_version_hook): New decls.
- * Makefile (SRCS): Add argp-pv.c & argp-pvh.c.
- * argp-pv.c, argp-pvh.c: New files.
-
-Tue Apr 30 20:25:12 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_past_time): New function.
- (fmt_minutes, fmt_seconds): New args, rewrite.
- (add_field): New function.
- (fmt_frac_value, append_fraction): Functions removed.
- * timefmt.h (fmt_past_time): New declaration.
- (fmt_minutes, fmt_seconds): Update.
-
- * argp-parse.c (argp_parse): Work with ARGP == 0.
-
-Mon Apr 29 15:34:00 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * cacheq.c, cacheq.h: New files.
- * Makefile (SRCS): Add cacheq.c.
- (LCLHDRS): Add cacheq.h.
-
-Thu Apr 25 00:09:48 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
-
- * idvec.c (idvec_free_contents): New function.
- * idvec.h (idvec_free_contents): Declare it.
-
-Thu Apr 11 15:23:15 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wire.c (wire_segment_internal): Cast values nicely in `poke'
- loop.
-
-Wed Apr 3 12:57:39 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (argp_parse): Change HOOK argument to INPUT.
- (struct argp_state): Rename HOOK & CHILD_HOOKS to INPUT & CHILD_INPUTS;
- add HOOK field again.
- * argp-parse.c (argp_parse): Change HOOK argument to INPUT.
- Don't propagate back return values when we're done.
- (struct group): Rename HOOK & CHILD_HOOKS to INPUT & CHILD_INPUTS;
- add HOOK field again.
- (group_parse): Restore and save value of GROUP's hook field into
- STATE around calling the parser. Don't save changed value of INPUT.
-
-Tue Apr 2 18:25:51 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * lcm.c: New file.
- * Makefile (SRCS): Add lcm.c.
-
-Thu Mar 28 19:06:12 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * portinfo.c, xportinfo.c, portinfo.h: New files.
- * portxlate.c, portxlate.h: New files.
- * Makefile (LCLHDRS): Add portinfo.h, portxlate.h.
- (SRCS): Add portinfo.c, xportinfo.c, portxlate.c.
-
-Tue Mar 26 17:43:51 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * wire.c: Add a weak reference to _start, so we don't have to
- compile all users of this library.
-
-Mon Mar 25 18:38:23 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * timefmt.c (fmt_named_interval): Rationalize WIDTH.
-
-Mon Mar 25 16:11:49 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wire.h, wire.c: New files.
- * Makefile (SRCS): Add wire.c.
- (LCLHDRS): Add wire.h.
-
-Mon Mar 25 16:06:40 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * envz.c (envz_merge): NEW_LEN is a size, not a char.
-
-Mon Mar 18 14:09:18 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (struct argp_state): Add HOOK and CHILD_HOOKS fields.
- Rename the PARENTS field to be CHILDREN (the most common use is
- initialization, so this change shouldn't have much effect).
- (ARGP_KEY_BEGIN, ARGP_KEY_ERROR): New macros.
- * argp-parse.c (struct group): Add PARENT, PARENT_INDEX, HOOK, and
- CHILD_HOOKS fields.
- (argp_parse): Add HOOK argument.
- Implement passing hook values to parsers, and propagating them
- between parents and children.
- * argp-help.c (argp_doc, argp_args_usage, argp_hol): Rename
- PARENTS field to CHILDREN.
-
- * argp-help.c (argp_error): Take an argp_state instead of an argp,
- and only doing anything if ARGP_NO_ERRS isn't set in it.
- (argp_state_help): New function.
- (argp_help): Don't interpret exiting options anymore.
- * argp-parse.c (argp_default_options): Add --usage option.
- (argp_default_parser): Use argp_state_help, so we don't need to
- screw with exit options anymore.
- Add usage option.
- (argp_parse): When printing `too many arguments', test
- ARGP_NO_ERRS instead of ARGP_NO_HELP.
- * argp.h (argp_state_help): New function.
- (argp_usage, argp_error): Change arguments.
-
-Fri Mar 1 18:59:40 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (hol_entry_help): Don't print extraneous blank lines.
-
-Wed Feb 28 18:44:38 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Print an error message if appropiate
- when we know there are too many arguments.
-
- * argp-help.c (hol_entry_help): Handle null group headers nicely.
-
-Wed Feb 28 16:09:27 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * maptime.c (maptime_map): mapped_time_value arg is volatile data.
- * maptime.h (maptime_map): Likewise.
-
-Sat Feb 17 21:34:18 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * shared-dom.c, localhost.c: New file.
- * Makefile (SRCS): Add shared-dom.c and localhost.c.
-
-Fri Feb 16 15:54:22 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * maptime.c, maptime.h: New files.
- * Makefile (SRCS, LCLHDRS): Add maptime.c and maptime.h respectively.
-
- * timefmt.c (fmt_named_interval): Correct backwards comparison.
-
-Thu Feb 15 15:18:34 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * canon-host.c: New file.
- * Makefile (SRCS): Add canon-host.c.
-
- * argp-parse.c (argp_parse): Correctly deal with errors from
- getopt, and allow the user to use '?' as a short option.
- (KEY_ERR): New macro.
- (argp_default_options, argp_default_parser): Use -? as the short
- option for --help.
-
-Wed Feb 14 14:33:48 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Make things a bit more readable by
- using the TRY_GETOPT variable in place of opt == EOF.
- Use KEY_END, KEY_ARG, and QUOTE.
- Clear STATE.quoted if STATE.next has been moved back before it.
- (KEY_END): New macro, in place of EOF.
- (KEY_ARG, QUOTE): New macros.
-
-Mon Feb 12 15:08:33 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Don't parse args in order by
- default. Honor ARGP_NO_ARGS.
- Deal correctly when the user turns a non-option arg into an option
- in re-ordering mode.
- * argp.h (struct argp_state): Add `quoted' field.
-
-Thu Feb 8 19:35:49 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): When a non-option arg fails to be
- parsed with EINVAL, set ARG_EINVAL true, and leave ERR as is until
- just before we return.
- Put process_arg() in the right scope.
-
-Wed Feb 7 23:08:33 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Deal with getopt returning EOF early
- because of `--'.
-
- * argp-parse.c (argp_parse): Make STATE.arg_num per-group.
- (struct group): Renamed process_arg field to args_processed (a count).
-
-Mon Feb 5 13:39:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (struct argp_state): Add ARG_NUM field.
- * argp-parse.c (argp_parse): Implement the ARG_NUM field.
-
- * argp.h (struct argp, struct argp_state, argp_parse, argp_help,
- argp_usage, argp_error, _option_is_short, _option_is_end): Add `const'
- where appropriate.
- * argp-parse.c (argp_default_options, argp_default_argp,
- argp_parse, find_long_option): Likewise.
- * argp-help.c (struct hol_entry, make_hol,
- hol_entry_short_iterate, hol_entry_long_iterate,
- hol_entry_first_short, hol_entry_first_long, hol_find_entry,
- hol_sort, hol_entry_help, argp_hol, argp_args_usage, argp_doc,
- argp_help, argp_error): Likewise.
- * line.h (line_write, line_fill, line_puts): Likewise.
- * line.c (line_write, line_fill): Likewise.
-
-Sat Feb 3 02:00:06 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * idvec.c (idvec_merge_ids): Correctly add all IDS, even if some
- duplicates are avoided.
-
-Tue Jan 23 15:02:03 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (hol_entry_help): Correctly print group headers, and
- precede them with a blank line.
- (hol_set_group): Renamed from hol_set_sort_class.
- (argp_help): Use hol_set_group instead of hol_set_sort_class.
- (struct hol_entry, make_hol, hol_sort, hol_set_group): Rename the
- `set_class' field to be `group'.
- (hol_help, hol_entry_help): After a group header has been printed,
- separate subsequent groups with a blank line.
-
-Mon Jan 15 11:01:15 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * path-lookup.c (hurd_file_name_path_lookup, file_name_path_lookup):
- Add PREFIXED_NAME (return) argument.
- (file_name_path_scan): New function.
- (hurd_file_name_path_lookup): Use file_name_path_scan().
-
-Tue Jan 2 01:24:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_default_options, argp_default_parser): Add
- --program-name (hidden) option.
- (OPT_PROGNAME): New macro.
-
- * idvec.c (idvec_merge_ids): Preserve duplicates internal to IDS.
- (idvec_ensure): Alloc NUM ids, not NUM chars!
- (idvec_remove): Correctly copy ids when deleting.
- * idvec.h (idvec_merge, idvec_delete): New declarations.
-
- * idvec-auth.c (idvec_merge_auth): Fix various small typos.
-
- * argz.c (argz_delete): If the result is empty, free it.
-
- * exec-reauth.c (exec_reauth): Doc fix.
-
- * argz.h (argz_delete): Renamed from argz_remove.
- * argz.c (argz_delete): Ditto.
- (argz_insert): Deref ARGZ where necessary.
- * envz.c (envz_merge): Rename argz_remove to argz_delete.
-
-Mon Jan 1 17:48:34 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * idvec.c (idvec_remove, idvec_insert_only): New functions.
- (idvec_setid): Use idvec_insert_only() instead of idvec_insert_new().
- * idvec.h (idvec_remove, idvec_insert_only): New declarations.
-
- * Makefile (SRCS): Add exec-reauth.c.
-
- * idvec.c (idvec_free_wrapper, idvec_free, idvec_ensure,
- idvec_grow, idvec_tail_contains, idvec_add_new, idvec_insert_new,
- idvec_merge_ids, idvec_setid): New functions.
- (idvec_insert): Rewritten to use idvec_grow().
- * idvec-auth.c (idvec_merge_auth): New function.
- * idvec.h (idvec_free_wrapper, idvec_free, idvec_ensure,
- idvec_grow, idvec_tail_contains, idvec_add_new, idvec_insert_new,
- idvec_merge_ids, idvec_setid, idvec_merge_auth): New declarations.
- * Makefile (SRCS): Added idvec-auth.c.
-
-Fri Dec 29 12:15:00 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (_argp_unlock_xxx): New function.
-
-Thu Dec 21 10:18:04 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * idvec.h (struct idvec): Renamed from struct ivec. `ints' field
- renamed to `ids'.
- (make_idvec, idvec_insert, idvec_add, idvec_contains):
- All renamed from the corresponding `ivec' declaration, and types,
- variable names, etc, changed accordingly.
- * idvec.c (make_idvec, idvec_insert, idvec_add, idvec_contains):
- All renamed from the corresponding `ivec' routine, and types,
- variable names, etc, changed accordingly.
- * Makefile (SRCS): Remove options.c. Rename ivec.c to idvec.c.
- (LCLHDRS): Remove options.h. Rename ivec.h to idvec.h.
-
-Wed Dec 20 13:05:00 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argz.c (argz_insert): Instead of an integer position N, take a
- pointer BEFORE into ARGZ to insert before.
- * argz.h (argz_insert): Instead of an integer position N, take a
- pointer BEFORE into ARGZ to insert before.
- (argz_next): New inline function.
-
-Tue Dec 19 13:52:52 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (struct argp_option): Add the GROUP field. Twiddle doc.
- (_option_is_end): Be more pessimistic about what constitutes `the end'.
- * argp-help.c (make_hol): Use the new GROUP field in struct
- argp_option to initialize sort_classes.
- (HEADER_COL): New macro.
- (hol_entry_help): Deal with group headers.
- * argp-parse.c (argp_default_options): Put --help in group -1.
-
-Sun Dec 17 00:18:58 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * ivec.c: New file.
- * ivec.h: New file.
- * Makefile (LCLHDRS): Add ivec.h.
- (SRCS): Add ivec.c.
-
-Sat Dec 16 17:42:27 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * termsize.c (deduce_term_size): New function, new file.
- * Makefile (SRCS): Add termsize.c.
-
- * argz.c (argz_insert): New function.
- (argz_remove, argz_append, argz_add): New functions, were in envz.c.
- * argz.h (argz_insert): New declaration.
-
-Thu Dec 14 18:04:48 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argz.h (argz_append, argz_add, argz_remove): New functions.
-
-Wed Dec 13 14:28:12 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * envz.c: New file.
- * envz.h: New file.
- * Makefile (SRCS): Add envz.c.
- (LCLHDRS): Add envz.h
-
-Wed Dec 6 15:05:43 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (struct argp_state): Rename the INDEX field to be NEXT.
- * argp-parse.c (argp_parse): Change uses of that field.
-
- * argz.c (argz_stringify): Add the SEP argument.
- * argz.h (argz_stringify): Ditto.
-
-Tue Dec 5 18:38:40 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * Makefile (SRCS, LCLHDRS): Removed error.c and error.h.
- (CPPFLAGS-error.c): Variable removed.
- * error.c, error.h: Files removed.
-
-Thu Oct 19 18:39:59 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (argp_usage, argp_error): New declarations.
- (argp_usage): New inline function.
- * argp-help.c (argp_error): New function.
-
-Fri Oct 13 19:28:28 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h (ARGP_HELP_STD_ERR): Doesn't print a usage message.
- (ARGP_HELP_STD_USAGE): ... whereas this does.
-
-Thu Oct 12 15:57:18 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-parse.c (argp_parse): Correctly mark short options as optional.
- (argp_parse): If an option alias doesn't have a key, use the real key.
-
-Wed Oct 11 13:54:18 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp-help.c (hol_find_entry): Don't increment ENTRY prematurely.
-
- * argp-parse.c (argp_parse): Update STATE.argp when adding a
- wrapper to implement the --help option.
- In general, use the version of variables that are in STATE.
- Update STATE.index in the case where getopt returns EOF.
- (argp_parse): Correctly translate options.
-
- * line.c (line_write): New function.
- (line_puts): Function deleted.
- (line_fill): Use line_write instead of line_printf.
- * line.h (line_write): New declaration.
- (line_puts): Rewrite in terms of line_write.
-
- * argp-help.c (hol_entry_help): Print the right documentation
- string for each entry.
-
- * argp-parse.c (argp_default_parser, argp_parse): Rename uses of
- argp_usage* to argp_help*.
-
- * argp-help.c (argp_help): Renamed from argp_usage.
- * argp.h (ARGP_HELP_*, argp_help): Renamed from ARGP_USAGE_* &c.
-
- * argp.h (ARGP_USAGE_STD_HELP): Use ARGP_USAGE_SHORT_USAGE instead
- of ARGP_USAGE_USAGE.
-
- * argp-help.c (make_hol): Deal with a null value of OPT. If there
- are no entries, don't define the ENTRIES or SHORT_OPTIONS fields.
- (hol_free): Don't free ENTRIES or SHORT_OPTIONS unless there are any.
- (hol_sort): Don't sort unless there are some entries.
- (hol_usage): Don't do anything unless there are some entries.
- (hol_sort): Sort int he correct order.
- (argp_usage): Add the ARGP_USAGE_SHORT_USAGE case.
-
- * argp-parse.c (argp_parse): Deal with null parser or option fields.
- If an argp has neither a parser or any options, don't put it in GROUPS.
- Use comparison with EGROUP, rather than testing the parser field,
- the end test for iteration over GROUPS.
-
- * argp-help.c (hol_append): Implement.
-
- * argp-parse.c (argp_parse): Pass in the right value for GROUPS to
- convert_options.
-
- * Makefile (SRCS): Add argp-parse.c, argp-help.c, and line.c
- (LCLHDRS): Add line.h and argp.h.
-
-Tue Oct 10 17:58:14 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * argp.h: Doc fixes.
-
- * argp.h: (ARGP_KEY_NO_ARGS): New macro.
- * argp-parse.c (argp_parse): Add support for ARGP_KEY_NO_ARGS.
- Put all the group attributes into structures which get stored in
- the GROUPS array, rather than having a separate array for each.
-
-Sat Oct 7 03:32:51 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * rwlock.h: Protect against multiple inclusion.
- Include cthreads.h and assert.h.
-
-Wed Sep 27 17:37:08 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * options.c (options_parse): Use 0 as the tag for non-option args.
- * options.h: Ditto.
-
-Sat Sep 23 14:15:01 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * rwlock.h (RWLOCK_INITIALIZER): New macro.
-
-Sat Sep 16 13:40:22 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * Makefile (lndist, $(srcdir)/hurd-snap/$(dir)/error.[ch]):
- Targets removed.
-
-Thu Aug 24 11:49:13 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
-
- * options.c: Include "options.h" instead of <options.h>.
diff --git a/libshouldbeinlibc/Makefile b/libshouldbeinlibc/Makefile
index 1a00dac1..0787d2d6 100644
--- a/libshouldbeinlibc/Makefile
+++ b/libshouldbeinlibc/Makefile
@@ -1,6 +1,6 @@
# Makefile for libshouldbeinlibc
#
-# Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+# Copyright (C) 1995,96,97,98,99,2002 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
@@ -20,13 +20,17 @@ dir := libshouldbeinlibc
makemode := library
libname = libshouldbeinlibc
-SRCS = argp-parse.c argp-help.c argp-pv.c argp-pvh.c \
- termsize.c idvec.c idvec-auth.c timefmt.c exec-reauth.c \
- canon-host.c maptime.c shared-dom.c localhost.c wire.c portinfo.c \
- xportinfo.c portxlate.c lcm.c cacheq.c fsysops.c
-LCLHDRS = argp.h idvec.h timefmt.h maptime.h \
- wire.h portinfo.h portxlate.h cacheq.h
-installhdrs = $(LCLHDRS)
+SRCS = termsize.c timefmt.c exec-reauth.c maptime-funcs.c \
+ canon-host.c maptime.c shared-dom.c localhost.c wire.c portinfo.c \
+ xportinfo.c portxlate.c lcm.c cacheq.c fsysops.c \
+ idvec.c idvec-auth.c idvec-funcs.c \
+ idvec-impgids.c idvec-verify.c idvec-rep.c \
+ ugids.c ugids-argp.c ugids-rep.c ugids-verify.c ugids-subtract.c \
+ ugids-auth.c ugids-xinl.c ugids-merge.c ugids-imply.c ugids-posix.c \
+ ugids-verify-auth.c
+installhdrs = idvec.h timefmt.h maptime.h \
+ wire.h portinfo.h portxlate.h cacheq.h ugids.h
+LCLHDRS = $(installhdrs)
installhdrsubdir = .
OBJS = $(SRCS:.c=.o)
diff --git a/libshouldbeinlibc/argp-help.c b/libshouldbeinlibc/argp-help.c
deleted file mode 100644
index b8b519e2..00000000
--- a/libshouldbeinlibc/argp-help.c
+++ /dev/null
@@ -1,908 +0,0 @@
-/* Hierarchial argument parsing help output
-
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <malloc.h>
-#include <ctype.h>
-#include <linewrap.h>
-
-#include "argp.h"
-
-#define SHORT_OPT_COL 2 /* column in which short options start */
-#define LONG_OPT_COL 6 /* column in which long options start */
-#define OPT_DOC_COL 29 /* column in which option text starts */
-#define HEADER_COL 1 /* column in which group headers are printed */
-#define USAGE_INDENT 12 /* indentation of wrapped usage lines */
-#define RMARGIN 79 /* right margin used for wrapping */
-
-/* Returns true if OPT hasn't been marked invisible. Visibility only affects
- whether OPT is displayed or used in sorting, not option shadowing. */
-#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
-
-/* Returns true if OPT is an alias for an earlier option. */
-#define oalias(opt) ((opt)->flags & OPTION_ALIAS)
-
-/* Returns true if OPT is the end-of-list marker for a list of options. */
-#define oend(opt) _option_is_end (opt)
-
-/* Returns true if OPT has a short option. */
-#define oshort(opt) _option_is_short (opt)
-
-/*
- The help format for a particular option is like:
-
- -xARG, -yARG, --long1=ARG, --long2=ARG Documentation...
-
- Where ARG will be omitted if there's no argument, for this option, or
- will be surrounded by "[" and "]" appropiately if the argument is
- optional. The documentation string is word-wrapped appropiately, and if
- the list of options is long enough, it will be started on a separate line.
- If there are no short options for a given option, the first long option is
- indented slighly in a way that's supposed to make most long options appear
- to be in a separate column.
-
- For example (from ps):
-
- -p PID, --pid=PID List the process PID
- --pgrp=PGRP List processes in the process group PGRP
- -P, -x, --no-parent Include processes without parents
- -Q, --all-fields Don't elide unusable fields (normally if there's
- some reason ps can't print a field for any
- process, it's removed from the output entirely)
- -r, --reverse, --gratuitously-long-reverse-option
- Reverse the order of any sort
- --session[=SID] Add the processes from the session SID (which
- defaults to the sid of the current process)
-
- The struct argp_option array for the above could look like:
-
- {
- {"pid", 'p', "PID", 0,
- "List the process PID"},
- {"pgrp", OPT_PGRP, "PGRP", 0,
- "List processes in the process group PGRP"},
- {"no-parent", 'P', 0, 0,
- "Include processes without parents"},
- {0, 'x', 0, OPTION_ALIAS},
- {"all-fields",'Q', 0, 0,
- "Don't elide unusable fields (normally if there's some reason ps \
-can't print a field for any process, it's removed from the output entirely)"},
- {"reverse", 'r', 0, 0,
- "Reverse the order of any sort"},
- {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS},
- {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL,
- "Add the processes from the session SID (which defaults to the sid of \
-the current process)"},
- }
-
-*/
-
-/* Returns true if CH occurs between BEG and END. */
-static int
-find_char (char ch, char *beg, char *end)
-{
- while (beg < end)
- if (*beg == ch)
- return 1;
- else
- beg++;
- return 0;
-}
-
-struct hol_entry
-{
- /* First option. */
- const struct argp_option *opt;
- /* Number of options (including aliases). */
- unsigned num;
-
- /* A pointers into the HOL's short_options field, to the first short option
- letter for this entry. The order of the characters following this point
- corresponds to the order of options pointed to by OPT, and there are at
- most NUM. A short option recorded in a option following OPT is only
- valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's
- probably been shadowed by some other entry). */
- char *short_options;
-
- /* Entries are sorted by their group first, in the order:
- 1, 2, ..., n, 0, -m, ..., -2, -1
- and then alphabetically within each group. The default is 0. */
- int group;
-};
-
-/* A list of options for help. */
-struct hol
-{
- /* The number of entries in this hol. If this field is zero, the others
- are undefined. */
- unsigned num_entries;
- /* An array of hol_entry's. */
- struct hol_entry *entries;
- /* A string containing all short options in this HOL. Each entry contains
- pointers into this string, so the order can't be messed with blindly. */
- char *short_options;
-};
-
-/* Create a struct hol from an array of struct argp_option. */
-struct hol *make_hol (const struct argp_option *opt)
-{
- char *so;
- const struct argp_option *o;
- struct hol_entry *entry;
- unsigned num_short_options = 0;
- struct hol *hol = malloc (sizeof (struct hol));
-
- assert (hol);
-
- hol->num_entries = 0;
-
- if (opt)
- {
- int cur_group = 0;
-
- /* The first option must not be an alias. */
- assert (! oalias (opt));
-
- /* Calculate the space needed. */
- for (o = opt; ! oend (o); o++)
- {
- if (! oalias (o))
- hol->num_entries++;
- if (oshort (o))
- num_short_options++; /* This is an upper bound. */
- }
-
- hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
- hol->short_options = malloc (num_short_options + 1);
-
- assert (hol->entries && hol->short_options);
-
- /* Fill in the entries. */
- so = hol->short_options;
- for (o = opt, entry = hol->entries; ! oend (o); entry++)
- {
- entry->opt = o;
- entry->num = 0;
- entry->short_options = so;
- entry->group = cur_group = o->group ?: cur_group;
-
- do
- {
- entry->num++;
- if (oshort (o) && ! find_char (o->key, hol->short_options, so))
- /* O has a valid short option which hasn't already been used.*/
- *so++ = o->key;
- o++;
- }
- while (! oend (o) && oalias (o));
- }
- *so = '\0'; /* null terminated so we can find the length */
- }
-
- return hol;
-}
-
-/* Free HOL and any resources it uses. */
-static void
-hol_free (struct hol *hol)
-{
- if (hol->num_entries > 0)
- {
- free (hol->entries);
- free (hol->short_options);
- }
- free (hol);
-}
-
-static inline int
-hol_entry_short_iterate (const struct hol_entry *entry,
- int (*func)(const struct argp_option *opt,
- const struct argp_option *real))
-{
- unsigned nopts;
- int val = 0;
- const struct argp_option *opt, *real = entry->opt;
- char *so = entry->short_options;
-
- for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
- if (oshort (opt) && *so == opt->key)
- {
- if (!oalias (opt))
- real = opt;
- if (ovisible (opt))
- val = (*func)(opt, real);
- so++;
- }
-
- return val;
-}
-
-static inline int
-hol_entry_long_iterate (const struct hol_entry *entry,
- int (*func)(const struct argp_option *opt,
- const struct argp_option *real))
-{
- unsigned nopts;
- int val = 0;
- const struct argp_option *opt, *real = entry->opt;
-
- for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
- if (opt->name)
- {
- if (!oalias (opt))
- real = opt;
- if (ovisible (opt))
- val = (*func)(opt, real);
- }
-
- return val;
-}
-
-/* Returns the first valid short option in ENTRY, or 0 if there is none. */
-static char
-hol_entry_first_short (const struct hol_entry *entry)
-{
- inline int func1 (const struct argp_option *opt,
- const struct argp_option *real)
- {
- return opt->key;
- }
- return hol_entry_short_iterate (entry, func1);
-}
-
-/* Returns the first valid long option in ENTRY, or 0 if there is none. */
-static const char *
-hol_entry_first_long (const struct hol_entry *entry)
-{
- const struct argp_option *opt;
- unsigned num;
- for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
- if (opt->name && ovisible (opt))
- return opt->name;
- return 0;
-}
-
-/* Returns the entry in HOL with the long option name NAME, or 0 if there is
- none. */
-static struct hol_entry *hol_find_entry (struct hol *hol, char *name)
-{
- struct hol_entry *entry = hol->entries;
- unsigned num_entries = hol->num_entries;
-
- while (num_entries-- > 0)
- {
- const struct argp_option *opt = entry->opt;
- unsigned num_opts = entry->num;
-
- while (num_opts-- > 0)
- if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
- return entry;
- else
- opt++;
-
- entry++;
- }
-
- return 0;
-}
-
-/* If an entry with the long option NAME occurs in HOL, set it's special
- sort position to GROUP. */
-static void
-hol_set_group (struct hol *hol, char *name, int group)
-{
- struct hol_entry *entry = hol_find_entry (hol, name);
- if (entry)
- entry->group = group;
-}
-
-/* Sort HOL by group and alphabetically by option name (with short options
- taking precedence over long). Since the sorting is for display purposes
- only, the shadowing of options isn't effected. */
-static void
-hol_sort (struct hol *hol)
-{
- int entry_cmp (const void *entry1_v, const void *entry2_v)
- {
- const struct hol_entry *entry1 = entry1_v, *entry2 = entry2_v;
- int group1 = entry1->group, group2 = entry2->group;
-
- if (group1 == group2)
- /* Normal comparison. */
- {
- int short1 = hol_entry_first_short (entry1);
- int short2 = hol_entry_first_short (entry2);
- const char *long1 = hol_entry_first_long (entry1);
- const char *long2 = hol_entry_first_long (entry2);
-
- if (!short1 && !short2 && long1 && long2)
- /* Only long options. */
- return strcasecmp (long1, long2);
- else
- /* Compare short/short, long/short, short/long, using the first
- character of long options. Entries without *any* valid
- options (such as options with OPTION_HIDDEN set) will be put
- first, but as they're not displayed, it doesn't matter where
- they are. */
- {
- char first1 = short1 ?: long1 ? *long1 : 0;
- char first2 = short2 ?: long2 ? *long2 : 0;
- /* Compare ignoring case, except when the options are both the
- same letter, in which case lower-case always comes first. */
- return (tolower (first1) - tolower (first2)) ?: first2 - first1;
- }
- }
- else
- /* Order by group: 1, 2, ..., n, 0, -m, ..., -2, -1 */
- if ((group1 < 0 && group2 < 0) || (group1 > 0 && group2 > 0))
- return group1 - group2;
- else
- return group2 - group1;
- }
-
- if (hol->num_entries > 0)
- qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
- entry_cmp);
-}
-
-/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow
- any in MORE with the same name. */
-static void
-hol_append (struct hol *hol, struct hol *more)
-{
- if (more->num_entries == 0)
- hol_free (more);
- else if (hol->num_entries == 0)
- {
- hol->num_entries = more->num_entries;
- hol->entries = more->entries;
- hol->short_options = more->short_options;
- /* We've stolen everything MORE from more. Destroy the empty shell. */
- free (more);
- }
- else
- /* append the entries in MORE to those in HOL, taking care to only add
- non-shadowed SHORT_OPTIONS values. */
- {
- unsigned left;
- char *so, *more_so;
- struct hol_entry *e;
- unsigned num_entries = hol->num_entries + more->num_entries;
- struct hol_entry *entries =
- malloc (num_entries * sizeof (struct hol_entry));
- unsigned hol_so_len = strlen (hol->short_options);
- char *short_options =
- malloc (hol_so_len + strlen (more->short_options) + 1);
-
- bcopy (hol->entries, entries,
- hol->num_entries * sizeof (struct hol_entry));
- bcopy (more->entries, entries + hol->num_entries,
- more->num_entries * sizeof (struct hol_entry));
-
- bcopy (hol->short_options, short_options, hol_so_len);
-
- /* Fix up the short options pointers from HOL. */
- for (e = entries, left = hol->num_entries; left > 0; e++, left--)
- e->short_options += (short_options - hol->short_options);
-
- /* Now add the short options from MORE, fixing up its entries too. */
- so = short_options + hol_so_len;
- more_so = more->short_options;
- for (left = more->num_entries; left > 0; e++, left--)
- {
- int opts_left;
- const struct argp_option *opt;
-
- e->short_options = so;
-
- for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
- {
- int ch = *more_so;
- if (oshort (opt) && ch == opt->key)
- /* The next short option in MORE_SO, CH, is from OPT. */
- {
- if (! find_char (ch,
- short_options, short_options + hol_so_len))
- /* The short option CH isn't shadowed by HOL's options,
- so add it to the sum. */
- *so++ = ch;
- more_so++;
- }
- }
- }
-
- *so = '\0';
-
- free (hol->entries);
- free (hol->short_options);
-
- hol->entries = entries;
- hol->num_entries = num_entries;
- hol->short_options = short_options;
-
- hol_free (more);
- }
-}
-
-/* Inserts enough spaces to make sure STREAM is at column COL. */
-static void
-indent_to (FILE *stream, unsigned col)
-{
- int needed = col - line_wrap_point (stream);
- while (needed-- > 0)
- putc (' ', stream);
-}
-
-/* Print help for ENTRY to STREAM. *LAST_ENTRY should contain the last entry
- printed before this, or null if it's the first, and if ENTRY is in a
- different group, and *SEP_GROUPS is true, then a blank line will be
- printed before any output. *SEP_GROUPS is also set to true if a
- user-specified group header is printed. */
-static void
-hol_entry_help (struct hol_entry *entry, FILE *stream,
- struct hol_entry **prev_entry, int *sep_groups)
-{
- unsigned num;
- int first = 1; /* True if nothing's been printed so far. */
- const struct argp_option *real = entry->opt, *opt;
- char *so = entry->short_options;
- int old_lm = line_wrap_set_lmargin (stream, 0);
- int old_wm = line_wrap_set_wmargin (stream, 0);
-
- /* Inserts a comma if this isn't the first item on the line, and then makes
- sure we're at least to column COL. Also clears FIRST. */
- void comma (unsigned col)
- {
- if (first)
- {
- if (sep_groups && *sep_groups
- && prev_entry && *prev_entry
- && entry->group != (*prev_entry)->group)
- putc ('\n', stream);
- first = 0;
- }
- else
- fputs (", ", stream);
- indent_to (stream, col);
- }
-
- /* If the option REAL has an argument, we print it in using the printf
- format REQ_FMT or OPT_FMT depending on whether it's a required or
- optional argument. */
- void arg (char *req_fmt, char *opt_fmt)
- {
- if (real->arg)
- if (real->flags & OPTION_ARG_OPTIONAL)
- fprintf (stream, opt_fmt, real->arg);
- else
- fprintf (stream, req_fmt, real->arg);
- }
-
- /* First emit short options. */
- line_wrap_set_wmargin (stream, SHORT_OPT_COL); /* For truly bizarre cases. */
- for (opt = real, num = entry->num; num > 0; opt++, num--)
- if (oshort (opt) && opt->key == *so)
- /* OPT has a valid (non shadowed) short option. */
- {
- if (ovisible (opt))
- {
- comma (SHORT_OPT_COL);
- putc ('-', stream);
- putc (*so, stream);
- arg (" %s", "[%s]");
- }
- so++;
- }
-
- /* Now, long options. */
- line_wrap_set_wmargin (stream, LONG_OPT_COL);
- for (opt = real, num = entry->num; num > 0; opt++, num--)
- if (opt->name && ovisible (opt))
- {
- comma (LONG_OPT_COL);
- fprintf (stream, "--%s", opt->name);
- arg ("=%s", "[=%s]");
- }
-
- line_wrap_set_lmargin (stream, 0);
- if (first)
- /* Didn't print any switches, what's up? */
- if (!oshort (real) && !real->name && real->doc)
- /* This is a group header, print it nicely. */
- {
- if (*real->doc)
- {
- if (prev_entry && *prev_entry)
- putc ('\n', stream); /* Precede with a blank line. */
- indent_to (stream, HEADER_COL);
- line_wrap_set_lmargin (stream, HEADER_COL);
- line_wrap_set_wmargin (stream, HEADER_COL);
- fputs (real->doc, stream);
- }
- if (sep_groups)
- *sep_groups = 1; /* Separate subsequent groups. */
- }
- else
- /* Just a totally shadowed option or null header; print nothing. */
- goto cleanup; /* Just return, after cleaning up. */
- else if (real->doc)
- /* Now the option documentation. */
- {
- unsigned col = line_wrap_point (stream);
- const char *doc = real->doc;
-
- line_wrap_set_lmargin (stream, OPT_DOC_COL);
- line_wrap_set_wmargin (stream, OPT_DOC_COL);
-
- if (col > OPT_DOC_COL + 3)
- putc ('\n', stream);
- else if (col >= OPT_DOC_COL)
- fprintf (stream, " ");
- else
- indent_to (stream, OPT_DOC_COL);
-
- fputs (doc, stream);
- }
-
- line_wrap_set_lmargin (stream, 0); /* Don't follow the nl with spaces. */
- putc ('\n', stream);
-
- if (prev_entry)
- *prev_entry = entry;
-
-cleanup:
- line_wrap_set_lmargin (stream, old_lm);
- line_wrap_set_wmargin (stream, old_wm);
-}
-
-/* Output a long help message about the options in HOL to STREAM. */
-static void
-hol_help (struct hol *hol, FILE *stream)
-{
- unsigned num;
- struct hol_entry *entry;
- struct hol_entry *last_entry = 0;
- int sep_groups = 0; /* True if we should separate different
- sections with blank lines. */
- for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
- hol_entry_help (entry, stream, &last_entry, &sep_groups);
-}
-
-/* Print a short usage description for the arguments in HOL to STREAM. */
-static void
-hol_usage (struct hol *hol, FILE *stream)
-{
- if (hol->num_entries > 0)
- {
- unsigned nentries;
- struct hol_entry *entry;
- char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
- char *snao_end = short_no_arg_opts;
-
- /* First we put a list of short options without arguments. */
- for (entry = hol->entries, nentries = hol->num_entries
- ; nentries > 0
- ; entry++, nentries--)
- {
- inline int func2 (const struct argp_option *opt,
- const struct argp_option *real)
- {
- if (! (opt->arg || real->arg))
- *snao_end++ = opt->key;
- return 0;
- }
- hol_entry_short_iterate (entry, func2);
- }
- if (snao_end > short_no_arg_opts)
- {
- *snao_end++ = 0;
- fprintf (stream, " [-%s]", short_no_arg_opts);
- }
-
- /* Now a list of short options *with* arguments. */
- for (entry = hol->entries, nentries = hol->num_entries
- ; nentries > 0
- ; entry++, nentries--)
- {
- inline int func3 (const struct argp_option *opt,
- const struct argp_option *real)
- {
- if (opt->arg || real->arg)
- if ((opt->flags | real->flags) & OPTION_ARG_OPTIONAL)
- fprintf (stream, " [-%c[%s]]",
- opt->key, opt->arg ?: real->arg);
- else
- {
- const char *arg = opt->arg ?: real->arg;
- /* Manually do line wrapping so that it (probably) won't
- get wrapped at the embedded space. */
- if (line_wrap_point (stream) + 6 + strlen (arg)
- >= line_wrap_rmargin (stream))
- putc ('\n', stream);
- else
- putc (' ', stream);
- fprintf (stream, "[-%c %s]", opt->key, arg);
- }
- return 0;
- }
- hol_entry_short_iterate (entry, func3);
- }
-
- /* Finally, a list of long options (whew!). */
- for (entry = hol->entries, nentries = hol->num_entries
- ; nentries > 0
- ; entry++, nentries--)
- {
- int func4 (const struct argp_option *opt,
- const struct argp_option *real)
- {
- if (opt->arg || real->arg)
- if ((opt->flags | real->flags) & OPTION_ARG_OPTIONAL)
- fprintf (stream, " [--%s[=%s]]",
- opt->name, opt->arg ?: real->arg);
- else
- fprintf (stream, " [--%s=%s]",
- opt->name, opt->arg ?: real->arg);
- else
- fprintf (stream, " [--%s]", opt->name);
- return 0;
- }
- hol_entry_long_iterate (entry, func4);
- }
- }
-}
-
-/* Make a HOL containing all levels of options in ARGP. */
-static struct hol *
-argp_hol (const struct argp *argp)
-{
- const struct argp **children = argp->children;
- struct hol *hol = make_hol (argp->options);
- if (children)
- while (*children)
- hol_append (hol, argp_hol (*children++));
- return hol;
-}
-
-/* Print all the non-option args documented in ARGP to STREAM. Any output is
- preceded by a space. */
-static void
-argp_args_usage (const struct argp *argp, FILE *stream)
-{
- const struct argp **children = argp->children;
- const char *doc = argp->args_doc;
- if (doc)
- {
- /* Manually do line wrapping so that it (probably) won't get wrapped at
- any embedded spaces. */
- if (line_wrap_point (stream) + 1 + strlen (doc)
- >= line_wrap_rmargin (stream))
- putc ('\n', stream);
- else
- putc (' ', stream);
- fputs (doc, stream);
- }
- if (children)
- while (*children)
- argp_args_usage (*children++, stream);
-}
-
-/* Print the documentation for ARGP to STREAM. Each separate bit of
- documentation is preceded by a blank line. */
-static void
-argp_doc (const struct argp *argp, FILE *stream)
-{
- const struct argp **children = argp->children;
- const char *doc = argp->doc;
- if (doc)
- {
- putc ('\n', stream);
- fputs (doc, stream);
- if (line_wrap_point (stream) > line_wrap_lmargin (stream))
- putc ('\n', stream);
- }
- if (children)
- while (*children)
- argp_doc (*children++, stream);
-}
-
-/* Output a usage message for ARGP to STREAM. FLAGS are from the set
- ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */
-void argp_help (const struct argp *argp, FILE *stream,
- unsigned flags, char *name)
-{
- int first = 1;
- struct hol *hol = 0;
-
- if (! stream)
- return;
-
- stream = line_wrap_stream (stream, 0, RMARGIN, 0);
- assert (stream);
-
- if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
- {
- hol = argp_hol (argp);
-
- /* If present, these options always come last. */
- hol_set_group (hol, "help", -1);
- hol_set_group (hol, "version", -1);
-
- hol_sort (hol);
- }
-
- if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
- /* Print a short `Usage:' message. */
- {
- int old_lm;
- int old_wm = line_wrap_set_wmargin (stream, USAGE_INDENT);
-
- fprintf (stream, "Usage: %s", name);
-
- /* We set the lmargin as well as the wmargin, because hol_usage
- manually wraps options with newline to avoid annoying breaks. */
- old_lm = line_wrap_set_lmargin (stream, USAGE_INDENT);
-
- if (flags & ARGP_HELP_SHORT_USAGE)
- /* Just show where the options go. */
- {
- if (hol->num_entries > 0)
- fputs (" [OPTION...]", stream);
- }
- else
- /* Actually print the options. */
- hol_usage (hol, stream);
- argp_args_usage (argp, stream);
-
- line_wrap_set_wmargin (stream, old_wm);
- line_wrap_set_lmargin (stream, old_lm);
-
- putc ('\n', stream);
- first = 0;
- }
-
- if (flags & ARGP_HELP_SEE)
- {
- fprintf (stream, "Try `%s --help' for more information.\n", name);
- first = 0;
- }
-
- if (flags & ARGP_HELP_LONG)
- /* Print a long, detailed help message. */
- {
- /* Print info about all the options. */
- if (hol->num_entries > 0)
- {
- if (! first)
- putc ('\n', stream);
- hol_help (hol, stream);
- first = 0;
- }
-
- /* Finally, print any documentation strings at the end. */
- argp_doc (argp, stream);
- }
-
- if (hol)
- hol_free (hol);
-
- line_unwrap_stream (stream);
-}
-
-/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
- from the set ARGP_HELP_*. */
-void
-argp_state_help (struct argp_state *state, FILE *stream, unsigned flags)
-{
- if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
- {
- argp_help (state ? state->argp : 0, stream, flags,
- state ? state->name : program_invocation_name);
-
- if (!state || ! (state->flags & ARGP_NO_EXIT))
- {
- if (flags & ARGP_HELP_EXIT_ERR)
- exit (1);
- if (flags & ARGP_HELP_EXIT_OK)
- exit (0);
- }
- }
-}
-
-/* If appropriate, print the printf string FMT and following args, preceded
- by the program name and `:', to stderr, and followed by a `Try ... --help'
- message, then exit (1). */
-void
-argp_error (struct argp_state *state, const char *fmt, ...)
-{
- if (!state || !(state->flags & ARGP_NO_ERRS))
- {
- FILE *stream = state ? state->err_stream : stderr;
-
- if (stream)
- {
- va_list ap;
-
- fputs (program_invocation_name, stream);
- putc (':', stream);
- putc (' ', stream);
-
- va_start (ap, fmt);
- vfprintf (stream, fmt, ap);
- va_end (ap);
-
- putc ('\n', stream);
-
- argp_state_help (state, stream, ARGP_HELP_STD_ERR);
- }
- }
-}
-
-/* Similar to the standard gnu error-reporting function error(), but will
- respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
- to STATE->err_stream. This is useful for argument parsing code that is
- shared between program startup (when exiting is desired) and runtime
- option parsing (when typically an error code is returned instead). The
- difference between this function and argp_error is that the latter is for
- *parsing errors*, and the former is for other problems that occur during
- parsing but don't reflect a (syntactic) problem with the input. */
-void
-argp_failure (struct argp_state *state, int status, int errnum,
- const char *fmt, ...)
-{
- if (!state || !(state->flags & ARGP_NO_ERRS))
- {
- FILE *stream = state ? state->err_stream : stderr;
-
- if (stream)
- {
- fputs (state ? state->name : program_invocation_name, stream);
-
- if (fmt)
- {
- va_list ap;
-
- putc (':', stream);
- putc (' ', stream);
-
- va_start (ap, fmt);
- vfprintf (stream, fmt, ap);
- va_end (ap);
- }
-
- if (errnum)
- {
- putc (':', stream);
- putc (' ', stream);
- fputs (strerror (errnum), stream);
- }
-
- putc ('\n', stream);
-
- if (status)
- exit (status);
- }
- }
-}
diff --git a/libshouldbeinlibc/argp-parse.c b/libshouldbeinlibc/argp-parse.c
deleted file mode 100644
index 73b28f06..00000000
--- a/libshouldbeinlibc/argp-parse.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/* Hierarchial argument parsing, layered over getopt
-
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-#include <getopt.h>
-#include <cthreads.h>
-
-#include "argp.h"
-
-/* Getopt return values. */
-#define KEY_END (-1) /* The end of the options. */
-#define KEY_ARG 1 /* A non-option argument. */
-#define KEY_ERR '?' /* An error parsing the options. */
-
-/* The meta-argument used to prevent any further arguments being interpreted
- as options. */
-#define QUOTE "--"
-
-/* The number of bits we steal in a long-option value for our own use. */
-#define GROUP_BITS CHAR_BIT
-
-/* The number of bits available for the user value. */
-#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
-#define USER_MASK ((1 << USER_BITS) - 1)
-
-/* EZ alias for ARGP_ERR_UNKNOWN. */
-#define EBADKEY ARGP_ERR_UNKNOWN
-
-/* ---------------------------------------------------------------- */
-/* Default options. */
-
-/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
- for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
- you can force the program to continue by attaching a debugger and setting
- it to 0 yourself. */
-volatile int _argp_hang = 0;
-
-#define OPT_PROGNAME -2
-#define OPT_USAGE -3
-#define OPT_HANG -4
-
-static const struct argp_option argp_default_options[] =
-{
- {"help", '?', 0, 0, "Give this help list", -1},
- {"usage", OPT_USAGE, 0, 0, "Give a short usage message"},
- {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, "Set the program name"},
- {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
- "Hang for SECS seconds (default 3600)"},
- {0, 0}
-};
-
-static error_t
-argp_default_parser (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case '?':
- argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
- break;
- case OPT_USAGE:
- argp_state_help (state, state->out_stream,
- ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
- break;
-
- case OPT_PROGNAME: /* Set the program name. */
- program_invocation_name = arg;
- program_invocation_short_name = rindex (arg, '/');
- if (program_invocation_short_name)
- program_invocation_short_name++;
- else
- program_invocation_short_name = program_invocation_name;
-
- if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
- == ARGP_PARSE_ARGV0)
- state->argv[0] = arg; /* Update what getopt uses too. */
-
- break;
-
- case OPT_HANG:
- _argp_hang = atoi (arg ?: "3600");
- while (_argp_hang-- > 0)
- sleep (1);
- break;
-
- default:
- return EBADKEY;
- }
- return 0;
-}
-
-static const struct argp argp_default_argp =
- {argp_default_options, &argp_default_parser};
-
-
-static const struct argp_option argp_version_options[] =
-{
- {"version", 'V', 0, 0, "Print program version", -1},
- {0, 0}
-};
-
-static error_t
-argp_version_parser (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case 'V':
- if (argp_program_version_hook)
- (*argp_program_version_hook) (state->out_stream, state);
- else if (argp_program_version)
- fprintf (state->out_stream, "%s\n", argp_program_version);
- else
- argp_error (state, "No version known!?");
- if (! (state->flags & ARGP_NO_EXIT))
- exit (0);
- break;
- default:
- return EBADKEY;
- }
- return 0;
-}
-
-static const struct argp argp_version_argp =
- {argp_version_options, &argp_version_parser};
-
-/* ---------------------------------------------------------------- */
-
-/* Returns the offset into the getopt long options array LONG_OPTIONS of a
- long option with called NAME, or -1 if none is found. Passing NULL as
- NAME will return the number of options. */
-static int
-find_long_option (struct option *long_options, const char *name)
-{
- struct option *l = long_options;
- while (l->name != NULL)
- if (name != NULL && strcmp (l->name, name) == 0)
- return l - long_options;
- else
- l++;
- if (name == NULL)
- return l - long_options;
- else
- return -1;
-}
-
-/* ---------------------------------------------------------------- */
-
-/* Used to regulate access to the getopt routines, which are non-reentrant. */
-static struct mutex getopt_lock = MUTEX_INITIALIZER;
-
-/* This hack to allow programs that know what's going on to call argp
- recursively. If someday argp is changed not to use the non-reentrant
- getopt interface, we can get rid of this shit. XXX */
-void
-_argp_unlock_xxx ()
-{
- mutex_unlock (&getopt_lock);
-}
-
-/* The state of a `group' during parsing. Each group corresponds to a
- particular argp structure from the tree of such descending from the top
- level argp passed to argp_parse. */
-struct group
-{
- /* This group's parsing function. */
- argp_parser_t parser;
-
- /* Points to the point in SHORT_OPTS corresponding to the end of the short
- options for this group. We use it to determine from which group a
- particular short options is from. */
- char *short_end;
-
- /* The number of non-option args sucessfully handled by this parser. */
- unsigned args_processed;
-
- /* This group's parser's parent's group. */
- struct group *parent;
- unsigned parent_index; /* And the our position in the parent. */
-
- /* These fields are swapped into and out of the state structure when
- calling this group's parser. */
- void *input, **child_inputs;
- void *hook;
-};
-
-/* Parse the options strings in ARGC & ARGV according to the argp in
- ARGP. FLAGS is one of the ARGP_ flags above. If OPTIND is
- non-NULL, the index in ARGV of the first unparsed option is returned in
- it. If an unknown option is present, EINVAL is returned; if some parser
- routine returned a non-zero value, it is returned; otherwise 0 is
- returned. */
-error_t
-argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
- int *end_index, void *input)
-{
- error_t err = 0;
- /* True if we think using getopt is still useful; if false, then
- remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is
- cleared whenever getopt returns KEY_END, but may be set again if the user
- moves the next argument pointer backwards. */
- int try_getopt = 1;
- /* If true, then err == EBADKEY is a result of a non-option argument failing
- to be parsed (which in some cases isn't actually an error). */
- int arg_ebadkey = 0;
- /* SHORT_OPTS is the getopt short options string for the union of all the
- groups of options. */
- char *short_opts;
- /* LONG_OPTS is the array of getop long option structures for the union of
- all the groups of options. */
- struct option *long_opts;
- /* States of the various parsing groups. */
- struct group *groups;
- /* The end of the GROUPS array. */
- struct group *egroup;
- /* A pointer for people to use for iteration over GROUPS. */
- struct group *group;
- /* An vector containing storage for the CHILD_INPUTS field in all groups. */
- void **child_inputs;
- /* State block supplied to parsing routines. */
- struct argp_state state =
- { argp, argc, argv, 0, flags, err_stream: stderr, out_stream: stdout };
-
- /* Call GROUP's parser with KEY and ARG, swapping any group-specific info
- from STATE before calling, and back into state afterwards. If GROUP has
- no parser, EBADKEY is returned. */
- error_t group_parse (struct group *group, int key, char *arg)
- {
- if (group->parser)
- {
- error_t err;
- state.hook = group->hook;
- state.input = group->input;
- state.child_inputs = group->child_inputs;
- state.arg_num = group->args_processed;
- err = (*group->parser)(key, arg, &state);
- group->hook = state.hook;
- return err;
- }
- else
- return EBADKEY;
- }
-
- /* Parse the non-option argument ARG, at the current position. Returns
- any error, and sets ARG_EBADKEY to true if return EBADKEY. */
- error_t process_arg (char *val, int *arg_ebadkey)
- {
- int index = state.next;
- error_t err = EBADKEY;
-
- for (group = groups; group < egroup && err == EBADKEY; group++)
- err = group_parse (group, ARGP_KEY_ARG, val);
-
- if (!err)
- if (state.next >= index)
- /* Remember that we successfully processed a non-option
- argument -- but only if the user hasn't gotten tricky and set
- the clock back. */
- (--group)->args_processed++;
- else
- /* The user wants to reparse some args, give getopt another try. */
- try_getopt = 1;
-
- if (err == EBADKEY)
- *arg_ebadkey = 1;
-
- return err;
- }
-
- /* Parse the option OPT (with argument ARG), at the current position.
- Returns any error, and sets ARG_EBADKEY to true if it was actually an
- argument and the parser returned EBADKEY. */
- error_t process_opt (int opt, char *val, int *arg_ebadkey)
- {
- /* The group key encoded in the high bits; 0 for short opts or
- group_number + 1 for long opts. */
- int group_key = opt >> USER_BITS;
- error_t err = EBADKEY; /* until otherwise asserted */
-
- if (group_key == 0)
- /* A short option. */
- {
- /* By comparing OPT's position in SHORT_OPTS to the various
- starting positions in each group's SHORT_END field, we can
- determine which group OPT came from. */
- char *short_index = index (short_opts, opt);
- if (short_index)
- for (group = groups; group < egroup; group++)
- if (group->short_end > short_index)
- {
- err = group_parse (group, opt, optarg);
- break;
- }
- }
- else
- /* A long option. We use shifts instead of masking for extracting
- the user value in order to preserve the sign. */
- err =
- group_parse (&groups[group_key - 1],
- (opt << GROUP_BITS) >> GROUP_BITS, optarg);
-
- return err;
- }
-
- if (! (state.flags & ARGP_NO_HELP))
- /* Add our own options. */
- {
- const struct argp **plist = alloca (3 * sizeof (struct argp *));
- struct argp *top_argp = alloca (sizeof (struct argp));
-
- /* TOP_ARGP has no options, it just serves to group the user & default
- argps. */
- bzero (top_argp, sizeof (*top_argp));
- top_argp->children = plist;
-
- if (state.argp)
- *plist++ = state.argp;
- *plist++ = &argp_default_argp;
- if (argp_program_version || argp_program_version_hook)
- *plist++ = &argp_version_argp;
- *plist = 0;
-
- state.argp = top_argp;
- }
-
- /* Find the merged set of getopt options, with keys appropiately prefixed. */
- {
- char *short_end;
- unsigned short_len = (state.flags & ARGP_NO_ARGS) ? 0 : 1;
- struct option *long_end;
- unsigned long_len = 0;
- unsigned num_groups = 0;
- unsigned num_child_inputs = 0;
-
- /* For ARGP, increments NUM_GROUPS by the total number of argp structures
- descended from it, and SHORT_LEN & LONG_LEN by the maximum lengths of
- the resulting merged getopt short options string and long-options
- array, respectively. */
- void calc_lengths (const struct argp *argp)
- {
- const struct argp **children = argp->children;
- const struct argp_option *opt = argp->options;
-
- if (opt || argp->parser)
- {
- num_groups++;
- if (opt)
- {
- int num_opts = 0;
- while (!_option_is_end (opt++))
- num_opts++;
- short_len += num_opts * 3; /* opt + up to 2 `:'s */
- long_len += num_opts;
- }
- }
-
- if (children)
- while (*children)
- {
- calc_lengths (*children++);
- num_child_inputs++;
- }
- }
-
- /* Converts all options in ARGP (which is put in GROUP) and ancestors
- into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
- LONG_END are the points at which new options are added. Returns the
- next unused group entry. */
- struct group *convert_options (const struct argp *argp,
- struct group *parent, unsigned parent_index,
- struct group *group)
- {
- /* REAL is the most recent non-alias value of OPT. */
- const struct argp_option *real = argp->options;
- const struct argp **children = argp->children;
-
- if (real || argp->parser)
- {
- const struct argp_option *opt;
-
- if (real)
- for (opt = real; !_option_is_end (opt); opt++)
- {
- if (! (opt->flags & OPTION_ALIAS))
- /* OPT isn't an alias, so we can use values from it. */
- real = opt;
-
- if (_option_is_short (opt))
- /* OPT can be used as a short option. */
- {
- *short_end++ = opt->key;
- if (real->arg)
- {
- *short_end++ = ':';
- if (real->flags & OPTION_ARG_OPTIONAL)
- *short_end++ = ':';
- }
- *short_end = '\0'; /* keep 0 terminated */
- }
-
- if (opt->name && find_long_option (long_opts, opt->name) < 0)
- /* OPT can be used as a long option. */
- {
- long_end->name = opt->name;
- long_end->has_arg =
- (real->arg
- ? (real->flags & OPTION_ARG_OPTIONAL
- ? optional_argument
- : required_argument)
- : no_argument);
- long_end->flag = 0;
- /* we add a disambiguating code to all the user's
- values (which is removed before we actually call
- the function to parse the value); this means that
- the user loses use of the high 8 bits in all his
- values (the sign of the lower bits is preserved
- however)... */
- long_end->val =
- ((opt->key | real->key) & USER_MASK)
- + (((group - groups) + 1) << USER_BITS);
-
- /* Keep the LONG_OPTS list terminated. */
- (++long_end)->name = NULL;
- }
- }
-
- group->parser = argp->parser;
- group->short_end = short_end;
- group->args_processed = 0;
- group->parent = parent;
- group->parent_index = parent_index;
- group->input = 0;
- group->hook = 0;
- group->child_inputs = 0;
-
- if (children)
- /* Assign GROUP's CHILD_INPUTS field a slice from CHILD_INPUTS.*/
- {
- unsigned num_children = 0;
- while (children[num_children])
- num_children++;
- group->child_inputs = child_inputs;
- child_inputs += num_children;
- }
-
- parent = group++;
- }
- else
- parent = 0;
-
- if (children)
- {
- unsigned index = 0;
- while (*children)
- group = convert_options (*children++, parent, index++, group);
- }
-
- return group;
- }
-
- if (state.argp)
- calc_lengths (state.argp);
-
- short_opts = short_end = alloca (short_len + 1);
- if (state.flags & ARGP_IN_ORDER)
- *short_end++ = '-';
- else if (state.flags & ARGP_NO_ARGS)
- *short_end++ = '+';
- *short_end = '\0';
-
- long_opts = long_end = alloca ((long_len + 1) * sizeof (struct option));
- long_end->name = NULL;
-
- groups = alloca ((num_groups + 1) * sizeof (struct group));
-
- child_inputs = alloca (num_child_inputs * sizeof (void *));
- bzero (child_inputs, num_child_inputs * sizeof (void *));
-
- if (state.argp)
- egroup = convert_options (state.argp, 0, 0, groups);
- else
- egroup = groups; /* No parsers at all! */
- }
-
- /* Call each parser for the first time, giving it a chance to propagate
- values to child parsers. */
- if (groups < egroup)
- groups->input = input;
- for (group = groups ; group < egroup && (!err || err == EBADKEY); group++)
- {
- if (group->parent)
- /* If a child parser, get the initial input value from the parent. */
- group->input = group->parent->child_inputs[group->parent_index];
- err = group_parse (group, ARGP_KEY_INIT, 0);
- }
- if (err == EBADKEY)
- err = 0; /* Some parser didn't understand. */
-
- /* Getopt is (currently) non-reentrant. */
- mutex_lock (&getopt_lock);
-
- /* Tell getopt to initialize. */
- state.next = 0;
-
- if (state.flags & ARGP_NO_ERRS)
- {
- opterr = 0;
- if (state.flags & ARGP_PARSE_ARGV0)
- /* getopt always skips ARGV[0], so we have to fake it out. As long
- as opterr is 0, then it shouldn't actually try to access it. */
- state.argv--, state.argc++;
- }
- else
- opterr = 1; /* Print error messages. */
-
- if (state.argv == argv && argv[0])
- /* There's an argv[0]; use it for messages. */
- state.name = argv[0];
- else
- state.name = program_invocation_name;
-
- /* Now use getopt on our coalesced options lists. */
- while (! err)
- {
- int opt;
-
- if (state.quoted && state.next < state.quoted)
- /* The next argument pointer has been moved to before the quoted
- region, so pretend we never saw the quoting `--', and give getopt
- another chance. If the user hasn't removed it, getopt will just
- process it again. */
- state.quoted = 0;
-
- if (try_getopt && !state.quoted)
- /* Give getopt a chance to parse this. */
- {
- optind = state.next; /* Put it back in OPTIND for getopt. */
- optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */
- opt = getopt_long (state.argc, state.argv, short_opts, long_opts, 0);
- state.next = optind; /* And see what getopt did. */
-
- if (opt == KEY_END)
- /* Getopt says there are no more options, so stop using
- getopt; we'll continue if necessary on our own. */
- {
- try_getopt = 0;
- if (state.next > 1
- && strcmp (state.argv[state.next - 1], QUOTE) == 0)
- /* Not only is this the end of the options, but it's a
- `quoted' region, which may have args that *look* like
- options, so we definitely shouldn't try to use getopt past
- here, whatever happens. */
- state.quoted = state.next;
- }
- else if (opt == KEY_ERR && optopt != KEY_END)
- /* KEY_ERR can have the same value as a valid user short
- option, but in the case of a real error, getopt sets OPTOPT
- to the offending character, which can never be KEY_END. */
- {
- err = EBADKEY;
- break;
- }
- }
- else
- opt = KEY_END;
-
- if (opt == KEY_END)
- /* We're past what getopt considers the options. */
- if (state.next >= state.argc || (state.flags & ARGP_NO_ARGS))
- break; /* done */
- else
- /* A non-option arg. */
- err = process_arg (state.argv[state.next++], &arg_ebadkey);
- else if (opt == KEY_ARG)
- /* A non-option argument; try each parser in turn. */
- err = process_arg (optarg, &arg_ebadkey);
- else
- err = process_opt (opt, optarg, &arg_ebadkey);
- }
-
- mutex_unlock (&getopt_lock);
-
- if (err == EBADKEY && arg_ebadkey)
- /* Suppress errors generated by unparsed arguments. */
- err = 0;
-
- if (!err)
- if (state.next == state.argc)
- /* We successfully parsed all arguments! Call all the parsers again,
- just a few more times... */
- {
- for (group = groups; group < egroup && (!err || err==EBADKEY); group++)
- if (group->args_processed == 0)
- err = group_parse (group, ARGP_KEY_NO_ARGS, 0);
- for (group = groups; group < egroup && (!err || err==EBADKEY); group++)
- err = group_parse (group, ARGP_KEY_END, 0);
- if (err == EBADKEY)
- err = 0; /* Some parser didn't understand. */
- }
- else if (end_index)
- /* Return any remaining arguments to the user. */
- *end_index = state.next;
- else
- /* No way to return the remaining arguments, they must be bogus. */
- {
- if (!(state.flags & ARGP_NO_ERRS) && state.err_stream)
- fprintf (state.err_stream, "%s: Too many arguments\n", state.name);
- err = EBADKEY;
- }
-
- /* Okay, we're all done, with either an error or success. We only call the
- parsers once more, to indicate which one. */
-
- if (err)
- {
- /* Maybe print an error message. */
- if (err == EBADKEY)
- argp_state_help (&state, state.err_stream, ARGP_HELP_STD_ERR);
-
- /* Since we didn't exit, give each parser an error indication. */
- for (group = groups; group < egroup; group++)
- group_parse (group, ARGP_KEY_ERROR, 0);
- }
- else
- /* Do final cleanup, including propagating back values from parsers. */
- {
- /* We pass over the groups in reverse order so that child groups are
- given a chance to do there processing before passing back a value to
- the parent. */
- for (group = egroup - 1
- ; group >= groups && (!err || err == EBADKEY)
- ; group--)
- err = group_parse (group, ARGP_KEY_SUCCESS, 0);
- if (err == EBADKEY)
- err = 0; /* Some parser didn't understand. */
- }
-
- if (err == EBADKEY)
- err = EINVAL;
-
- return err;
-}
diff --git a/libshouldbeinlibc/argp-pvh.c b/libshouldbeinlibc/argp-pvh.c
deleted file mode 100644
index a58c1923..00000000
--- a/libshouldbeinlibc/argp-pvh.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Default definition for ARGP_PROGRAM_VERSION_HOOK
-
- Copyright (C) 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "argp.h"
-
-/* If set by the user program to a non-zero value, then a default option
- --version is added (unless the ARGP_NO_HELP flag is used), which calls
- this function with a stream to print the version to and a pointer to the
- current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
- used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
-void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = 0;
diff --git a/libshouldbeinlibc/argp.h b/libshouldbeinlibc/argp.h
deleted file mode 100644
index 9c59c407..00000000
--- a/libshouldbeinlibc/argp.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/* Hierarchial argument parsing, layered over getopt
-
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef __ARGP_H__
-#define __ARGP_H__
-
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <getopt.h>
-
-/* A description of a particular option. A pointer to an array of
- these is passed in the OPTIONS field of an argp structure. Each option
- entry can correspond to one long option and/or one short option; more
- names for the same option can be added by following an entry in an option
- array with options having the OPTION_ALIAS flag set. */
-struct argp_option
-{
- /* The long option name. For more than one name for the same option, you
- can use following options with the OPTION_ALIAS flag set. */
- const char *name;
-
- /* What key is returned for this option. If > 0 and printable, then it's
- also accepted as a short option. */
- int key;
-
- /* If non-NULL, this is the name of the argument associated with this
- option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
- const char *arg;
-
- /* OPTION_ flags. */
- int flags;
-
- /* The doc string for this option. If both NAME and KEY are 0, This string
- will be printed outdented from the normal option column, making it
- useful as a group header (it will be the first thing printed in its
- group); in this usage, it's conventional to end the string with a `:'. */
- const char *doc;
-
- /* The group this option is in. In a long help message, options are sorted
- alphabetically within each group, and the groups presented in the order
- 1, 2, ..., n, 0, -m, ..., -2, -1. Every entry in an options array with
- if this field 0 will inherit the group number of the previous entry, or
- zero if it's the first one. Automagic options such as --help are put
- into group -1. */
- int group;
-};
-
-/* The argument associated with this option is optional. */
-#define OPTION_ARG_OPTIONAL 0x1
-/* This option isn't displayed in any help messages. */
-#define OPTION_HIDDEN 0x2
-/* This option is an alias for the closest previous non-alias option. This
- means that it will be displayed in the same help entry, and will inherit
- fields other than NAME and KEY from the aliased option. */
-#define OPTION_ALIAS 0x4
-
-struct argp; /* fwd declare this type */
-struct argp_state; /* " */
-
-/* The type of a pointer to an argp parsing function. */
-typedef error_t (*argp_parser_t)(int key, char *arg, struct argp_state *state);
-
-/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such
- returns will simply be ignored. For user keys, this error will be turned
- into EINVAL (if the call to argp_parse is such that errors are propagated
- back to the user instead of exiting); returning EINVAL itself would result
- in an immediate stop to parsing in *all* cases. */
-#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */
-
-/* Special values for the KEY argument to an argument parsing function.
- ARGP_ERR_UNKNOWN should be returned if they aren't understood.
-
- The sequence of keys to parser calls is either (where opt is a user key):
- ARGP_KEY_INIT (opt | ARGP_KEY_ARG)... ARGP_KEY_END
- or ARGP_KEY_INIT opt... ARGP_KEY_NO_ARGS ARGP_KEY_END
-
- If an error occurs, then the parser is called with ARGP_KEY_ERR, and no
- other calls are made. */
-
-/* This is not an option at all, but rather a command line argument. If a
- parser receiving this key returns success, the fact is recorded, and the
- ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the
- argument, a parser function decrements the NEXT field of the state it's
- passed, the option won't be considered processed; this is to allow you to
- actually modify the argument (perhaps into an option), and have it
- processed again. */
-#define ARGP_KEY_ARG 0
-/* There are no more command line arguments at all. */
-#define ARGP_KEY_END 1
-/* Because it's common to want to do some special processing if there aren't
- any non-option args, user parsers are called with this key if they didn't
- successfully process any non-option arguments. Called just before
- ARGP_KEY_END (where more general validity checks on previously parsed
- arguments can take place). */
-#define ARGP_KEY_NO_ARGS 2
-/* Passed in before any parsing is done. Afterwards, the values of each
- element of the CHILD_INPUT field, if any, in the state structure is
- copied to each child's state to be the initial value of the INPUT field. */
-#define ARGP_KEY_INIT 3
-/* Passed in when parsing has successfully been completed (even if there are
- still arguments remaining). */
-#define ARGP_KEY_SUCCESS 4
-/* Passed in if an error occurs (in which case a call with ARGP_KEY_SUCCESS is
- never made, so any cleanup must be done here). */
-#define ARGP_KEY_ERROR 5
-
-/* An argp structure contains a set of getopt options declarations, a
- function to deal with getting one, and an optional pointer to another
- argp structure. When actually parsing options, getopt is called with
- the union of all the argp structures chained together through their
- CHILD pointers, with conflicts being resolved in favor of the first
- occurance in the chain. */
-struct argp
-{
- /* An array of argp_option structures, terminated by an entry with both
- NAME and KEY having a value of 0. */
- const struct argp_option *options;
-
- /* What to do with an option from this structure. KEY is the key
- associated with the option, and ARG is any associated argument (NULL if
- none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be
- returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then
- parsing is stopped immediately, and that value is returned from
- argp_parse(). For special (non-user-supplied) values of KEY, see the
- ARGP_KEY_ definitions below. */
- argp_parser_t parser;
-
- /* A string describing what other arguments are wanted by this program. It
- is only used by argp_usage to print the `Usage:' message. */
- const char *args_doc;
-
- /* A string containing extra text to be printed after the options in a long
- help message, if it is non-NULL. */
- const char *doc;
-
- /* A NULL terminated list of other argp structures that should be parsed
- with this one. Any conflicts are resolved in favor of this argp, or
- early argps in the CHILDREN list. This field is useful if you use
- libraries that supply their own argp structure, which you want to use in
- conjunction with your own. */
- const struct argp **children;
-};
-
-/* Parsing state. This is provided to parsing functions called by argp,
- which may examine and, as noted, modify fields. */
-struct argp_state
-{
- /* The top level ARGP being parsed. */
- const struct argp *argp;
-
- /* The argument vector being parsed. May be modified. */
- int argc;
- char **argv;
-
- /* The index in ARGV of the next arg that to be parsed. May be modified. */
- int next;
-
- /* The flags supplied to argp_parse. May be modified. */
- unsigned flags;
-
- /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the
- number of the current arg, starting at zero, and incremented after each
- such call returns. At all other times, this is the number of such
- arguments that have been processed. */
- unsigned arg_num;
-
- /* If non-zero, the index in ARGV of the first argument following a special
- `--' argument (which prevents anything following being interpreted as an
- option). Only set once argument parsing has proceeded past this point. */
- int quoted;
-
- /* An arbitrary pointer passed in from the user. */
- void *input;
- /* Values to pass to child parsers. This vector will be the same length as
- the number of children for the current parser. */
- void **child_inputs;
-
- /* For the parser's use. Initialized to 0. */
- void *hook;
-
- /* The name used when printing messages. This is initialized to ARGV[0],
- or PROGRAM_INVOCATION_NAME if that is unavailable. */
- char *name;
-
- /* Streams used when argp prints something. */
- FILE *err_stream; /* For errors; initialized to stderr. */
- FILE *out_stream; /* For information; initialized to stdout. */
-};
-
-/* Flags for argp_parse (note that the defaults are those that are
- convenient for program command line parsing): */
-
-/* Don't ignore the first element of ARGV. Normally (and always unless
- ARGP_NO_ERRS is set) the first element of the argument vector is
- skipped for option parsing purposes, as it corresponds to the program name
- in a command line. */
-#define ARGP_PARSE_ARGV0 0x1
-
-/* Don't print error messages for unknown options to stderr; unless this flag
- is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program
- name in the error messages. This flag implies ARGP_NO_EXIT (on the
- assumption that silent exiting upon errors is bad behaviour). */
-#define ARGP_NO_ERRS 0x2
-
-/* Don't parse any non-option args. Normally non-option args are parsed by
- calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg
- as the value. Since it's impossible to know which parse function wants to
- handle it, each one is called in turn, until one returns 0 or an error
- other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the
- argp_parse returns prematurely (but with a return value of 0). If all
- args have been parsed without error, all parsing functions are called one
- last time with a key of ARGP_KEY_END. This flag needn't normally be set,
- as the normal behavior is to stop parsing as soon as some argument can't
- be handled. */
-#define ARGP_NO_ARGS 0x4
-
-/* Parse options and arguments in the same order they occur on the command
- line -- normally they're rearranged so that all options come first. */
-#define ARGP_IN_ORDER 0x8
-
-/* Don't provide the standard long option --help, which causes usage and
- option help information to be output to stdout, and exit (0) called. */
-#define ARGP_NO_HELP 0x10
-
-/* Don't exit on errors (they may still result in error messages). */
-#define ARGP_NO_EXIT 0x20
-
-/* Turns off any message-printing/exiting options. */
-#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP)
-
-/* Parse the options strings in ARGC & ARGV according to the options in ARGP.
- FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the
- index in ARGV of the first unparsed option is returned in it. If an
- unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser
- routine returned a non-zero value, it is returned; otherwise 0 is
- returned. This function may also call exit unless the ARGP_NO_HELP flag
- is set. INPUT is a pointer to a value to be passed in to the parser. */
-error_t argp_parse (const struct argp *argp,
- int argc, char **argv, unsigned flags,
- int *arg_index, void *input);
-
-/* If defined or set by the user program to a non-zero value, then a default
- option --version is added (unless the ARGP_NO_HELP flag is used), which
- will print this this string followed by a newline and exit (unless the
- ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
-extern char *argp_program_version;
-
-/* If defined or set by the user program to a non-zero value, then a default
- option --version is added (unless the ARGP_NO_HELP flag is used), which
- calls this function with a stream to print the version to and a pointer to
- the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
- used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
-extern void (*argp_program_version_hook) (FILE *stream,
- struct argp_state *state);
-
-/* Flags for argp_help. */
-#define ARGP_HELP_USAGE 0x01 /* Print a Usage: message. */
-#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */
-#define ARGP_HELP_SEE 0x04 /* Print a `for more help...' message. */
-#define ARGP_HELP_LONG 0x08 /* Print a long help message. */
-
-/* These ARGP_HELP flags are only understood by argp_state_help. */
-#define ARGP_HELP_EXIT_ERR 0x10 /* Call exit(1) instead of returning. */
-#define ARGP_HELP_EXIT_OK 0x20 /* Call exit(0) instead of returning. */
-
-/* The standard thing to do after a program command line parsing error, if an
- error message has already been printed. */
-#define ARGP_HELP_STD_ERR \
- (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
-/* The standard thing to do after a program command line parsing error, if no
- more specific error message has been printed. */
-#define ARGP_HELP_STD_USAGE \
- (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
-/* The standard thing to do in response to a --help option. */
-#define ARGP_HELP_STD_HELP \
- (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK)
-
-/* Output a usage message for ARGP to STREAM. FLAGS are from the set
- ARGP_HELP_*. */
-extern void argp_help (const struct argp *argp, FILE *stream, unsigned flags,
- char *name);
-
-/* The following routines are intended to be called from within an argp
- parsing routine (thus taking an argp_state structure as the first
- argument). They may or may not print an error message and exit, depending
- on the flags in STATE -- in any case, the caller should be prepared for
- them *not* to exit, and should return an appropiate error after calling
- them. [argp_usage & argp_error should probably be called argp_state_...,
- but they're used often enough that they should be short] */
-
-/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
- from the set ARGP_HELP_*. */
-void argp_state_help (struct argp_state *state, FILE *stream, unsigned flags);
-
-/* Possibly output the standard usage message for ARGP to stderr and exit. */
-extern inline void
-argp_usage (struct argp_state *state)
-{
- argp_state_help (state, stderr, ARGP_HELP_STD_USAGE);
-}
-
-/* If appropriate, print the printf string FMT and following args, preceded
- by the program name and `:', to stderr, and followed by a `Try ... --help'
- message, then exit (1). */
-void argp_error (struct argp_state *state, const char *fmt, ...)
- __attribute__ ((format (printf, 2, 3)));
-
-/* Similar to the standard gnu error-reporting function error(), but will
- respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
- to STATE->err_stream. This is useful for argument parsing code that is
- shared between program startup (when exiting is desired) and runtime
- option parsing (when typically an error code is returned instead). The
- difference between this function and argp_error is that the latter is for
- *parsing errors*, and the former is for other problems that occur during
- parsing but don't reflect a (syntactic) problem with the input. */
-void argp_failure (struct argp_state *state,
- int status, int errnum, const char *fmt, ...)
- __attribute__ ((format (printf, 4, 5)));
-
-/* Returns true if the option OPT is a valid short option. */
-extern inline int
-_option_is_short (const struct argp_option *opt)
-{
- int key = opt->key;
- return key > 0 && isprint (key);
-}
-
-/* Returns true if the option OPT is in fact the last (unused) entry in an
- options array. */
-extern inline int
-_option_is_end (const struct argp_option *opt)
-{
- return !opt->key && !opt->name && !opt->doc && !opt->group;
-}
-
-#endif /* __ARGP_H__ */
diff --git a/libshouldbeinlibc/cacheq.c b/libshouldbeinlibc/cacheq.c
index c8b0c989..5649903a 100644
--- a/libshouldbeinlibc/cacheq.c
+++ b/libshouldbeinlibc/cacheq.c
@@ -1,6 +1,6 @@
/* Helper functions for maintaining a fixed-size lru-ordered queue
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1998 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -82,7 +82,8 @@ cacheq_set_length (struct cacheq *cq, int length)
/* Source entries. */
struct cacheq_hdr *fh = cq->mru;
/* Destination entries (and limit). */
- struct cacheq_hdr *th = new_entries, *end = new_entries + esz * length;
+ struct cacheq_hdr *th = new_entries;
+ struct cacheq_hdr *end = new_entries + esz * (length - 1);
struct cacheq_hdr *prev_th = 0;
if (! new_entries)
@@ -91,7 +92,7 @@ cacheq_set_length (struct cacheq *cq, int length)
while (fh || th)
{
struct cacheq_hdr *next_th =
- (!th || th > end) ? 0 : (void *)th + esz;
+ (!th || th >= end) ? 0 : (void *)th + esz;
if (fh && th)
bcopy (fh, th, esz); /* Copy the bits in a moved entry. */
@@ -105,7 +106,7 @@ cacheq_set_length (struct cacheq *cq, int length)
th->next = next_th;
}
- /* Call user hooks as appropiate. */
+ /* Call user hooks as appropriate. */
if (fh && th)
{
if (cq->move_entry)
diff --git a/libshouldbeinlibc/exec-reauth.c b/libshouldbeinlibc/exec-reauth.c
index 2b068684..dd267ef7 100644
--- a/libshouldbeinlibc/exec-reauth.c
+++ b/libshouldbeinlibc/exec-reauth.c
@@ -1,6 +1,6 @@
/* Re-authentication in preparation for an exec
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96, 98, 2000 Free Software Foundation, Inc.
Stolen by Miles Bader <miles@gnu.ai.mit.edu>, but really
written by Michael I. Bushnell p/BSG <mib@gnu.ai.mit.edu>
@@ -54,9 +54,12 @@ exec_reauth (auth_t auth, int secure, int must_reauth,
(isproc ? proc_reauthenticate : io_reauthenticate)
(*port, ref, MACH_MSG_TYPE_MAKE_SEND);
+ /* MAKE_SEND is safe here because we destroy REF ourselves. */
+
if (!err)
err = auth_user_authenticate (auth, ref, MACH_MSG_TYPE_MAKE_SEND,
&newport);
+ mach_port_destroy (mach_task_self (), ref);
if (err)
{
if (must_reauth)
@@ -73,22 +76,23 @@ exec_reauth (auth_t auth, int secure, int must_reauth,
*port = newport;
}
}
- mach_port_destroy (mach_task_self (), ref);
}
return 0;
}
-
+
/* Re-authenticate all the ports we are handing to the user
with this new port, and install the new auth port in ports. */
for (i = 0; i < num_fds && !err; ++i)
err = reauth (&fds[i], 0);
if (!err)
- if (secure)
- /* Not worth doing; the exec server will just do it again. */
- ports[INIT_PORT_CRDIR] = MACH_PORT_NULL;
- else
- err = reauth (&ports[INIT_PORT_CRDIR], 0);
+ {
+ if (secure)
+ /* Not worth doing; the exec server will just do it again. */
+ ports[INIT_PORT_CRDIR] = MACH_PORT_NULL;
+ else
+ err = reauth (&ports[INIT_PORT_CRDIR], 0);
+ }
if (!err)
err = reauth (&ports[INIT_PORT_PROC], 1);
if (!err)
diff --git a/libshouldbeinlibc/fsysops.c b/libshouldbeinlibc/fsysops.c
index 4e282f0b..f26069df 100644
--- a/libshouldbeinlibc/fsysops.c
+++ b/libshouldbeinlibc/fsysops.c
@@ -1,6 +1,6 @@
/* Some handy utility routines for fsys control ports
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1999 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -23,6 +23,7 @@
#include <errno.h>
#include <argz.h>
#include <mach.h>
+#include <sys/mman.h>
#include <hurd/fsys.h>
/* Make FSYS readonly or writable. */
@@ -57,7 +58,7 @@ fsys_get_readonly (fsys_t fsys, int *readonly)
for (opt = opts
; !ok && opt && opt < opts + opts_len
- ; opt = argz_next (opts, opts_len, opt))
+ ; opt = argz_next (opts, opts_len, opt))
if (strcasecmp (opt, "--readonly") == 0)
{
*readonly = 1;
@@ -74,7 +75,7 @@ fsys_get_readonly (fsys_t fsys, int *readonly)
if (opts != _opts)
/* Free out-of-line memory returned by fsys_get_options. */
- vm_deallocate (mach_task_self (), (vm_address_t)opts, opts_len);
+ munmap (opts, opts_len);
}
return err;
@@ -82,10 +83,10 @@ fsys_get_readonly (fsys_t fsys, int *readonly)
/* Tell FSYS to remount itself. */
error_t
-fsys_remount (fsys_t fsys, int readonly)
+fsys_update (fsys_t fsys, int readonly)
{
error_t err;
- char *opts = "--remount";
+ char *opts = "--update";
size_t opts_len = strlen (opts) + 1;
err = fsys_set_options (fsys, opts, opts_len, 0);
if (err == EINVAL)
diff --git a/libshouldbeinlibc/idvec-auth.c b/libshouldbeinlibc/idvec-auth.c
index 896bfdb7..bb7f4afd 100644
--- a/libshouldbeinlibc/idvec-auth.c
+++ b/libshouldbeinlibc/idvec-auth.c
@@ -1,8 +1,9 @@
/* Idvec functions that interact with an auth server
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1998, 1999, 2001, 2002, 2008
+ Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -19,12 +20,11 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <mach.h>
+#include <sys/mman.h>
#include <hurd/auth.h>
#include "idvec.h"
-typedef uid_t id_t;
-
/* Add to all of EFF_UIDS, AVAIL_UIDS, EFF_GIDS, AVAIL_GIDS (as if with
idvec_merge_ids()) the ids associated with the auth port AUTH. Any of
these parameters may be NULL if that information isn't desired. */
@@ -34,12 +34,12 @@ idvec_merge_auth (struct idvec *eff_uids, struct idvec *avail_uids,
auth_t auth)
{
error_t err;
- id_t eff_uid_buf[10], avail_uid_buf[20];
- id_t *_eff_uids = eff_uid_buf, *_avail_uids = avail_uid_buf;
- int num_eff_uids = 10, num_avail_uids = 20;
- id_t eff_gid_buf[10], avail_gid_buf[20];
- id_t *_eff_gids = eff_gid_buf, *_avail_gids = avail_gid_buf;
- int num_eff_gids = 10, num_avail_gids = 20;
+ uid_t eff_uid_buf[10], avail_uid_buf[20];
+ uid_t *_eff_uids = eff_uid_buf, *_avail_uids = avail_uid_buf;
+ size_t num_eff_uids = 10, num_avail_uids = 20;
+ uid_t eff_gid_buf[10], avail_gid_buf[20];
+ uid_t *_eff_gids = eff_gid_buf, *_avail_gids = avail_gid_buf;
+ size_t num_eff_gids = 10, num_avail_gids = 20;
err = auth_getids (auth,
&_eff_uids, &num_eff_uids, &_avail_uids, &num_avail_uids,
@@ -60,21 +60,25 @@ idvec_merge_auth (struct idvec *eff_uids, struct idvec *avail_uids,
/* Now that we've ensured there's enough space, none of these should
return an error. */
{
- idvec_merge_ids (eff_uids, _eff_uids, num_eff_uids);
- idvec_merge_ids (avail_uids, _avail_uids, num_avail_uids);
- idvec_merge_ids (eff_gids, _eff_gids, num_eff_gids);
- idvec_merge_ids (avail_gids, _avail_gids, num_avail_gids);
+ if (eff_uids)
+ idvec_merge_ids (eff_uids, _eff_uids, num_eff_uids);
+ if (avail_uids)
+ idvec_merge_ids (avail_uids, _avail_uids, num_avail_uids);
+ if (eff_gids)
+ idvec_merge_ids (eff_gids, _eff_gids, num_eff_gids);
+ if (avail_gids)
+ idvec_merge_ids (avail_gids, _avail_gids, num_avail_gids);
}
/* Deallocate any out-of-line memory we got back. */
if (_eff_uids != eff_uid_buf)
- vm_deallocate (mach_task_self (), (vm_address_t)_eff_uids, num_eff_uids);
+ munmap ((caddr_t) _eff_uids, num_eff_uids * sizeof (uid_t));
if (_avail_uids != avail_uid_buf)
- vm_deallocate (mach_task_self (), (vm_address_t)_avail_uids, num_avail_uids);
+ munmap ((caddr_t) _avail_uids, num_avail_uids * sizeof (uid_t));
if (_eff_gids != eff_gid_buf)
- vm_deallocate (mach_task_self (), (vm_address_t)_eff_gids, num_eff_gids);
+ munmap ((caddr_t) _eff_gids, num_eff_gids * sizeof (gid_t));
if (_avail_gids != avail_gid_buf)
- vm_deallocate (mach_task_self (), (vm_address_t)_avail_gids, num_avail_gids);
+ munmap ((caddr_t) _avail_gids, num_avail_gids * sizeof (gid_t));
return err;
}
diff --git a/libshouldbeinlibc/idvec-funcs.c b/libshouldbeinlibc/idvec-funcs.c
new file mode 100644
index 00000000..3bb0318d
--- /dev/null
+++ b/libshouldbeinlibc/idvec-funcs.c
@@ -0,0 +1,2 @@
+#define IDVEC_DEFINE_EI
+#include "idvec.h"
diff --git a/libshouldbeinlibc/idvec-impgids.c b/libshouldbeinlibc/idvec-impgids.c
new file mode 100644
index 00000000..66f82e21
--- /dev/null
+++ b/libshouldbeinlibc/idvec-impgids.c
@@ -0,0 +1,127 @@
+/* Add gids implied by a user
+
+ Copyright (C) 1997, 2001 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 <errno.h>
+#include <idvec.h>
+#include <pwd.h>
+#include <grp.h>
+
+#define NUM_STATIC_GIDS 100 /* Initial size of static gid array. */
+
+/* The set of gids implied by a uid. */
+struct uid_implies
+{
+ uid_t uid; /* this uid... */
+ struct idvec *implies; /* implies these gids. */
+ struct uid_implies *next;
+};
+
+/* Cache of previously calculated results for add_implied_gids. */
+static struct uid_implies *uid_implies_cache = 0;
+
+/* Add to IMPLIED_GIDS those group ids implied by the user UID. */
+static error_t
+_merge_implied_gids (struct idvec *implied_gids, uid_t uid)
+{
+ struct uid_implies *ui;
+
+ for (ui = uid_implies_cache; ui; ui = ui->next)
+ if (ui->uid == uid)
+ return idvec_merge (implied_gids, ui->implies);
+
+ {
+ error_t err = 0;
+ struct passwd *pw = getpwuid (uid);
+
+ if (! pw)
+ err = EINVAL;
+ else
+ {
+ struct idvec *cache = make_idvec ();
+#ifdef HAVE_GETGROUPLIST
+ gid_t _gids[NUM_STATIC_GIDS], *gids = _gids;
+ int maxgids = NUM_STATIC_GIDS;
+ int ngids = getgrouplist (pw->pw_name, pw->pw_gid, gids, &maxgids);
+
+ if (ngids == -1)
+ {
+ gids = malloc (maxgids * sizeof (gid_t));
+ if (! gids)
+ err = ENOMEM;
+ else
+ ngids = getgrouplist (pw->pw_name, pw->pw_gid, gids, &maxgids);
+ }
+
+ if (! cache)
+ err = ENOMEM;
+
+ if (! err)
+ {
+ err = idvec_merge_ids (cache, gids, ngids);
+ if (gids != _gids)
+ free (gids);
+ }
+#else
+#warning "getgrouplist() not available; supplementary group IDs unsupported."
+ if (! cache)
+ err = ENOMEM;
+ else
+ {
+ err = idvec_add_new (cache, pw->pw_gid);
+ if (err)
+ idvec_free (cache);
+ }
+#endif
+
+ if (! err)
+ {
+ idvec_merge (implied_gids, cache);
+ ui = malloc (sizeof (struct uid_implies));
+ if (ui)
+ {
+ ui->uid = uid;
+ ui->implies = cache;
+ ui->next = uid_implies_cache;
+ uid_implies_cache = ui;
+ }
+ else
+ idvec_free (cache);
+ }
+ }
+
+ return err;
+ }
+}
+
+/* Add to GIDS those group ids implied by the users in UIDS. */
+error_t
+idvec_merge_implied_gids (struct idvec *gids, const struct idvec *uids)
+{
+ int i;
+ error_t err = 0;
+ for (i = 0; i < uids->num; i++)
+ {
+ error_t this_err = _merge_implied_gids (gids, uids->ids[i]);
+ if (this_err && !err)
+ err = this_err;
+ }
+ return err;
+}
diff --git a/libshouldbeinlibc/idvec-rep.c b/libshouldbeinlibc/idvec-rep.c
new file mode 100644
index 00000000..b20e58ca
--- /dev/null
+++ b/libshouldbeinlibc/idvec-rep.c
@@ -0,0 +1,164 @@
+/* idvec string representation
+
+ Copyright (C) 1996, 1997, 1998 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <idvec.h>
+#include <grp.h>
+#include <pwd.h>
+
+/* Return a string representation of the ids in IDVEC, each id separated by
+ the string SEP (default ","). SHOW_VALUES and SHOW_NAMES reflect how each
+ id is printed (if SHOW_NAMES is true values are used where names aren't
+ available); if both are true, the `VALUE(NAME)' format is used.
+ ID_NAME_FN is used to map each id to a name; it should return a malloced
+ string, which will be freed here. The empty string is returned for an
+ empty list, and 0 for an allocation error. */
+char *
+idvec_rep (const struct idvec *idvec, int show_values, int show_names,
+ char *(*id_name_fn) (uid_t id), const char *sep)
+{
+ size_t sep_len;
+ char *rep = 0;
+ size_t rep_len = 0, rep_sz = 0;
+
+ int ensure_room (size_t amount)
+ {
+ size_t end = rep_len + amount;
+ if (end > rep_sz)
+ {
+ size_t new_sz = rep_sz + end;
+ char *new_rep = realloc (rep, new_sz);
+ if (new_rep)
+ {
+ rep = new_rep;
+ rep_sz = new_sz;
+ }
+ else
+ return 0;
+ }
+ return 1;
+ }
+ int add_id (uid_t val, char *name)
+ {
+ if (!name || show_values)
+ {
+ if (! ensure_room (10))
+ return 0;
+ rep_len += snprintf (rep + rep_len, 10, "%d", val);
+ }
+ if (name)
+ {
+ size_t nlen = strlen (name) + 3;
+ if (! ensure_room (nlen))
+ {
+ free (name);
+ return 0;
+ }
+ rep_len +=
+ snprintf (rep + rep_len, nlen, show_values ? "(%s)" : "%s", name);
+ free (name);
+ }
+ return 1;
+ }
+
+ if (! sep)
+ sep = ",";
+ sep_len = strlen (sep);
+
+ if (idvec->num > 0)
+ {
+ int i;
+
+ for (i = 0; i < idvec->num; i++)
+ {
+ char *name = 0;
+ uid_t val = idvec->ids[i];
+
+ if (i > 0)
+ {
+ if (ensure_room (sep_len))
+ {
+ strcpy (rep + rep_len, sep);
+ rep_len += sep_len;
+ }
+ else
+ break;
+ }
+
+ if (show_names || !show_values)
+ name = (*id_name_fn) (val);
+ if (! add_id (val, name))
+ break;
+ }
+
+ if (i < idvec->num)
+ {
+ free (rep);
+ return 0;
+ }
+
+ return rep;
+ }
+
+ return strdup ("");
+}
+
+/* Return a malloced string with the name of the user UID. */
+static char *
+lookup_uid (uid_t uid)
+{
+ char buf[1024];
+ struct passwd _pw, *pw;
+ if (getpwuid_r (uid, &_pw, buf, sizeof buf, &pw) == 0)
+ return strdup (pw->pw_name);
+ else
+ return 0;
+}
+
+/* Return a malloced string with the name of the group GID. */
+static char *
+lookup_gid (gid_t gid)
+{
+ char buf[1024];
+ struct group _gr, *gr;
+ if (getgrgid_r (gid, &_gr, buf, sizeof buf, &gr) == 0)
+ return strdup (gr->gr_name);
+ else
+ return 0;
+}
+
+/* Like idvec_rep, mapping ids to user names. */
+char *
+idvec_uids_rep (const struct idvec *idvec, int show_values, int show_names,
+ const char *sep)
+{
+ return idvec_rep (idvec, show_values, show_names, lookup_uid, sep);
+}
+
+/* Like idvec_rep, mapping ids to group names. */
+char *
+idvec_gids_rep (const struct idvec *idvec, int show_values, int show_names,
+ const char *sep)
+{
+ return idvec_rep (idvec, show_values, show_names, lookup_gid, sep);
+}
diff --git a/libshouldbeinlibc/idvec-verify.c b/libshouldbeinlibc/idvec-verify.c
new file mode 100644
index 00000000..981f86ac
--- /dev/null
+++ b/libshouldbeinlibc/idvec-verify.c
@@ -0,0 +1,362 @@
+/* Verify user passwords
+
+ Copyright (C) 1996, 1997, 1998, 1999, 2002, 2008
+ Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.org>
+
+ 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 <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <idvec.h>
+#include <grp.h>
+#include <pwd.h>
+#include <shadow.h>
+#include <crypt.h>
+
+#define SHADOW_PASSWORD_STRING "x" /* pw_passwd contents for shadow passwd */
+
+#pragma weak crypt
+
+static error_t verify_id (); /* FWD */
+
+/* Get a password from the user, returning it in malloced storage. */
+static char *
+get_passwd (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook)
+{
+ char *st = getpass (prompt);
+ if (st)
+ st = strdup (st);
+ return st;
+}
+
+/* Verify PASSWORD using /etc/passwd (and maybe /etc/shadow). */
+static error_t
+verify_passwd (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook)
+{
+ const char *encrypted;
+ int wheel_uid = (intptr_t)hook;
+ const char *sys_encrypted;
+
+ if (! pwd_or_grp)
+ /* No password db entry for ID; if ID is root, the system is probably
+ really fucked up, so grant it (heh). */
+ return (id == 0 ? 0 : EACCES);
+
+ /* The encrypted password in the passwd db. */
+ sys_encrypted =
+ (is_group
+ ? ((struct passwd *)pwd_or_grp)->pw_passwd
+ : ((struct group *)pwd_or_grp)->gr_passwd);
+
+ if (sys_encrypted[0] == '\0')
+ return 0; /* No password. */
+
+ if (crypt)
+ /* Encrypt the password entered by the user (SYS_ENCRYPTED is the salt). */
+ encrypted = crypt (password, sys_encrypted);
+ else
+ /* No crypt on this system! Use plain-text passwords. */
+ encrypted = password;
+
+ if (! encrypted)
+ /* Crypt failed. */
+ return errno;
+
+ /* See whether the user's password matches the system one. */
+ if (strcmp (encrypted, sys_encrypted) == 0)
+ /* Password check succeeded. */
+ return 0;
+ else if (id == 0 && !is_group && wheel_uid)
+ /* Special hack: a user attempting to gain root access can use
+ their own password (instead of root's) if they're in group 0. */
+ {
+ struct passwd _pw, *pw;
+ char lookup_buf[1024];
+ char sp_lookup_buf[1024];
+
+ const char *check_shadow (struct passwd *pw)
+ {
+ if (strcmp (pw->pw_passwd, SHADOW_PASSWORD_STRING) == 0)
+ {
+ /* When encrypted password is "x", try shadow passwords. */
+ struct spwd _sp, *sp;
+ if (getspnam_r (pw->pw_name, &_sp, sp_lookup_buf,
+ sizeof sp_lookup_buf, &sp) == 0)
+ return sp->sp_pwdp;
+ }
+ return pw->pw_passwd;
+ }
+
+ if (getpwuid_r (wheel_uid, &_pw, lookup_buf, sizeof lookup_buf, &pw))
+ return errno ?: EINVAL;
+
+ sys_encrypted = check_shadow (pw);
+
+ encrypted = crypt (password, sys_encrypted);
+ if (! encrypted)
+ /* Crypt failed. */
+ return errno;
+
+ if (strcmp (encrypted, sys_encrypted) == 0)
+ /* *this* password is correct! */
+ return 0;
+ }
+
+ return EACCES;
+}
+
+/* Make sure the user has the right to the ids in UIDS and GIDS, given that
+ we know he already has HAVE_UIDS and HAVE_GIDS, asking for passwords (with
+ GETPASS_FN) where necessary; any of the arguments may be 0, which is
+ treated the same as if they were empty. 0 is returned if access should be
+ allowed, otherwise EINVAL if an incorrect password was entered, or an
+ error relating to resource failure. Any uid/gid < 0 will be guaranteed to
+ fail regardless of what the user types. GETPASS_FN should ask for a
+ password from the user, and return it in malloced storage; it defaults to
+ using the standard libc function getpass. If VERIFY_FN is 0, then the
+ users password will be encrypted with crypt and compared with the
+ password/group entry's encrypted password, otherwise, VERIFY_FN will be
+ called to check the entered password's validity; it should return 0 if the
+ given password is correct, or an error code. The common arguments to
+ GETPASS_FN and VERIFY_FN are: ID, the user/group id; IS_GROUP, true if its
+ a group, or false if a user; PWD_OR_GRP, a pointer to either the passwd or
+ group entry for ID, and HOOK, containing the appropriate hook passed into
+ idvec_verify. */
+error_t
+idvec_verify (const struct idvec *uids, const struct idvec *gids,
+ const struct idvec *have_uids, const struct idvec *have_gids,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *getpass_hook,
+ error_t (*verify_fn) (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *verify_hook)
+{
+ if (have_uids && idvec_contains (have_uids, 0))
+ /* Root can do anything. */
+ return 0;
+ else
+ {
+ int i;
+ int multiple = 0; /* Asking for multiple ids? */
+ error_t err = 0; /* Our return status. */
+ struct idvec implied_gids = IDVEC_INIT; /* Gids implied by uids. */
+ /* If we already are in group 0 (`wheel'), this user's password can be
+ used to get root privileges instead of root's. */
+ int wheel_uid =
+ ((have_uids && have_gids
+ && (idvec_contains (have_gids, 0) && have_uids->num > 0))
+ ? have_uids->ids[0]
+ : 0);
+
+ if (! verify_fn)
+ {
+ verify_fn = verify_passwd;
+ verify_hook = (void *)(intptr_t)wheel_uid;
+ }
+
+ /* See if there are multiple ids in contention, in which case we should
+ name each user/group as we ask for its password. */
+ if (uids && gids)
+ {
+ int num_non_implied_gids = 0;
+
+ /* Calculate which groups we need not ask about because they are
+ implied by the uids which we (will) have verified. Note that we
+ ignore any errors; at most, it means we will ask for too many
+ passwords. */
+ idvec_merge_implied_gids (&implied_gids, uids);
+
+ for (i = 0; i < gids->num; i++)
+ if (! idvec_contains (&implied_gids, gids->ids[i]))
+ num_non_implied_gids++;
+
+ multiple = (uids->num + num_non_implied_gids) > 1;
+ }
+ else if (uids)
+ multiple = uids->num > 1;
+ else if (gids)
+ multiple = gids->num > 1;
+
+ if (uids && idvec_contains (uids, 0))
+ /* root is being asked for, which, once granted will provide access for
+ all the others. */
+ err = verify_id (0, 0, multiple,
+ getpass_fn, getpass_hook, verify_fn, verify_hook);
+ else
+ {
+ if (uids)
+ /* Check uids */
+ for (i = 0; i < uids->num && !err; i++)
+ {
+ uid_t uid = uids->ids[i];
+ if (!have_uids || !idvec_contains (have_uids, uid))
+ err = verify_id (uid, 0, multiple,
+ getpass_fn, getpass_hook, verify_fn, verify_hook);
+ }
+
+ if (gids)
+ /* Check gids */
+ for (i = 0; i < gids->num && !err; i++)
+ {
+ gid_t gid = gids->ids[i];
+ if ((!have_gids || !idvec_contains (have_gids, gid))
+ && !idvec_contains (&implied_gids, gid))
+ err = verify_id (gid, 1, multiple,
+ getpass_fn, getpass_hook, verify_fn, verify_hook);
+ }
+ }
+
+ idvec_fini (&implied_gids);
+
+ return err;
+ }
+}
+
+/* Verify that the user should be allowed to assume the indentity of the
+ user/group ID (depending on whether IS_GROUP is false/true). If MULTIPLE
+ is true, then this is one of multiple ids being verified, so */
+static error_t
+verify_id (uid_t id, int is_group, int multiple,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *getpass_hook,
+ error_t (*verify_fn) (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *verify_hook)
+{
+ int err;
+ void *pwd_or_grp = 0;
+ char *name = 0;
+ char *prompt = 0, *password;
+ char id_lookup_buf[1024];
+ char sp_lookup_buf[1024];
+
+ /* VERIFY_FN should have been defaulted in idvec_verify if necessary. */
+ assert (verify_fn);
+
+ if (id != (uid_t) -1)
+ do
+ {
+ if (is_group)
+ {
+ struct group _gr, *gr;
+ if (getgrgid_r (id, &_gr, id_lookup_buf, sizeof id_lookup_buf, &gr)
+ == 0)
+ {
+ if (!gr->gr_passwd || !*gr->gr_passwd)
+ return (*verify_fn) ("", id, 1, gr, verify_hook);
+ name = gr->gr_name;
+ pwd_or_grp = gr;
+ }
+ }
+ else
+ {
+ struct passwd _pw, *pw;
+ if (getpwuid_r (id, &_pw, id_lookup_buf, sizeof id_lookup_buf, &pw)
+ == 0)
+ {
+ if (strcmp (pw->pw_passwd, SHADOW_PASSWORD_STRING) == 0)
+ {
+ /* When encrypted password is "x", check shadow
+ passwords to see if there is an empty password. */
+ struct spwd _sp, *sp;
+ if (getspnam_r (pw->pw_name, &_sp, sp_lookup_buf,
+ sizeof sp_lookup_buf, &sp) == 0)
+ /* The storage for the password string is in
+ SP_LOOKUP_BUF, a local variable in this function.
+ We Know that the only use of PW->pw_passwd will be
+ in the VERIFY_FN call in this function, and that
+ the pointer will not be stored past the call. */
+ pw->pw_passwd = sp->sp_pwdp;
+ }
+
+ if (pw->pw_passwd[0] == '\0')
+ return (*verify_fn) ("", id, 0, pw, verify_hook);
+ name = pw->pw_name;
+ pwd_or_grp = pw;
+ }
+ }
+ if (! name)
+ {
+ /* [ug]id lookup failed! */
+ if (id != 0 || is_group)
+ /* If ID != 0, then it's probably just an unknown id, so ask for
+ the root password instead -- root should be able to do
+ anything. */
+ {
+ id = 0; /* Root */
+ is_group = 0; /* uid */
+ multiple = 1; /* Explicitly ask for root's password. */
+ }
+ else
+ /* No password entry for root. */
+ name = "root";
+ }
+ }
+ while (! name);
+
+ if (! getpass_fn)
+ /* Default GETPASS_FN to using getpass. */
+ getpass_fn = get_passwd;
+
+ if (multiple)
+ {
+ if (name)
+ asprintf (&prompt, "Password for %s%s:",
+ is_group ? "group " : "", name);
+ else
+ asprintf (&prompt, "Password for %s %d:",
+ is_group ? "group" : "user", id);
+ }
+
+ /* Prompt the user for the password. */
+ if (prompt)
+ {
+ password =
+ (*getpass_fn) (prompt, id, is_group, pwd_or_grp, getpass_hook);
+ free (prompt);
+ }
+ else
+ password =
+ (*getpass_fn) ("Password:", id, is_group, pwd_or_grp, getpass_hook);
+
+ /* Check the user's answer. */
+ if (password)
+ {
+ err = (*verify_fn) (password, id, is_group, pwd_or_grp, verify_hook);
+
+ /* Paranoia may destroya. */
+ memset (password, 0, strlen (password));
+
+ free (password);
+ }
+ else
+ err = EACCES;
+
+ return err;
+}
diff --git a/libshouldbeinlibc/idvec.c b/libshouldbeinlibc/idvec.c
index 6daa639a..24adeb8f 100644
--- a/libshouldbeinlibc/idvec.c
+++ b/libshouldbeinlibc/idvec.c
@@ -1,6 +1,6 @@
/* Routines for vectors of uids/gids
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -22,8 +22,6 @@
#include <string.h>
#include <idvec.h>
-typedef uid_t id_t;
-
/* Return a new, empty, idvec, or NULL if there wasn't enough memory. */
struct idvec *
make_idvec ()
@@ -67,7 +65,7 @@ idvec_ensure (struct idvec *idvec, unsigned num)
{
if (num > idvec->alloced)
{
- id_t *_ids = realloc (idvec->ids, num * sizeof (id_t));
+ uid_t *_ids = realloc (idvec->ids, num * sizeof (uid_t));
if (! _ids)
return ENOMEM;
idvec->ids = _ids;
@@ -83,47 +81,42 @@ idvec_grow (struct idvec *idvec, unsigned inc)
{
return idvec_ensure (idvec, idvec->num + inc);
}
-
+
/* Returns true if IDVEC contains ID, at or after position POS. */
int
-idvec_tail_contains (struct idvec *idvec, unsigned pos, id_t id)
+idvec_tail_contains (const struct idvec *idvec, unsigned pos, uid_t id)
{
- while (pos < idvec->num)
- if (idvec->ids[pos++] == id)
+ uid_t *ids = idvec->ids, *end = ids + idvec->num, *p = ids + pos;
+ while (p < end)
+ if (*p++ == id)
return 1;
return 0;
}
-
-/* Returns true if IDVEC contains ID. */
-int
-idvec_contains (struct idvec *idvec, id_t id)
-{
- return idvec_tail_contains (idvec, 0, id);
-}
/* Insert ID into IDVEC at position POS, returning ENOMEM if there wasn't
enough memory, or 0. */
error_t
-idvec_insert (struct idvec *idvec, unsigned pos, id_t id)
+idvec_insert (struct idvec *idvec, unsigned pos, uid_t id)
{
error_t err = 0;
unsigned num = idvec->num;
+ unsigned new_num = (pos < num ? num + 1 : pos + 1);
if (idvec->alloced == num)
/* If we seem to be growing by just one, actually prealloc some more. */
- err = idvec_grow (idvec, num + 1);
+ err = idvec_ensure (idvec, new_num + num);
else
- err = idvec_grow (idvec, 1);
+ err = idvec_ensure (idvec, new_num);
if (! err)
{
- id_t *ids = idvec->ids;
+ uid_t *ids = idvec->ids;
if (pos < num)
- bcopy (ids + pos, ids + pos + 1, (num - pos) * sizeof (id_t));
+ bcopy (ids + pos, ids + pos + 1, (num - pos) * sizeof (uid_t));
else if (pos > num)
- bzero (ids + num, (pos - num) * sizeof (id_t));
+ bzero (ids + num, (pos - num) * sizeof (uid_t));
ids[pos] = id;
- idvec->num = num + 1;
+ idvec->num = new_num;
}
return err;
@@ -132,7 +125,7 @@ idvec_insert (struct idvec *idvec, unsigned pos, id_t id)
/* Add ID onto the end of IDVEC, returning ENOMEM if there's not enough memory,
or 0. */
error_t
-idvec_add (struct idvec *idvec, id_t id)
+idvec_add (struct idvec *idvec, uid_t id)
{
return idvec_insert (idvec, idvec->num, id);
}
@@ -140,7 +133,7 @@ idvec_add (struct idvec *idvec, id_t id)
/* If IDVEC doesn't contain ID, add it onto the end, returning ENOMEM if
there's not enough memory; otherwise, do nothing. */
error_t
-idvec_add_new (struct idvec *idvec, id_t id)
+idvec_add_new (struct idvec *idvec, uid_t id)
{
if (idvec_contains (idvec, id))
return 0;
@@ -151,7 +144,7 @@ idvec_add_new (struct idvec *idvec, id_t id)
/* If IDVEC doesn't contain ID at position POS or after, insert it at POS,
returning ENOMEM if there's not enough memory; otherwise, do nothing. */
error_t
-idvec_insert_new (struct idvec *idvec, unsigned pos, id_t id)
+idvec_insert_new (struct idvec *idvec, unsigned pos, uid_t id)
{
if (idvec_tail_contains (idvec, pos, id))
return 0;
@@ -159,10 +152,33 @@ idvec_insert_new (struct idvec *idvec, unsigned pos, id_t id)
return idvec_insert (idvec, pos, id);
}
+/* Set the ids in IDVEC to IDS (NUM elements long); delete whatever
+ the previous ids were. */
+error_t
+idvec_set_ids (struct idvec *idvec, const uid_t *ids, unsigned num)
+{
+ error_t err;
+
+ err = idvec_ensure (idvec, num);
+ if (!err)
+ {
+ bcopy (ids, idvec->ids, num * sizeof (uid_t));
+ idvec->num = num;
+ }
+ return err;
+}
+
+/* Like idvec_set_ids, but get the new ids from new. */
+error_t
+idvec_set (struct idvec *idvec, const struct idvec *new)
+{
+ return idvec_set_ids (idvec, new->ids, new->num);
+}
+
/* Adds each id in the vector IDS (NUM elements long) to IDVEC, as long as it
wasn't previously in IDVEC. */
error_t
-idvec_merge_ids (struct idvec *idvec, id_t *ids, unsigned num)
+idvec_merge_ids (struct idvec *idvec, const uid_t *ids, unsigned num)
{
error_t err = 0;
unsigned num_old = idvec->num;
@@ -181,34 +197,77 @@ idvec_merge_ids (struct idvec *idvec, id_t *ids, unsigned num)
/* Adds each id from NEW to IDVEC, as if with idvec_add_new(). */
error_t
-idvec_merge (struct idvec *idvec, struct idvec *new)
+idvec_merge (struct idvec *idvec, const struct idvec *new)
{
return idvec_merge_ids (idvec, new->ids, new->num);
}
-/* Remove any occurances of ID in IDVEC after position POS> Returns true if
- anything was done. */
+/* Remove any occurrences of ID in IDVEC after position POS.
+ Returns true if anything was done. */
int
-idvec_remove (struct idvec *idvec, unsigned pos, id_t id)
+idvec_remove (struct idvec *idvec, unsigned pos, uid_t id)
{
- int left = idvec->num - pos;
- id_t *ids = idvec->ids + pos, *targ = ids;
- while (left--)
+ if (pos < idvec->num)
{
- if (*ids != id)
+ int left = idvec->num - pos;
+ uid_t *ids = idvec->ids + pos, *targ = ids;
+ while (left--)
{
- if (ids != targ)
- *targ = *ids;
- targ++;
+ if (*ids != id)
+ {
+ if (ids != targ)
+ *targ = *ids;
+ targ++;
+ }
+ ids++;
}
- ids++;
+ if (ids == targ)
+ return 0;
+ idvec->num = targ - idvec->ids;
+ return 1;
}
- if (ids == targ)
+ else
return 0;
- idvec->num = targ - idvec->ids;
- return 1;
}
+/* Remove all ids in SUB from IDVEC, returning true if anything was done. */
+int
+idvec_subtract (struct idvec *idvec, const struct idvec *sub)
+{
+ int i;
+ int done = 0;
+ for (i = 0; i < sub->num; i++)
+ done |= idvec_remove (idvec, 0, sub->ids[i]);
+ return done;
+}
+
+/* Remove all ids from IDVEC that are *not* in KEEP, returning true if
+ anything was changed. */
+int
+idvec_keep (struct idvec *idvec, const struct idvec *keep)
+{
+ uid_t *old = idvec->ids, *new = old, *end = old + idvec->num;
+
+ while (old < end)
+ {
+ uid_t id = *old++;
+ if (idvec_contains (keep, id))
+ {
+ if (old != new)
+ *new = id;
+ new++;
+ }
+ }
+
+ if (old != new)
+ {
+ idvec->num = new - idvec->ids;
+ return 1;
+ }
+ else
+ return 0;
+}
+
/* Deleted the id at position POS in IDVEC. */
void
idvec_delete (struct idvec *idvec, unsigned pos)
@@ -216,20 +275,20 @@ idvec_delete (struct idvec *idvec, unsigned pos)
unsigned num = idvec->num;
if (pos < num)
{
- id_t *ids = idvec->ids;
+ uid_t *ids = idvec->ids;
idvec->num = --num;
if (num > pos)
- bcopy (ids + pos + 1, ids + pos, (num - pos) * sizeof (id_t));
+ bcopy (ids + pos + 1, ids + pos, (num - pos) * sizeof (uid_t));
}
}
-/* Insert ID at position POS in IDVEC, remoint any instances of ID previously
+/* Insert ID at position POS in IDVEC, remove any instances of ID previously
present at POS or after. ENOMEM is returned if there's not enough memory,
otherwise 0. */
error_t
-idvec_insert_only (struct idvec *idvec, unsigned pos, id_t id)
+idvec_insert_only (struct idvec *idvec, unsigned pos, uid_t id)
{
- if (idvec->ids[pos] == id)
+ if (idvec->num > pos && idvec->ids[pos] == id)
return 0;
else
{
@@ -238,39 +297,37 @@ idvec_insert_only (struct idvec *idvec, unsigned pos, id_t id)
}
}
-/* EFF and AVAIL should be idvec's corresponding to a processes effective and
- available ids. ID replaces the first id in EFF, and what it replaces is
- preserved by adding it to AVAIL (if not already present). If SECURE is
- non-NULL, and ID was not previously present in either EFF or AVAIL, then
- *SECURE is set to true. ENOMEM is returned if a malloc fails, otherwise
- 0. The return parameters are only touched if this call succeeds. */
+/* EFF and AVAIL should be idvec's corresponding to a processes
+ effective and available ids. ID replaces the first id in EFF, and,
+ if there are any IDs in AVAIL, replaces the second ID in AVAIL;
+ what it replaces in any case is preserved by adding it to AVAIL if
+ not already present. In addition, the If SECURE is non-NULL, and
+ ID was not previously present in either EFF or AVAIL, then *SECURE
+ is set to true. ENOMEM is returned if a malloc fails, otherwise 0.
+ The return parameters are only touched if this call succeeds. */
error_t
-idvec_setid (struct idvec *eff, struct idvec *avail, id_t id, int *secure)
+idvec_setid (struct idvec *eff, struct idvec *avail, uid_t id, int *secure)
{
error_t err;
/* True if ID was not previously present in either EFF or AVAIL. */
int _secure = !idvec_contains (eff, id) && !idvec_contains (avail, id);
if (eff->num > 0)
- /* If there are any old effective ids, we replace eff[0] with ID, and try
- to preserve the old eff[0] by putting it in AVAIL list if necessary. */
{
- if (avail->num == 0)
- /* The old eff[0] becomes avail[0] (the posix real id). */
- err = idvec_add (avail, eff->ids[0]);
- else
- /* We preserve the old real id, and add eff[0] to the list of saved
- ids (if necessary). Inserting it means that the latest id saved
- will correspond to the (single) posix saved id. */
- err = idvec_insert_only (avail, 1, eff->ids[0]);
-
- /* Replace eff[0] with the new id. */
- eff->ids[0] = id;
+ /* If there are any old effective ids, we replace eff[0] with
+ ID, and try to preserve the old eff[0] by putting it in AVAIL
+ list if necessary. */
+ err = idvec_add_new (avail, eff->ids[0]);
+ if (!err)
+ eff->ids[0] = id;
}
else
/* No previous effective ids, just make ID the first one. */
err = idvec_add (eff, id);
+ if (avail->num > 0 && !err)
+ err = idvec_insert_only (avail, 1, id);
+
if (err)
return err;
diff --git a/libshouldbeinlibc/idvec.h b/libshouldbeinlibc/idvec.h
index 8e99d433..abbc273e 100644
--- a/libshouldbeinlibc/idvec.h
+++ b/libshouldbeinlibc/idvec.h
@@ -1,8 +1,7 @@
/* Routines for vectors of uids/gids
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Copyright (C) 1995,96,97,99,2001 Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -22,8 +21,16 @@
#define __IDVEC_H__
#include <sys/types.h>
-#include <errno.h>
#include <hurd/hurd_types.h>
+#include <errno.h>
+#include <string.h>
+#include <features.h>
+
+#ifdef IDVEC_DEFINE_EI
+#define IDVEC_EI
+#else
+#define IDVEC_EI __extern_inline
+#endif
struct idvec
{
@@ -31,11 +38,14 @@ struct idvec
unsigned num, alloced;
};
+#define IDVEC_INIT { 0 }
+
/* Return a new, empty, idvec, or NULL if there wasn't enough memory. */
struct idvec *make_idvec (void);
/* Free the storage pointed to by IDVEC->ids. */
void idvec_free_contents (struct idvec *idvec);
+#define idvec_fini idvec_free_contents
/* Free IDVEC, but not the storage pointed to by the IDS field. */
void idvec_free_wrapper (struct idvec *idvec);
@@ -43,13 +53,40 @@ void idvec_free_wrapper (struct idvec *idvec);
/* Free IDVEC and any storage associated with it. */
void idvec_free (struct idvec *idvec);
+extern void idvec_clear (struct idvec *idvec);
+
+extern int idvec_is_empty (const struct idvec *idvec);
+
+extern int idvec_equal (const struct idvec *idvec1, const struct idvec *idvec2);
+
+#if defined(__USE_EXTERN_INLINES) || defined(IDVEC_DEFINE_EI)
+
/* Mark IDVEC as not containing any ids. */
-extern inline void
+IDVEC_EI void
idvec_clear (struct idvec *idvec)
{
idvec->num = 0;
}
+/* Returns true if IDVEC contains no ids. */
+IDVEC_EI int
+idvec_is_empty (const struct idvec *idvec)
+{
+ return idvec->num == 0;
+}
+
+/* Return true if IDVEC1 has contents identical to IDVEC2. */
+IDVEC_EI int
+idvec_equal (const struct idvec *idvec1, const struct idvec *idvec2)
+{
+ size_t num = idvec1->num;
+ return idvec2->num == num
+ && (num == 0
+ || memcmp (idvec1->ids, idvec2->ids, num * sizeof *idvec1->ids) == 0);
+}
+
+#endif /* Use extern inlines. */
+
/* Ensure that IDVEC has enough spaced allocated to hold NUM ids, thus
ensuring that any subsequent ids added won't return a memory allocation
error unless it would result in more ids that NUM. ENOMEM is returned if
@@ -61,10 +98,20 @@ error_t idvec_ensure (struct idvec *idvec, unsigned num);
error_t idvec_grow (struct idvec *idvec, unsigned inc);
/* Returns true if IDVEC contains ID, at or after position POS. */
-int idvec_tail_contains (struct idvec *idvec, unsigned pos, uid_t id);
+int idvec_tail_contains (const struct idvec *idvec, unsigned pos, uid_t id);
+
+extern int idvec_contains (const struct idvec *idvec, uid_t id);
+
+#if defined(__USE_EXTERN_INLINES) || defined(IDVEC_DEFINE_EI)
/* Returns true if IDVEC contains ID. */
-int idvec_contains (struct idvec *idvec, uid_t id);
+IDVEC_EI int
+idvec_contains (const struct idvec *idvec, uid_t id)
+{
+ return idvec_tail_contains (idvec, 0, id);
+}
+
+#endif /* Use extern inlines. */
/* Insert ID into IDVEC at position POS, returning ENOMEM if there wasn't
enough memory, or 0. */
@@ -82,31 +129,47 @@ error_t idvec_add_new (struct idvec *idvec, uid_t id);
returning ENOMEM if there's not enough memory; otherwise, do nothing. */
error_t idvec_insert_new (struct idvec *idvec, unsigned pos, uid_t id);
+/* Set the ids in IDVEC to IDS (NUM elements long); delete whatever
+ the previous ids were. */
+error_t idvec_set_ids (struct idvec *idvec, const uid_t *ids, unsigned num);
+
+/* Like idvec_set_ids, but get the new ids from new. */
+error_t idvec_set (struct idvec *idvec, const struct idvec *new);
+
/* Adds each id in the vector IDS (NUM elements long) to IDVEC, as if with
idvec_add_new(). */
-error_t idvec_merge_ids (struct idvec *idvec, uid_t *ids, unsigned num);
+error_t idvec_merge_ids (struct idvec *idvec, const uid_t *ids, unsigned num);
/* Adds each id from NEW to IDVEC, as if with idvec_add_new(). */
-error_t idvec_merge (struct idvec *idvec, struct idvec *new);
+error_t idvec_merge (struct idvec *idvec, const struct idvec *new);
-/* Remove any occurances of ID in IDVEC after position POS> Returns true if
+/* Remove all ids in SUB from IDVEC, returning true if anything was done. */
+int idvec_subtract (struct idvec *idvec, const struct idvec *sub);
+
+/* Remove all ids from IDVEC that are *not* in KEEP, returning true if
+ anything was changed. */
+int idvec_keep (struct idvec *idvec, const struct idvec *keep);
+
+/* Remove any occurrences of ID in IDVEC after position POS> Returns true if
anything was done. */
int idvec_remove (struct idvec *idvec, unsigned pos, uid_t id);
/* Deleted the id at position POS in IDVEC. */
void idvec_delete (struct idvec *idvec, unsigned pos);
-/* Insert ID at position POS in IDVEC, remoint any instances of ID previously
+/* Insert ID at position POS in IDVEC, remove any instances of ID previously
present at POS or after. ENOMEM is returned if there's not enough memory,
otherwise 0. */
error_t idvec_insert_only (struct idvec *idvec, unsigned pos, uid_t id);
-/* EFF and AVAIL should be idvec's corresponding to a processes effective and
- available ids. ID replaces the first id in EFF, and what it replaces is
- preserved by adding it to AVAIL (if not already present). If SECURE is
- non-NULL, and ID was not previously present in either EFF or AVAIL, then
- *SECURE is set to true. ENOMEM is returned if a malloc fails, otherwise
- 0. The return parameters are only touched if this call succeeds. */
+/* EFF and AVAIL should be idvec's corresponding to a process's
+ effective and available ids. ID replaces the first id in EFF, and,
+ if there are any IDs in AVAIL, replaces the second ID in AVAIL;
+ what it replaces in any case is preserved by adding it to AVAIL if
+ not already present. In addition, the If SECURE is non-NULL, and
+ ID was not previously present in either EFF or AVAIL, then *SECURE
+ is set to true. ENOMEM is returned if a malloc fails, otherwise 0.
+ The return parameters are only touched if this call succeeds. */
error_t idvec_setid (struct idvec *eff, struct idvec *avail, uid_t id,
int *secure);
@@ -117,4 +180,58 @@ error_t idvec_merge_auth (struct idvec *eff_uids, struct idvec *avail_uids,
struct idvec *eff_gids, struct idvec *avail_gids,
auth_t auth);
+/* Add to GIDS those group ids implied by the users in UIDS. */
+error_t idvec_merge_implied_gids (struct idvec *gids, const struct idvec *uids);
+
+/* Make sure the user has the right to the ids in UIDS and GIDS, given that
+ we know he already has HAVE_UIDS and HAVE_GIDS, asking for passwords (with
+ GETPASS_FN) where necessary; any of the arguments may be 0, which is
+ treated the same as if they were empty. 0 is returned if access should be
+ allowed, otherwise EINVAL if an incorrect password was entered, or an
+ error relating to resource failure. Any uid/gid < 0 will be guaranteed to
+ fail regardless of what the user types. GETPASS_FN should ask for a
+ password from the user, and return it in malloced storage; it defaults to
+ using the standard libc function getpass. If VERIFY_FN is 0, then the
+ users password will be encrypted with crypt and compared with the
+ password/group entry's encrypted password, otherwise, VERIFY_FN will be
+ called to check the entered password's validity; it should return 0 if the
+ given password is correct, or an error code. The common arguments to
+ GETPASS_FN and VERIFY_FN are: ID, the user/group id; IS_GROUP, true if its
+ a group, or false if a user; PWD_OR_GRP, a pointer to either the passwd or
+ group entry for ID, and HOOK, containing the appropriate hook passed into
+ idvec_verify. */
+error_t idvec_verify (const struct idvec *uids, const struct idvec *gids,
+ const struct idvec *have_uids,
+ const struct idvec *have_gids,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *getpass_hook,
+ error_t (*verify_fn) (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *verify_hook);
+
+/* Return a string representation of the ids in IDVEC, each id separated by
+ the string SEP (default ","). SHOW_VALUES and SHOW_NAMES reflect how each
+ id is printed (if SHOW_NAMES is true values are used where names aren't
+ available); if both are true, the `VALUE(NAME)' format is used.
+ ID_NAME_FN is used to map each id to a name; it should return a malloced
+ string, which will be freed here. The empty string is returned for an
+ empty list, and 0 for an allocation error. */
+char *idvec_rep (const struct idvec *idvec,
+ int show_values, int show_names,
+ char *(*id_name_fn) (uid_t id),
+ const char *sep);
+
+/* Like idvec_rep, mapping ids to user names. */
+char *idvec_uids_rep (const struct idvec *idvec,
+ int show_values, int show_names,
+ const char *sep);
+
+/* Like idvec_rep, mapping ids to group names. */
+char *idvec_gids_rep (const struct idvec *idvec,
+ int show_values, int show_names,
+ const char *sep);
+
#endif /* __IDVEC_H__ */
diff --git a/libshouldbeinlibc/localhost.c b/libshouldbeinlibc/localhost.c
index f0c67541..f0225116 100644
--- a/libshouldbeinlibc/localhost.c
+++ b/libshouldbeinlibc/localhost.c
@@ -39,18 +39,27 @@ localhost ()
errno = 0;
if (buf) {
+ char *new;
buf_len += buf_len;
- buf = realloc (buf, buf_len);
+ new = realloc (buf, buf_len);
+ if (! new)
+ {
+ free (buf);
+ buf = 0;
+ errno = ENOMEM;
+ return 0;
+ }
+ else
+ buf = new;
} else {
buf_len = 128; /* Initial guess */
buf = malloc (buf_len);
+ if (! buf)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
}
-
- if (! buf)
- {
- errno = ENOMEM;
- return 0;
- }
} while ((gethostname(buf, buf_len) == 0 && !memchr (buf, '\0', buf_len))
|| errno == ENAMETOOLONG);
diff --git a/libshouldbeinlibc/maptime-funcs.c b/libshouldbeinlibc/maptime-funcs.c
new file mode 100644
index 00000000..080e3ae6
--- /dev/null
+++ b/libshouldbeinlibc/maptime-funcs.c
@@ -0,0 +1,5 @@
+#define MAPTIME_DEFINE_EI
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include "maptime.h"
diff --git a/libshouldbeinlibc/maptime.c b/libshouldbeinlibc/maptime.c
index 95ae64cb..bc750458 100644
--- a/libshouldbeinlibc/maptime.c
+++ b/libshouldbeinlibc/maptime.c
@@ -1,6 +1,6 @@
/* Support for mach's mapped time
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -18,6 +18,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <fcntl.h>
#include <hurd.h>
#include <mach.h>
#include <device/device.h>
@@ -34,11 +35,11 @@ maptime_map (int use_mach_dev, char *dev_name,
volatile struct mapped_time_value **mtime)
{
error_t err;
- device_t device;
- mach_port_t mobj;
+ mach_port_t memobj;
if (use_mach_dev)
{
+ device_t device;
mach_port_t device_master;
err = get_privileged_ports (0, &device_master);
@@ -47,72 +48,32 @@ maptime_map (int use_mach_dev, char *dev_name,
err = device_open (device_master, 0, dev_name ?: "time", &device);
mach_port_deallocate (mach_task_self (), device_master);
}
+
+ err = device_map (device, VM_PROT_READ, 0, sizeof *mtime, &memobj, 0);
}
else
{
- mach_msg_type_number_t data_len = 100;
- mach_msg_type_number_t num_ints = 10, num_ports = 10, num_offsets = 10;
- int _ints[num_ints], *ints = _ints;
- mach_port_t _ports[num_ports], *ports = _ports;
- off_t _offsets[num_offsets], *offsets = _offsets;
- char _data[data_len], *data = _data;
- file_t node = file_name_lookup (dev_name ?: "/dev/time", 0, 0);
+ mach_port_t wr_memobj;
+ file_t node = file_name_lookup (dev_name ?: "/dev/time", O_RDONLY, 0);
if (node == MACH_PORT_NULL)
return errno;
- err = file_get_storage_info (node, &ports, &num_ports, &ints, &num_ints,
- &offsets, &num_offsets, &data, &data_len);
-
- if (! err)
- {
- int i;
-
- if (num_ints >= 6 && ints[0] == STORAGE_DEVICE)
- /* This a device. */
- if (num_ports != 1)
- err = EGRATUITOUS;
- else if (! MACH_PORT_VALID (ports[0]))
- err = EPERM; /* Didn't pass back the device port. XXX */
- else
- {
- device = ports[0];
- ports[0] = MACH_PORT_NULL; /* Don't deallocate here. */
- }
- else
- err = ENODEV; /* Not admitting to being a device. XXX */
-
- /* Deallocate any ports we got back. */
- for (i = 0; i < num_ports; i++)
- if (MACH_PORT_VALID (ports[i]))
- mach_port_deallocate (mach_task_self (), ports[i]);
-
- /* Deallocate any out of line vectors return by gsi. */
-#define DISCARD_MEM(v, vl, b) \
- if (vl && v != b) \
- vm_deallocate (mach_task_self (), (vm_address_t)v, vl * sizeof *v);
- DISCARD_MEM (ints, num_ints, _ints);
- DISCARD_MEM (offsets, num_offsets, _offsets);
- DISCARD_MEM (ports, num_ports, _ports);
- DISCARD_MEM (data, data_len, _data);
- }
+ err = io_map (node, &memobj, &wr_memobj);
+ if (!err && wr_memobj != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), wr_memobj);
mach_port_deallocate (mach_task_self (), node);
}
- if (err)
- return err;
-
- err = device_map (device, VM_PROT_READ, 0, sizeof *mtime, &mobj, 0);
if (! err)
{
+ *mtime = 0;
err =
vm_map (mach_task_self (), (vm_address_t *)mtime, sizeof *mtime, 0, 1,
- mobj, 0, 0, VM_PROT_READ, VM_PROT_READ, VM_INHERIT_NONE);
- mach_port_deallocate (mach_task_self (), mobj);
+ memobj, 0, 0, VM_PROT_READ, VM_PROT_READ, VM_INHERIT_NONE);
+ mach_port_deallocate (mach_task_self (), memobj);
}
- mach_port_deallocate (mach_task_self (), device);
-
return err;
}
diff --git a/libshouldbeinlibc/maptime.h b/libshouldbeinlibc/maptime.h
index 244cbcf1..947ad640 100644
--- a/libshouldbeinlibc/maptime.h
+++ b/libshouldbeinlibc/maptime.h
@@ -1,8 +1,8 @@
/* Support for mach's mapped time
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000, 2007 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -22,17 +22,30 @@
#define __MAPTIME_H__
#include <mach/time_value.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <features.h>
+
+#ifdef MAPTIME_DEFINE_EI
+#define MAPTIME_EI
+#else
+#define MAPTIME_EI __extern_inline
+#endif
/* Return the mach mapped time page in MTIME. If USE_MACH_DEV is false, then
- the hurd uptime device DEV_NAME, or "/dev/uptime" if DEV_NAME is 0, is
+ the hurd time device DEV_NAME, or "/dev/time" if DEV_NAME is 0, is
used. If USE_MACH_DEV is true, the mach device DEV_NAME, or "time" if
- DEV_NAME is 0, is used; this is a privileged operation. The mapped uptime
- may be converted to a struct timeval at any time using read_uptime. */
+ DEV_NAME is 0, is used; this is a privileged operation. The mapped time
+ may be converted to a struct timeval at any time using maptime_read. */
error_t maptime_map (int use_mach_dev, char *dev_name,
volatile struct mapped_time_value **mtime);
+extern void maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv);
+
+#if defined(__USE_EXTERN_INLINES) || defined(MAPTIME_DEFINE_EI)
+
/* Read the current time from MTIME into TV. This should be very fast. */
-static inline void
+MAPTIME_EI void
maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv)
{
do
@@ -43,4 +56,6 @@ maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv)
while (tv->tv_sec != mtime->check_seconds);
}
+#endif /* Use extern inlines. */
+
#endif /* __MAPTIME_H__ */
diff --git a/libshouldbeinlibc/options.c b/libshouldbeinlibc/options.c
deleted file mode 100644
index 5f719616..00000000
--- a/libshouldbeinlibc/options.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/* Hierarchial options parsing, layered over getopt
-
- Copyright (C) 1995 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h> /* for CHAR_BIT */
-#include <getopt.h>
-#include <cthreads.h>
-
-#include "options.h"
-
-#define EOF (-1)
-
-/* The number of bits we steal in a long-option value for our own use. */
-#define GROUP_BITS CHAR_BIT
-
-/* The number of bits available for the user value. */
-#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
-#define USER_MASK ((1 << USER_BITS) - 1)
-
-/* ---------------------------------------------------------------- */
-
-/* Returns the offset into LONG_OPTIONS of a long option with called NAME, or
- -1 if none is found. Passing NULL as NAME will return the number of
- options. */
-static int
-find_long_option (struct option *long_options, const char *name)
-{
- struct option *l = long_options;
- while (l->name != NULL)
- if (name != NULL && strcmp (l->name, name) == 0)
- return l - long_options;
- else
- l++;
- if (name == NULL)
- return l - long_options;
- else
- return -1;
-}
-
-/* ---------------------------------------------------------------- */
-
-/* Used to regulate access to the getopt routines, which are non-reentrant. */
-static struct mutex getopt_lock = MUTEX_INITIALIZER;
-
-/* Parse the options strings in ARGC & ARGV according to the options in
- OPTIONS. FLAGS is one of the OPTIONS_ flags above. If OPTIND is
- non-NULL, the index in ARGV of the first unparsed option is returned in
- it. If an unknown option is present, EINVAL is returned; if some parser
- routine returned a non-zero value, it is returned; otherwise 0 is
- returned. */
-error_t
-options_parse (struct options *options,
- int argc, char **argv,
- unsigned flags, int *arg_index)
-{
- int opt;
- struct options *o;
- /* SHORT_OPTS is the getopt short options string for the union of all the
- groups of options. */
- char *short_opts;
- /* GROUP_SHORT_STARTS is an array pointing to the part of SHORT_OPTS
- corresponding to each different group of options. We use it to
- determine from which groupa particular short options is from. */
- char **group_short_starts;
- /* LONG_OPTS is the array of getop long option structures for the union of
- all the groups of options. */
- struct option *long_opts;
- error_t err = 0;
-
- /* Find the merged set of short options. */
- {
- char *short_end;
- int short_len = (flags & OPTIONS_PARSE_ARGS) ? 1 : 0;
- int num_groups = 0, group;
-
- /* Find the (maximum) amount of space necessary to store all combined
- short options, plus the number of options groups in the chain. */
- for (o = options; o != NULL; o = o->parent)
- {
- num_groups++;
- short_len += strlen (o->short_options);
- }
-
- short_opts = short_end = alloca (short_len + 1);
- if (flags & OPTIONS_PARSE_ARGS)
- *short_end++ = '-'; /* Tell getopt we want to do this. */
- *short_end = '\0';
-
- group_short_starts = alloca (num_groups * sizeof (char *));
-
- for (o = options, group = 0; o != NULL; o = o->parent, group++)
- {
- char *s;
-
- group_short_starts[group] = short_end;
-
- for (s = o->short_options; *s != '\0'; s++)
- /* We add *S to our set of short options only if it hasn't already
- been added by some previous group. */
- if (*s != ':' && !index (short_opts, *s))
- {
- *short_end++ = *s;
- /* Copy all the colon modifiers following the option. */
- while (s[1] == ':')
- *short_end++ = *++s;
- *short_end = '\0';
- }
- }
- }
-
- /* Find the merged set of long options, with keys appropiately prefixed. */
- {
- struct option *long_end;
- int group;
- int long_len = 0;
-
- for (o = options; o != NULL; o = o->parent)
- long_len += find_long_option (o->long_options, NULL);
-
- long_opts = long_end = alloca ((long_len + 1) * sizeof (struct option));
- long_end->name = NULL;
-
- /* Note that GROUP starts at 1 because 0 is for short options. */
- for (o = options, group = 1; o != NULL; o = o->parent, group++)
- {
- struct option *l;
- for (l = o->long_options; l->name != NULL; l++)
- /* Only add the long option L if it hasn't been already. */
- if (find_long_option (long_opts, l->name) < 0)
- {
- *long_end = *l;
- if (long_end->flag == NULL)
- /* In the case where a long option returns a key from getopt,
- we add a disambiguating code to all the user's values
- (which is removed before we actually call the function to
- parse the value); this means that the user loses use of
- the high 8 bits in all his values (the sign of the lower
- bits is preserved however)... */
- long_end->val = (l->val & USER_MASK) + (group << USER_BITS);
- /* Keep the LONG_OPTS list terminated. */
- (++long_end)->name = NULL;
- }
- }
- }
-
- /* Getopt is (currently) non-reentrant. */
- mutex_lock (&getopt_lock);
-
- /* Tell getopt to initialize. */
- optind = 0;
-
- if (flags & OPTIONS_PRINT_ERRS)
- opterr = 1; /* Print error messages. */
- else
- {
- opterr = 0;
- if (!(flags & OPTIONS_SKIP_ARG0))
- /* getopt always skips ARGV[0], so we have to fake it out. As long
- as opterr is 0, then it shouldn't actually try to access it. */
- argv--, argc++;
- }
-
- /* Now use getopt on our coalesced options lists. */
- while ((opt = getopt_long (argc, argv, short_opts, long_opts, 0)) != EOF)
- {
- int group = opt >> USER_BITS;
-
- err = EINVAL; /* until otherwise asserted */
-
- if (opt == 1)
- /* A non-option argument; try each parser in turn. */
- for (o = options; o != NULL && err == EINVAL; o = o->parent)
- err = (*o->parser)(0, optarg);
- else if (group == 0)
- /* A short option. */
- {
- /* By comparing OPT's position in SHORT_OPTS to the various
- starting positions in GROUP_SHORT_STARTS, we can determine which
- group OPT came from. */
- char *short_index = index (short_opts, opt);
- if (short_index)
- for (o = options, group = 0; o != NULL; o = o->parent, group++)
- if (o->parent == NULL
- || group_short_starts[group + 1] > short_index)
- {
- err = (*o->parser)(opt, optarg);
- break;
- }
- }
- else
- /* A long option. */
- for (o = options; o != NULL; o = o->parent)
- if (--group == 0)
- {
- /* We use shifts instead of masking for extracting the user value
- in order to preserve the sign. */
- err = (*o->parser)(((opt << GROUP_BITS) >> GROUP_BITS), optarg);
- break;
- }
-
- if (err)
- break;
- }
-
- if (arg_index != NULL)
- *arg_index = optind;
-
- mutex_unlock (&getopt_lock);
-
- return err;
-}
diff --git a/libshouldbeinlibc/options.h b/libshouldbeinlibc/options.h
deleted file mode 100644
index 46651add..00000000
--- a/libshouldbeinlibc/options.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Hierarchial options parsing, layered over getopt
-
- Copyright (C) 1995 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
-
- 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef __OPTIONS_H__
-#define __OPTIONS_H__
-
-#include <errno.h>
-#include <getopt.h>
-
-/* An options structure contains a set of getopt options declarations, a
- function to deal with getting one, and an optional pointer to another
- options structure. When actually parsing options, getopt is called with
- the union of all the options structures chained together through their
- PARENT pointers, with conflicts being resolved in favor of the first
- occurance in the chain. */
-struct options
-{
- /* The getopt-style short options string for this group of options. */
- char *short_options;
- /* An array of getopt-style long-options structures. */
- struct option *long_options;
-
- /* What to do with an option from this structure. KEY is either the short
- option letter, or the final member of the long-option entry, as returned
- by getopt, and ARG is the value of OPTARG. If a non-zero value is
- returned, then parsing is stopped immediately, and that value is
- returned from options_parse(). */
- error_t (*parser)(int key, char *arg);
-
- /* The next member in this options chain. */
- struct options *parent;
-};
-
-/* Flags for options_parse: */
-
-/* Ignore the first element of ARGV. Useful for program command lines. */
-#define OPTIONS_SKIP_ARG0 0x1
-
-/* Print error messages for unknown options to stderr; if this flag is set,
- OPTIONS_SKIP_ARG0 is ignored, as ARGV[0] is used as the program name in
- the error messages. */
-#define OPTIONS_PRINT_ERRS 0x2
-
-/* Parse non-option args as well, similarly to getopt, by calling the parse
- function with a key of 0, and the actual arg as the value. Since it's
- impossible to know which parse function wants to handle it, each one is
- called in turn, until one returns 0 or an error other than EINVAL. */
-#define OPTIONS_PARSE_ARGS 0x4
-
-
-/* Parse the options strings in ARGC & ARGV according to the options in
- OPTIONS. FLAGS is one of the OPTIONS_ flags above. If ARG_INDEX is
- non-NULL, the index in ARGV of the first unparsed option is returned in
- it. If an unknown option is present, EINVAL is returned; if some parser
- routine returned a non-zero value, it is returned; otherwise 0 is
- returned. */
-error_t options_parse (struct options *options, int argc, char **argv,
- unsigned flags, int *arg_index);
-
-#endif /* __OPTIONS_H__ */
diff --git a/libshouldbeinlibc/portinfo.c b/libshouldbeinlibc/portinfo.c
index cb4e9605..e6305c6e 100644
--- a/libshouldbeinlibc/portinfo.c
+++ b/libshouldbeinlibc/portinfo.c
@@ -1,8 +1,7 @@
/* Print information about a task's ports
- Copyright (C) 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Copyright (C) 1996,98,99,2002 Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -18,6 +17,9 @@
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 <sys/mman.h>
+
#include "portinfo.h"
/* Prints info about NAME in TASK to STREAM, in a way described by the flags
@@ -41,7 +43,7 @@ print_port_info (mach_port_t name, mach_port_type_t type, task_t task,
mach_port_urefs_t refs;
error_t err = mach_port_get_refs (task, name, right, &refs);
if (! err)
- fprintf (stream, " (refs: %u)", refs);
+ fprintf (stream, " (refs: %zu)", refs);
}
if (type == 0)
@@ -51,7 +53,7 @@ print_port_info (mach_port_t name, mach_port_type_t type, task_t task,
return err;
}
- fprintf (stream, hex_names ? "%#6x: " : "%6d: ", name);
+ fprintf (stream, hex_names ? "%#6zx: " : "%6zd: ", name);
if (type & MACH_PORT_TYPE_RECEIVE)
{
@@ -66,15 +68,15 @@ print_port_info (mach_port_t name, mach_port_type_t type, task_t task,
fprintf (stream, " (");
if (status.mps_pset != MACH_PORT_NULL)
fprintf (stream,
- hex_names ? "port-set: %#x, " : "port-set: %d, ",
+ hex_names ? "port-set: %#zx, " : "port-set: %zd, ",
status.mps_pset);
- fprintf (stream, "seqno: %u", status.mps_seqno);
+ fprintf (stream, "seqno: %zu", status.mps_seqno);
if (status.mps_mscount)
- fprintf (stream, ", ms-count: %u", status.mps_mscount);
+ fprintf (stream, ", ms-count: %zu", status.mps_mscount);
if (status.mps_qlimit != MACH_PORT_QLIMIT_DEFAULT)
- fprintf (stream, ", qlimit: %u", status.mps_qlimit);
+ fprintf (stream, ", qlimit: %zu", status.mps_qlimit);
if (status.mps_msgcount)
- fprintf (stream, ", msgs: %u", status.mps_msgcount);
+ fprintf (stream, ", msgs: %zu", status.mps_msgcount);
fprintf (stream, "%s%s%s)",
status.mps_srights ? ", send-rights" : "",
status.mps_pdrequest ? ", pd-req" : "",
@@ -112,17 +114,19 @@ print_port_info (mach_port_t name, mach_port_type_t type, task_t task,
error_t err =
mach_port_get_set_status (task, name, &members, &members_len);
if (! err)
- if (members_len == 0)
- fprintf (stream, " (empty)");
- else
- {
- fprintf (stream, hex_names ? " (%#x" : " (%u", members[0]);
- for (i = 1; i < members_len; i++)
- fprintf (stream, hex_names ? ", %#x" : ", %u", members[i]);
- fprintf (stream, ")");
- vm_deallocate (mach_task_self (), (vm_address_t)members,
- members_len * sizeof *members);
- }
+ {
+ if (members_len == 0)
+ fprintf (stream, " (empty)");
+ else
+ {
+ fprintf (stream, hex_names ? " (%#zx" : " (%zu", members[0]);
+ for (i = 1; i < members_len; i++)
+ fprintf (stream, hex_names ? ", %#zx" : ", %zu",
+ members[i]);
+ fprintf (stream, ")");
+ munmap ((caddr_t) members, members_len * sizeof *members);
+ }
+ }
}
}
putc ('\n', stream);
@@ -147,10 +151,8 @@ print_task_ports_info (task_t task, mach_port_type_t only,
if (types[i] & only)
print_port_info (names[i], types[i], task, show, stream);
- vm_deallocate (mach_task_self (),
- (vm_address_t)names, names_len * sizeof *names);
- vm_deallocate (mach_task_self (),
- (vm_address_t)types, types_len * sizeof *types);
+ munmap ((caddr_t) names, names_len * sizeof *names);
+ munmap ((caddr_t) types, types_len * sizeof *types);
return 0;
}
diff --git a/libshouldbeinlibc/portinfo.h b/libshouldbeinlibc/portinfo.h
index bef2fa00..143c2898 100644
--- a/libshouldbeinlibc/portinfo.h
+++ b/libshouldbeinlibc/portinfo.h
@@ -1,6 +1,6 @@
/* Print information about a task's ports
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1999 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
diff --git a/libshouldbeinlibc/portxlate.c b/libshouldbeinlibc/portxlate.c
index 07b2fc03..291bcf3a 100644
--- a/libshouldbeinlibc/portxlate.c
+++ b/libshouldbeinlibc/portxlate.c
@@ -1,8 +1,7 @@
/* Translate mach port names between two tasks
- Copyright (C) 1996 Free Software Foundation, Inc.
-
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Copyright (C) 1996,99,2002 Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -19,12 +18,14 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <malloc.h>
+#include <sys/types.h>
+#include <sys/mman.h>
#include "portxlate.h"
/* Return a new port name translator translating names between FROM_TASK and
TO_TASK, in XLATOR, or an error. */
-error_t
+error_t
port_name_xlator_create (mach_port_t from_task, mach_port_t to_task,
struct port_name_xlator **xlator)
{
@@ -59,12 +60,10 @@ port_name_xlator_create (mach_port_t from_task, mach_port_t to_task,
}
else
{
- vm_deallocate (mach_task_self (),
- (vm_address_t)x->to_names,
- x->to_names_len * sizeof (mach_port_t));
- vm_deallocate (mach_task_self (),
- (vm_address_t)x->to_types,
- x->to_types_len * sizeof (mach_port_type_t));
+ munmap ((caddr_t) x->to_names,
+ x->to_names_len * sizeof (mach_port_t));
+ munmap ((caddr_t) x->to_types,
+ x->to_types_len * sizeof (mach_port_type_t));
err = ENOMEM;
}
}
@@ -88,12 +87,8 @@ port_name_xlator_free (struct port_name_xlator *x)
mach_port_deallocate (mach_task_self (), x->ports[i]);
free (x->ports);
- vm_deallocate (mach_task_self (),
- (vm_address_t)x->to_names,
- x->to_names_len * sizeof (mach_port_t));
- vm_deallocate (mach_task_self (),
- (vm_address_t)x->to_types,
- x->to_types_len * sizeof (mach_port_type_t));
+ munmap ((caddr_t) x->to_names, x->to_names_len * sizeof (mach_port_t));
+ munmap ((caddr_t) x->to_types, x->to_types_len * sizeof (mach_port_type_t));
mach_port_deallocate (mach_task_self (), x->to_task);
mach_port_deallocate (mach_task_self (), x->from_task);
@@ -112,8 +107,8 @@ port_name_xlator_xlate (struct port_name_xlator *x,
error_t err;
mach_port_t port;
mach_msg_type_number_t i;
- mach_port_type_t aquired_type;
- mach_port_type_t valid_to_types;
+ mach_msg_type_name_t aquired_type;
+ mach_msg_type_name_t valid_to_types;
if (from_type == 0)
{
@@ -130,7 +125,7 @@ port_name_xlator_xlate (struct port_name_xlator *x,
return EKERN_INVALID_RIGHT;
/* Translate the name FROM, in FROM_TASK's namespace into our namespace. */
- err =
+ err =
mach_port_extract_right (x->from_task, from,
((from_type & MACH_PORT_TYPE_RECEIVE)
? MACH_MSG_TYPE_MAKE_SEND
diff --git a/libshouldbeinlibc/timefmt.c b/libshouldbeinlibc/timefmt.c
index da4ccde0..aa8965b7 100644
--- a/libshouldbeinlibc/timefmt.c
+++ b/libshouldbeinlibc/timefmt.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
+#include <time.h>
#include "timefmt.h"
diff --git a/libshouldbeinlibc/ugids-argp.c b/libshouldbeinlibc/ugids-argp.c
new file mode 100644
index 00000000..dc076d27
--- /dev/null
+++ b/libshouldbeinlibc/ugids-argp.c
@@ -0,0 +1,175 @@
+/* Parse user and group ids
+
+ Copyright (C) 1997, 1999, 2008 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 <string.h>
+#include <hurd.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <argp.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "ugids.h"
+
+#define OA OPTION_ARG_OPTIONAL
+
+static const struct argp_option options[] =
+{
+ {"user", 'u', "USER", 0, "Add USER to the effective uids"},
+ {"avail-user",'U', "USER", 0, "Add USER to the available uids"},
+ {"group", 'g', "GROUP", 0, "Add GROUP to the effective groups"},
+ {"avail-group",'G',"GROUP", 0, "Add GROUP to the available groups"},
+ { 0 }
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ char id_lookup_buf[1024];
+ struct ugids_argp_params *params = state->input;
+ struct ugids *ugids = params->ugids;
+
+ switch (key)
+ {
+ uid_t uid;
+
+ case 'u':
+ case 'U':
+ case ARGP_KEY_ARG:
+ case ARGP_KEY_END:
+ if (key == ARGP_KEY_ARG && !params->parse_user_args)
+ /* Let someone else parse this argument. */
+ return ARGP_ERR_UNKNOWN;
+
+ if (key == ARGP_KEY_END)
+ {
+ if (ugids_is_empty (ugids))
+ {
+ if (params->default_user >= 0)
+ uid = params->default_user;
+ else if (params->require_ids)
+ {
+ argp_error (state, "No ids specified");
+ return EINVAL;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else if (isdigit (*arg))
+ uid = atoi (arg);
+ else if (strcmp (arg, "-") == 0)
+ break;
+ else
+ {
+ struct passwd _pw, *pw;
+ int err;
+ err = getpwnam_r (arg, &_pw, id_lookup_buf,
+ sizeof id_lookup_buf, &pw);
+ if (err == 0)
+ {
+ if (pw == NULL)
+ {
+ argp_failure (state, 10, 0, "%s: Unknown user", arg);
+ return EINVAL;
+ }
+
+ uid = pw->pw_uid;
+ }
+ else
+ {
+ argp_failure (state, 12, err,
+ "Could not get uid for user: %s", arg);
+ return err;
+ }
+ }
+
+ if (key == ARGP_KEY_ARG || key == ARGP_KEY_END)
+ {
+ /* A user arg, which means add the user, and any appropriate
+ groups. */
+ if (!params->user_args_are_effective
+ && !params->user_args_are_available)
+ return ugids_set_posix_user (ugids, uid);
+ else
+ {
+ error_t err = 0;
+ if (params->user_args_are_effective)
+ err = ugids_add_user (ugids, uid, 0);
+ if (!err && params->user_args_are_available)
+ err = ugids_add_user (ugids, uid, 1);
+ return err;
+ }
+ }
+ else
+ /* Add an individual specific effective/auxiliary uid. */
+ return ugids_add_uid (ugids, uid, key == 'U');
+
+ case 'g':
+ case 'G':
+ if (isdigit (*arg))
+ return ugids_add_gid (ugids, atoi (arg), key == 'G');
+ else
+ {
+ struct group _gr, *gr;
+ int err = getgrnam_r (arg, &_gr, id_lookup_buf,
+ sizeof id_lookup_buf, &gr);
+ if (err == 0)
+ {
+ if (gr == NULL)
+ {
+ argp_failure (state, 11, 0, "%s: Unknown group", arg);
+ return EINVAL;
+ }
+
+ return ugids_add_gid (ugids, gr->gr_gid, key == 'G');
+ }
+ else
+ {
+ argp_failure (state, 13, err,
+ "Could not get gid for group: %s", arg);
+ return err;
+ }
+ }
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+/* Filtering of help output strings for UGIDS_ARGP. */
+static char *
+help_filter (int key, const char *text, void *input)
+{
+ struct ugids_argp_params *params = input;
+
+ /* Describe the optional behavior of parsing normal args as ugids. */
+ if (key == ARGP_KEY_HELP_ARGS_DOC && params->parse_user_args)
+ return strdup ("[USER...]");
+
+ return (char *)text;
+}
+
+/* A parser for selecting a set of ugids. */
+struct argp ugids_argp = { options, parse_opt, 0, 0, 0, help_filter };
diff --git a/libshouldbeinlibc/ugids-auth.c b/libshouldbeinlibc/ugids-auth.c
new file mode 100644
index 00000000..d7ec9daa
--- /dev/null
+++ b/libshouldbeinlibc/ugids-auth.c
@@ -0,0 +1,53 @@
+/* Translate user and group ids to/from auth ports
+
+ 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 <hurd.h>
+
+#include "ugids.h"
+
+/* Make an auth port from UGIDS and return it in AUTH, using authority in
+ both the auth port FROM and the current auth port. */
+error_t
+ugids_make_auth (const struct ugids *ugids,
+ const auth_t *from, size_t num_from,
+ auth_t *auth)
+{
+ auth_t cur_auth = getauth ();
+ error_t err =
+ auth_makeauth (cur_auth, (auth_t *)from, MACH_MSG_TYPE_COPY_SEND, num_from,
+ ugids->eff_uids.ids, ugids->eff_uids.num,
+ ugids->avail_uids.ids, ugids->avail_uids.num,
+ ugids->eff_gids.ids, ugids->eff_gids.num,
+ ugids->avail_gids.ids, ugids->avail_gids.num,
+ auth);
+ mach_port_deallocate (mach_task_self (), cur_auth);
+ return err;
+}
+
+/* Merge the ids from the auth port AUTH into UGIDS. */
+error_t
+ugids_merge_auth (struct ugids *ugids, auth_t auth)
+{
+ return
+ idvec_merge_auth (&ugids->eff_uids, &ugids->avail_uids,
+ &ugids->eff_gids, &ugids->avail_gids,
+ auth);
+}
diff --git a/libshouldbeinlibc/argp-pv.c b/libshouldbeinlibc/ugids-imply.c
index e6e87adb..9c2a8a2c 100644
--- a/libshouldbeinlibc/argp-pv.c
+++ b/libshouldbeinlibc/ugids-imply.c
@@ -1,17 +1,15 @@
-/* Default definition for ARGP_PROGRAM_VERSION
+/* Calculate implied group ids from user ids
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1997 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
- This file is part of the GNU Hurd.
-
- The GNU Hurd is free software; you can redistribute it and/or
+ 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.
- The GNU Hurd is distributed in the hope that it will be useful, but
+ 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.
@@ -20,8 +18,18 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* If set by the user program to a non-zero value, then a default option
- --version is added (unless the ARGP_NO_HELP flag is used), which will
- print this this string followed by a newline and exit (unless the
- ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
-char *argp_program_version = 0;
+#include <stdlib.h>
+
+#include "ugids.h"
+
+/* Mark as implied all gids in UGIDS that can be implied from its uids. */
+error_t
+ugids_imply_all (struct ugids *ugids)
+{
+ error_t err;
+ err = idvec_merge_implied_gids (&ugids->imp_eff_gids, &ugids->eff_uids);
+ if (! err)
+ err =
+ idvec_merge_implied_gids (&ugids->imp_avail_gids, &ugids->avail_uids);
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids-merge.c b/libshouldbeinlibc/ugids-merge.c
new file mode 100644
index 00000000..924e1ed9
--- /dev/null
+++ b/libshouldbeinlibc/ugids-merge.c
@@ -0,0 +1,109 @@
+/* Merging of ugids
+
+ 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 "ugids.h"
+
+static error_t
+_merge_gids (struct idvec *gids, struct idvec *gids_imp,
+ const struct idvec *new, const struct idvec *new_imp)
+{
+ error_t err;
+ /* Gids that exist in both GIDS and NEW can only be implied in the result
+ if they are implied in both; here GIDS_STRONG and NEW_STRONG contain
+ those gids which shouldn't be implied in the result because they are not
+ in either of the sources. */
+ struct idvec gids_strong = IDVEC_INIT;
+ struct idvec new_strong = IDVEC_INIT;
+
+ err = idvec_set (&gids_strong, gids);
+ if (! err)
+ err = idvec_set (&new_strong, new);
+ if (! err)
+ {
+ idvec_subtract (&gids_strong, gids_imp);
+ idvec_subtract (&new_strong, new_imp);
+
+ err = idvec_merge (gids, new);
+ if (! err)
+ {
+ err = idvec_merge (gids_imp, new_imp);
+ if (! err)
+ {
+ idvec_subtract (gids_imp, &gids_strong);
+ idvec_subtract (gids_imp, &new_strong);
+ }
+ }
+ }
+
+ idvec_fini (&gids_strong);
+ idvec_fini (&new_strong);
+
+ return err;
+}
+
+/* Add all ids in NEW to UGIDS. */
+error_t
+ugids_merge (struct ugids *ugids, const struct ugids *new)
+{
+ error_t err;
+ err = idvec_merge (&ugids->eff_uids, &new->eff_uids);
+ if (! err)
+ err = idvec_merge (&ugids->avail_uids, &new->avail_uids);
+ if (! err)
+ err = _merge_gids (&ugids->eff_gids, &ugids->imp_eff_gids,
+ &new->eff_gids, &new->imp_eff_gids);
+ if (! err)
+ err = _merge_gids (&ugids->avail_gids, &ugids->imp_avail_gids,
+ &new->avail_gids, &new->imp_avail_gids);
+ return err;
+}
+
+/* Set the ids in UGIDS to those in NEW. */
+error_t
+ugids_set (struct ugids *ugids, const struct ugids *new)
+{
+ idvec_clear (&ugids->eff_uids);
+ idvec_clear (&ugids->eff_gids);
+ idvec_clear (&ugids->avail_uids);
+ idvec_clear (&ugids->avail_gids);
+ idvec_clear (&ugids->imp_eff_gids);
+ idvec_clear (&ugids->imp_avail_gids);
+ return ugids_merge (ugids, new);
+}
+
+/* Save any effective ids in UGIDS by merging them into the available ids,
+ and removing them from the effective ones. */
+error_t
+ugids_save (struct ugids *ugids)
+{
+ error_t err = idvec_merge (&ugids->avail_uids, &ugids->eff_uids);
+ if (! err)
+ err = _merge_gids (&ugids->avail_gids, &ugids->imp_avail_gids,
+ &ugids->eff_gids, &ugids->imp_eff_gids);
+ if (! err)
+ {
+ idvec_clear (&ugids->eff_uids);
+ idvec_clear (&ugids->eff_gids);
+ idvec_clear (&ugids->imp_eff_gids);
+ }
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids-posix.c b/libshouldbeinlibc/ugids-posix.c
new file mode 100644
index 00000000..35d73e32
--- /dev/null
+++ b/libshouldbeinlibc/ugids-posix.c
@@ -0,0 +1,95 @@
+/* Set posix-compatible ugids
+
+ 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 "ugids.h"
+
+/* Install UID into UGIDS as the main user, making sure that the posix
+ `real' and `saved' uid slots are filled in, and similarly add all
+ groups to which UID belongs. */
+error_t
+ugids_set_posix_user (struct ugids *ugids, uid_t uid)
+{
+ error_t err;
+ struct idvec imp_gids = IDVEC_INIT;
+ uid_t uids_ids[] = { uid };
+ struct idvec uids = { uids_ids, 1 };
+
+ error_t update_real (struct idvec *avail_ids, uid_t id)
+ {
+ if (avail_ids->num == 0
+ || !idvec_tail_contains (avail_ids, 1, avail_ids->ids[0]))
+ return idvec_insert (avail_ids, 0, id);
+ else
+ avail_ids->ids[0] = id;
+ return 0;
+ }
+
+ idvec_merge_implied_gids (&imp_gids, &uids);
+
+ /* Try to add UID. */
+ err = idvec_insert_only (&ugids->eff_uids, 0, uid); /* Effective */
+ if (! err)
+ err = update_real (&ugids->avail_uids, uid); /* Real */
+ if (! err)
+ err = idvec_insert_only (&ugids->avail_uids, 1, uid); /* Saved */
+
+ if (!err && imp_gids.num > 0)
+ /* Now do the gids. */
+ {
+ /* The main gid associated with UID (usually from /etc/passwd). */
+ gid_t gid = imp_gids.ids[0];
+ /* True if GID was already an available gid. */
+ int gid_was_avail = idvec_contains (&ugids->avail_gids, gid);
+
+ /* Update the implied sets for the gids: they're implied unless
+ they were present as non-implied gids before. Here we
+ remove existing effective gids from the IMP_GIDS before we
+ added it to the implied sets -- if some of those gids were
+ actually implied, they'll already be present in the implied
+ set. */
+ idvec_subtract (&imp_gids, &ugids->eff_gids);
+
+ /* Now add GID, as effective, real, and saved gids. */
+ if (! err) /* Effective */
+ err = idvec_insert_only (&ugids->eff_gids, 0, gid);
+ if (! err) /* Real */
+ err = update_real (&ugids->avail_gids, gid);
+ if (! err) /* Saved */
+ err = idvec_insert_only (&ugids->avail_gids, 1, gid);
+
+ /* Mark GID as implied in the available gids unless it was already
+ present (in which case its implied status is already settled). */
+ if (!err && !gid_was_avail)
+ err = idvec_add (&ugids->imp_avail_gids, gid);
+
+ /* Add the other implied gids to the end of the effective gids. */
+ if (! err)
+ err = idvec_merge (&ugids->eff_gids, &imp_gids);
+ /* And make them implied. */
+ if (! err)
+ err = idvec_merge (&ugids->imp_eff_gids, &imp_gids);
+ }
+
+ idvec_fini (&imp_gids);
+
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids-rep.c b/libshouldbeinlibc/ugids-rep.c
new file mode 100644
index 00000000..3e6e59d5
--- /dev/null
+++ b/libshouldbeinlibc/ugids-rep.c
@@ -0,0 +1,118 @@
+/* String representation of ugids
+
+ 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 <string.h>
+
+#include "ugids.h"
+
+/* Return a string representation of the ids in UGIDS. SHOW_VALUES and
+ SHOW_NAMES reflect how each id is printed (if SHOW_NAMES is true values
+ are used where names aren't available); if both are true, the
+ `VALUE(NAME)' format is used. ID_SEP, TYPE_SEP, and HDR_SEP contain the
+ strings that separate, respectively, multiple ids of a particular type
+ (default ","), the various types of ids (default ", "), and the name of
+ each type from its ids (default ": "). The empty string is returned for
+ an empty list, and 0 for an allocation error. */
+char *
+ugids_rep (const struct ugids *ugids, int show_values, int show_names,
+ const char *id_sep, const char *type_sep, const char *hdr_sep)
+{
+ size_t type_sep_len, hdr_sep_len;
+ int first = 1;
+ char *rep = 0; /* Result */
+ size_t len = 0; /* Total length of result. */
+ char *euid_rep = 0, *egid_rep = 0, *auid_rep = 0, *agid_rep = 0;
+
+ /* Calculate the rep for NAME, with ids IDS, returning the rep for the ids
+ in REP, and updates LEN to include everything needed by this type (the
+ length of *REP *plus* the length of NAME and any separators). True is
+ returned unless an allocation error occurs. */
+ int type_rep (const char *name, const struct idvec *ids, int is_group,
+ char **rep)
+ {
+ if (ids->num > 0)
+ {
+ if (first)
+ first = 0;
+ else
+ len += type_sep_len;
+ len += strlen (name);
+ len += hdr_sep_len;
+ *rep =
+ (is_group ? idvec_gids_rep : idvec_uids_rep)
+ (ids, show_values, show_names, id_sep);
+ if (*rep)
+ len += strlen (*rep);
+ else
+ return 0;
+ }
+ return 1;
+ }
+ void add_type_rep (char **to, const char *name, const char *rep)
+ {
+ if (rep)
+ {
+ if (first)
+ first = 0;
+ else
+ *to = stpcpy (*to, type_sep);
+ *to = stpcpy (*to, name);
+ *to = stpcpy (*to, hdr_sep);
+ *to = stpcpy (*to, rep);
+ }
+ }
+
+ if (! type_sep)
+ type_sep = ", ";
+ if (! hdr_sep)
+ hdr_sep = ": ";
+
+ type_sep_len = strlen (type_sep);
+ hdr_sep_len = strlen (hdr_sep);
+
+ if (type_rep ("euids", &ugids->eff_uids, 0, &euid_rep)
+ && type_rep ("egids", &ugids->eff_gids, 1, &egid_rep)
+ && type_rep ("auids", &ugids->avail_uids, 0, &auid_rep)
+ && type_rep ("agids", &ugids->avail_gids, 1, &agid_rep))
+ {
+ char *p = malloc (len + 1);
+ if (p)
+ {
+ rep = p;
+ first = 1;
+ add_type_rep (&p, "euids", euid_rep);
+ add_type_rep (&p, "egids", egid_rep);
+ add_type_rep (&p, "auids", auid_rep);
+ add_type_rep (&p, "agids", agid_rep);
+ }
+ }
+
+ if (euid_rep)
+ free (euid_rep);
+ if (egid_rep)
+ free (egid_rep);
+ if (auid_rep)
+ free (auid_rep);
+ if (agid_rep)
+ free (agid_rep);
+
+ return rep;
+}
diff --git a/libshouldbeinlibc/ugids-subtract.c b/libshouldbeinlibc/ugids-subtract.c
new file mode 100644
index 00000000..eecba20e
--- /dev/null
+++ b/libshouldbeinlibc/ugids-subtract.c
@@ -0,0 +1,130 @@
+/* Subtract one set of user and group ids from another
+
+ 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 <stdio.h>
+
+#include "ugids.h"
+
+/* Remove the gids in SUB from those in GIDS, except where they are implied
+ in SUB (as represented by SUB_IMP), but not in GIDS (as represented by
+ GIDS_IMP). */
+static
+error_t _sub_gids (struct idvec *gids, struct idvec *gids_imp,
+ const struct idvec *sub, const struct idvec *sub_imp)
+{
+ error_t err;
+ /* What we'll remove from GIDS. */
+ struct idvec delta = IDVEC_INIT;
+ /* Those implied ids in SUB that we *won't* remove, because they're not
+ also implied in GIDS. */
+ struct idvec delta_suppress = IDVEC_INIT;
+
+ err = idvec_set (&delta, sub);
+ if (! err)
+ err = idvec_set (&delta_suppress, sub_imp);
+ if (! err)
+ {
+ /* Don't suppress those implied ids that are implied in both. */
+ idvec_subtract (&delta_suppress, gids_imp);
+ idvec_subtract (&delta, &delta_suppress);
+
+ /* Actually remove the gids. */
+ idvec_subtract (gids, &delta);
+ }
+
+ idvec_fini (&delta);
+ idvec_fini (&delta_suppress);
+
+ return err;
+}
+
+/* Remove the in SUB from those in GIDS, except where they are implied
+ in SUB (as represented by SUB_IMP), but not in GIDS (as represented by
+ GIDS_IMP). */
+static
+error_t _sub (struct idvec *uids, struct idvec *gids, struct idvec *gids_imp,
+ const struct idvec *sub_uids,
+ const struct idvec *sub_gids, const struct idvec *sub_gids_imp)
+{
+ error_t err;
+ struct idvec new_uids = IDVEC_INIT; /* The set of uids after subtraction. */
+ struct idvec no_sub_gids = IDVEC_INIT; /* Gids we *don't* want to remove
+ from GIDS, despite what's in
+ SUB_GIDS. */
+ struct idvec new_sub_gids = IDVEC_INIT;
+ struct idvec new_sub_gids_imp = IDVEC_INIT;
+
+ err = idvec_set (&new_uids, uids);
+ if (! err)
+ err = idvec_set (&new_sub_gids, sub_gids);
+ if (! err)
+ err = idvec_set (&new_sub_gids_imp, sub_gids_imp);
+ if (! err)
+ {
+ idvec_subtract (&new_uids, sub_uids);
+
+ err = idvec_merge_implied_gids (&no_sub_gids, &new_uids);
+ if (! err)
+ {
+ /* NO_SUB_GIDS is the intersection of implied gids in GIDS,
+ implied gids in SUB_GIDS, and implied gids after the subtraction
+ of uids -- we don't want to remove those implied gids because we
+ can't be sure which uids implied them (as there will be
+ appropriately implicative uids left after the subtraction). */
+ idvec_keep (&no_sub_gids, gids_imp);
+ idvec_keep (&no_sub_gids, sub_gids_imp);
+
+ /* Remove those gids we don't want to subtract. */
+ idvec_subtract (&new_sub_gids, &no_sub_gids);
+ idvec_subtract (&new_sub_gids_imp, &no_sub_gids);
+
+ /* Do the group subtraction. */
+ err = _sub_gids (gids, gids_imp, &new_sub_gids, &new_sub_gids_imp);
+ if (! err)
+ /* Finally, if no problems, do the uid subtraction. */
+ err = idvec_set (uids, &new_uids);
+ }
+ }
+
+ idvec_fini (&new_uids);
+ idvec_fini (&no_sub_gids);
+ idvec_fini (&new_sub_gids);
+ idvec_fini (&new_sub_gids_imp);
+
+ return err;
+}
+
+/* Remove the ids in SUB from those in UGIDS. */
+error_t
+ugids_subtract (struct ugids *ugids, const struct ugids *sub)
+{
+ error_t err =
+ _sub (&ugids->eff_uids, &ugids->eff_gids, &ugids->imp_eff_gids,
+ &sub->eff_uids, &sub->eff_gids, &sub->imp_eff_gids);
+
+ if (! err)
+ /* If this second call to _sub fails, ugids will be in an inconsistent
+ state, but oh well. */
+ err = _sub (&ugids->avail_uids, &ugids->avail_gids, &ugids->imp_avail_gids,
+ &sub->avail_uids, &sub->avail_gids, &sub->imp_avail_gids);
+
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids-verify-auth.c b/libshouldbeinlibc/ugids-verify-auth.c
new file mode 100644
index 00000000..91fa06e9
--- /dev/null
+++ b/libshouldbeinlibc/ugids-verify-auth.c
@@ -0,0 +1,190 @@
+/* Verify user/group passwords and authenticate accordingly
+
+ Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+ 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <hurd.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <argp.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <hurd/paths.h>
+#include <hurd/password.h>
+
+#include "ugids.h"
+
+/* Accumulated information from authentication various passwords. */
+struct svma_state
+{
+ /* The password server. */
+ file_t server;
+
+ /* An auth port for each password that was verify by the server. */
+ auth_t *auths;
+ size_t num_auths;
+};
+
+/* Append the auth ports in AUTHS, of length NUM_AUTHS, to the auth port
+ vector in SS, returning 0 if successful, or an error. */
+static error_t
+svma_state_add_auths (struct svma_state *ss,
+ const auth_t *auths, size_t num_auths)
+{
+ auth_t *new = realloc (ss->auths,
+ (ss->num_auths + num_auths) * sizeof (auth_t));
+ if (new)
+ {
+ ss->auths = new;
+ while (num_auths--)
+ ss->auths[ss->num_auths++] = *auths++;
+ return 0;
+ }
+ else
+ return ENOMEM;
+}
+
+/* Get authentication from PASSWORD using the hurd password server. */
+static error_t
+server_verify_make_auth (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook)
+{
+ auth_t auth;
+ struct svma_state *svma_state = hook;
+ error_t (*check) (io_t server, uid_t id, const char *passwd, auth_t *auth) =
+ is_group ? password_check_group : password_check_user;
+ error_t err = (*check) (svma_state->server, id, password, &auth);
+
+ if (! err)
+ /* PASSWORD checked out ok; the corresponding authentication is in AUTH. */
+ {
+ err = svma_state_add_auths (svma_state, &auth, 1);
+ if (err)
+ mach_port_deallocate (mach_task_self (), auth);
+ }
+
+ return err;
+}
+
+/* Verify that we have the right to the ids in UGIDS, given that we already
+ possess those in HAVE_UIDS and HAVE_GIDS (asking for passwords where
+ necessary), and return corresponding authentication in AUTH; the auth
+ ports in FROM, of length NUM_FROM, are used to supplement the auth port of
+ the current process if necessary. 0 is returned if access should be
+ allowed, otherwise EINVAL if an incorrect password was entered, or an
+ error relating to resource failure. GETPASS_FN and GETPASS_HOOK are as
+ for the idvec_verify function in <idvec.h>. */
+error_t
+ugids_verify_make_auth (const struct ugids *ugids,
+ const struct idvec *have_uids,
+ const struct idvec *have_gids,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *getpass_hook,
+ const auth_t *from, size_t num_from,
+ auth_t *auth)
+{
+ error_t err;
+ /* By default, get authentication from the password server. */
+ struct svma_state svma_state;
+ error_t (*verify_fn) (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook)
+ = server_verify_make_auth;
+ void *verify_hook = &svma_state;
+
+ /* Try to open the hurd password server. */
+ svma_state.server = file_name_lookup (_SERVERS_PASSWORD, 0, 0);
+
+ if (svma_state.server == MACH_PORT_NULL)
+ /* Can't open the password server, try to use our own authority in
+ the traditional unix manner. */
+ {
+ verify_fn = 0;
+ verify_hook = 0;
+ }
+ else
+ {
+ /* Must initialize list to empty so svma_state_add_auths works. */
+ svma_state.auths = NULL;
+ svma_state.num_auths = 0;
+ }
+
+ /* Check passwords. */
+ err = ugids_verify (ugids, have_uids, have_gids,
+ getpass_fn, getpass_hook, verify_fn, verify_hook);
+
+ if (! err)
+ {
+ /* The user apparently has access to all the ids, try to grant the
+ corresponding authentication. */
+ if (verify_fn)
+ /* Merge the authentication we got from the password server into our
+ result. */
+ {
+ if (num_from > 0)
+ /* Use FROM as well as the passwords to get authentication. */
+ err = svma_state_add_auths (&svma_state, from, num_from);
+
+ if (! err)
+ {
+ auth_t cur_auth = getauth ();
+
+ err =
+ auth_makeauth (cur_auth,
+ svma_state.auths, MACH_MSG_TYPE_COPY_SEND,
+ svma_state.num_auths,
+ ugids->eff_uids.ids, ugids->eff_uids.num,
+ ugids->avail_uids.ids, ugids->avail_uids.num,
+ ugids->eff_gids.ids, ugids->eff_gids.num,
+ ugids->avail_gids.ids, ugids->avail_gids.num,
+ auth);
+ mach_port_deallocate (mach_task_self (), cur_auth);
+
+ /* Avoid deallocating FROM when we clean up SVMA_STATE. */
+ svma_state.num_auths -= num_from;
+ }
+ }
+ else
+ /* Try to authenticate the old fashioned way... */
+ err = ugids_make_auth (ugids, from, num_from, auth);
+ }
+
+ if (verify_fn)
+ /* Clean up any left over state. */
+ {
+ int i;
+
+ /* Get rid of auth ports. */
+ for (i = 0; i < svma_state.num_auths; i++)
+ mach_port_deallocate (mach_task_self (), svma_state.auths[i]);
+
+ /* Close password server. */
+ mach_port_deallocate (mach_task_self (), svma_state.server);
+
+ if (svma_state.num_auths > 0)
+ free (svma_state.auths);
+ }
+
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids-verify.c b/libshouldbeinlibc/ugids-verify.c
new file mode 100644
index 00000000..f9d45c63
--- /dev/null
+++ b/libshouldbeinlibc/ugids-verify.c
@@ -0,0 +1,70 @@
+/* Verify user/group passwords
+
+ 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 <string.h>
+#include <hurd.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <argp.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "ugids.h"
+
+/* Verify that we have the right to the ids in UGIDS, given that we already
+ possess those in HAVE_UIDS and HAVE_GIDS, asking for passwords where
+ necessary. 0 is returned if access should be allowed, otherwise
+ EINVAL if an incorrect password was entered, or an error relating to
+ resource failure. The GETPASS_FN, GETPASS_HOOK, VERIFY_FN, and
+ VERIFY_HOOK arguments are as for the idvec_verify function (in <idvec.h>). */
+error_t
+ugids_verify (const struct ugids *ugids,
+ const struct idvec *have_uids, const struct idvec *have_gids,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *getpass_hook,
+ error_t (*verify_fn) (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *verify_hook)
+{
+ error_t err;
+ struct idvec check_uids = IDVEC_INIT; /* User-ids to verify. */
+ struct idvec check_gids = IDVEC_INIT; /* group-ids to verify. */
+
+ err = idvec_merge (&check_uids, &ugids->eff_uids);
+ if (! err)
+ err = idvec_merge (&check_uids, &ugids->avail_uids);
+ if (! err)
+ err = idvec_merge (&check_gids, &ugids->eff_gids);
+ if (! err)
+ err = idvec_merge (&check_gids, &ugids->avail_gids);
+
+ if (! err)
+ err = idvec_verify (&check_uids, &check_gids, have_uids, have_gids,
+ getpass_fn, getpass_hook, verify_fn, verify_hook);
+
+ idvec_fini (&check_uids);
+ idvec_fini (&check_gids);
+
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids-xinl.c b/libshouldbeinlibc/ugids-xinl.c
new file mode 100644
index 00000000..107de8b9
--- /dev/null
+++ b/libshouldbeinlibc/ugids-xinl.c
@@ -0,0 +1,23 @@
+/* Real definitions for extern inline functions in ugids.h
+
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define UGIDS_DEFINE_EI
+#include "ugids.h"
diff --git a/libshouldbeinlibc/ugids.c b/libshouldbeinlibc/ugids.c
new file mode 100644
index 00000000..2b9b6b71
--- /dev/null
+++ b/libshouldbeinlibc/ugids.c
@@ -0,0 +1,97 @@
+/* Frob user and group ids
+
+ 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 <string.h>
+
+#include "ugids.h"
+
+/* Return a new ugids structure, or 0 if an allocation error occurs. */
+struct ugids *
+make_ugids ()
+{
+ struct ugids *u = malloc (sizeof (struct ugids));
+ if (u)
+ bzero (u, sizeof *u);
+ return u;
+}
+
+/* Add a new uid to UGIDS. If AVAIL is true, it's added to the avail uids
+ instead of the effective ones. */
+error_t
+ugids_add_uid (struct ugids *ugids, uid_t uid, int avail)
+{
+ return idvec_add_new (avail ? &ugids->avail_uids : &ugids->eff_uids, uid);
+}
+
+/* Add a new gid to UGIDS. If AVAIL is true, it's added to the avail gids
+ instead of the effective ones. */
+error_t
+ugids_add_gid (struct ugids *ugids, gid_t gid, int avail)
+{
+ error_t err =
+ idvec_add_new (avail ? &ugids->avail_gids : &ugids->eff_gids, gid);
+ if (! err)
+ /* Since this gid is now explicit, remove it from the appropriate implied
+ set. */
+ idvec_remove (avail ? &ugids->imp_avail_gids : &ugids->imp_eff_gids,
+ 0, gid);
+ return err;
+}
+
+/* Add UID to UGIDS, plus any gids to which that user belongs. If AVAIL is
+ true, the are added to the avail gids instead of the effective ones. */
+error_t
+ugids_add_user (struct ugids *ugids, uid_t uid, int avail)
+{
+ error_t err;
+ struct idvec imp_gids = IDVEC_INIT;
+ uid_t uids_ids[] = { uid };
+ struct idvec uids = { uids_ids, 1 };
+ struct idvec *gids = avail ? &ugids->avail_gids : &ugids->eff_gids;
+
+ idvec_merge_implied_gids (&imp_gids, &uids);
+
+ /* Now remove any gids we already know about from IMP_GIDS. For gids
+ that weren't in the appropriate implied set before, this will
+ ensure that they remain out after we merge IMP_GIDS into it, and
+ ones that *were*, they will remain so. */
+ idvec_subtract (&imp_gids, gids);
+
+ /* Try to add UID. */
+ err = idvec_add_new (avail ? &ugids->avail_uids : &ugids->eff_uids, uid);
+
+ if (! err)
+ /* Now that we've added UID, we can add appropriate implied gids.
+ [If this fails, UGIDS will be an inconsistent state, but things
+ are probably fucked anyhow] */
+ err =
+ idvec_merge (avail ? &ugids->avail_gids : &ugids->eff_gids,
+ &imp_gids);
+ if (! err)
+ err = idvec_merge ((avail
+ ? &ugids->imp_avail_gids
+ : &ugids->imp_eff_gids),
+ &imp_gids);
+
+ idvec_fini (&imp_gids);
+
+ return err;
+}
diff --git a/libshouldbeinlibc/ugids.h b/libshouldbeinlibc/ugids.h
new file mode 100644
index 00000000..10e7a242
--- /dev/null
+++ b/libshouldbeinlibc/ugids.h
@@ -0,0 +1,229 @@
+/* Uid/gid parsing/frobbing
+
+ Copyright (C) 1997,2001 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.org>
+
+ 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. */
+
+#ifndef __UGIDS_H__
+#define __UGIDS_H__
+
+#include <stdlib.h> /* For inline function stuff. */
+#include <idvec.h>
+#include <features.h>
+
+#ifdef UGIDS_DEFINE_EI
+#define UGIDS_EI
+#else
+#define UGIDS_EI __extern_inline
+#endif
+
+/* A structure holding a set of the common various types of ids. */
+struct ugids
+{
+ struct idvec eff_uids; /* Effective UIDs */
+ struct idvec eff_gids; /* Effective GIDs */
+ struct idvec avail_uids; /* Available UIDs */
+ struct idvec avail_gids; /* Available GIDs */
+
+ /* These should be a subset of EFF/AVAIL_GIDS, containing those gids which
+ are present only by implication from uids in EFF/AVAIL_UIDS. */
+ struct idvec imp_eff_gids;
+ struct idvec imp_avail_gids;
+};
+
+#define UGIDS_INIT { IDVEC_INIT, IDVEC_INIT, IDVEC_INIT, IDVEC_INIT, IDVEC_INIT, IDVEC_INIT }
+
+/* Return a new ugids structure, or 0 if an allocation error occurs. */
+struct ugids *make_ugids ();
+
+extern void ugids_fini (struct ugids *ugids);
+
+extern void ugids_free (struct ugids *ugids);
+
+extern int ugids_is_empty (const struct ugids *ugids);
+
+extern int ugids_equal (const struct ugids *ugids1, const struct ugids *ugids2);
+
+#if defined(__USE_EXTERN_INLINES) || defined(UGIDS_DEFINE_EI)
+
+/* Free all resources used by UGIDS except UGIDS itself. */
+UGIDS_EI void
+ugids_fini (struct ugids *ugids)
+{
+ idvec_fini (&ugids->eff_uids);
+ idvec_fini (&ugids->eff_gids);
+ idvec_fini (&ugids->avail_uids);
+ idvec_fini (&ugids->avail_gids);
+ idvec_fini (&ugids->imp_eff_gids);
+ idvec_fini (&ugids->imp_avail_gids);
+}
+
+/* Free all resources used by UGIDS. */
+UGIDS_EI void
+ugids_free (struct ugids *ugids)
+{
+ ugids_fini (ugids);
+ free (ugids);
+}
+
+/* Return true if UGIDS contains no ids. */
+UGIDS_EI int
+ugids_is_empty (const struct ugids *ugids)
+{
+ /* We needn't test the imp_*_gids vectors because they are subsets of the
+ corresponding *_gids vectors. */
+ return
+ idvec_is_empty (&ugids->eff_uids)
+ && idvec_is_empty (&ugids->eff_gids)
+ && idvec_is_empty (&ugids->avail_uids)
+ && idvec_is_empty (&ugids->avail_gids);
+}
+
+/* Free all resources used by UGIDS except UGIDS itself. */
+UGIDS_EI int
+ugids_equal (const struct ugids *ugids1, const struct ugids *ugids2)
+{
+ return
+ idvec_equal (&ugids1->eff_uids, &ugids2->eff_uids)
+ && idvec_equal (&ugids1->eff_gids, &ugids2->eff_gids)
+ && idvec_equal (&ugids1->avail_uids, &ugids2->avail_uids)
+ && idvec_equal (&ugids1->avail_gids, &ugids2->avail_gids)
+ && idvec_equal (&ugids1->imp_eff_gids, &ugids2->imp_eff_gids)
+ && idvec_equal (&ugids1->imp_avail_gids, &ugids2->imp_avail_gids);
+}
+
+#endif /* Use extern inlines. */
+
+/* Add all ids in NEW to UGIDS. */
+error_t ugids_merge (struct ugids *ugids, const struct ugids *new);
+
+/* Set the ids in UGIDS to those in NEW. */
+error_t ugids_set (struct ugids *ugids, const struct ugids *new);
+
+/* Remove the ids in SUB from those in UGIDS. */
+error_t ugids_subtract (struct ugids *ugids, const struct ugids *sub);
+
+/* Mark as implied all gids in UGIDS that can be implied from its uids. */
+error_t ugids_imply_all (struct ugids *ugids);
+
+/* Save any effective ids in UGIDS by merging them into the available ids,
+ and removing them from the effective ones. */
+error_t ugids_save (struct ugids *ugids);
+
+/* Verify that we have the right to the ids in UGIDS, given that we already
+ possess those in HAVE_UIDS and HAVE_GIDS, asking for passwords where
+ necessary. 0 is returned if access should be allowed, otherwise
+ EINVAL if an incorrect password was entered, or an error relating to
+ resource failure. The GETPASS_FN, GETPASS_HOOK, VERIFY_FN, and
+ VERIFY_HOOK arguments are as for the idvec_verify function (in <idvec.h>). */
+error_t ugids_verify (const struct ugids *ugids,
+ const struct idvec *have_uids,
+ const struct idvec *have_gids,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *getpass_hook,
+ error_t (*verify_fn) (const char *password,
+ uid_t id, int is_group,
+ void *pwd_or_grp, void *hook),
+ void *verify_hook);
+
+/* Make an auth port from UGIDS and return it in AUTH, using authority in
+ both the auth port FROM and the current auth port. */
+error_t ugids_make_auth (const struct ugids *ugids,
+ const auth_t *from, size_t num_from,
+ auth_t *auth);
+
+/* Verify that we have the right to the ids in UGIDS, given that we already
+ possess those in HAVE_UIDS and HAVE_GIDS (asking for passwords where
+ necessary), and return corresponding authentication in AUTH; the auth
+ ports in FROM, of length NUM_FROM, are used to supplement the auth port of
+ the current process if necessary. 0 is returned if access should be
+ allowed, otherwise EINVAL if an incorrect password was entered, or an
+ error relating to resource failure. GETPASS_FN and GETPASS_HOOK are as
+ for the idvec_verify function in <idvec.h>. */
+error_t ugids_verify_make_auth (const struct ugids *ugids,
+ const struct idvec *have_uids,
+ const struct idvec *have_gids,
+ char *(*getpass_fn) (const char *prompt,
+ uid_t id, int is_group,
+ void *pwd_or_grp,
+ void *hook),
+ void *getpass_hook,
+ const auth_t *from, size_t num_from,
+ auth_t *auth);
+
+/* Merge the ids from the auth port AUTH into UGIDS. */
+error_t ugids_merge_auth (struct ugids *ugids, auth_t auth);
+
+/* Return a string representation of the ids in UGIDS. SHOW_VALUES and
+ SHOW_NAMES reflect how each id is printed (if SHOW_NAMES is true values
+ are used where names aren't available); if both are true, the
+ `VALUE(NAME)' format is used. ID_SEP, TYPE_SEP, and HDR_SEP contain the
+ strings that separate, respectively, multiple ids of a particular type
+ (default ","), the various types of ids (default ", "), and the name of
+ each type from its ids (default ": "). The empty string is returned for
+ an empty list, and 0 for an allocation error. */
+char *ugids_rep (const struct ugids *ugids, int show_values, int show_names,
+ const char *id_sep, const char *type_sep,
+ const char *hdr_sep);
+
+/* Add a new uid to UGIDS. If AVAIL is true, it's added to the avail uids
+ instead of the effective ones. */
+error_t ugids_add_uid (struct ugids *ugids, uid_t uid, int avail);
+
+/* Add a new gid to UGIDS. If AVAIL is true, it's added to the avail gids
+ instead of the effective ones. */
+error_t ugids_add_gid (struct ugids *ugids, gid_t gid, int avail);
+
+/* Add UID to UGIDS, plus any gids to which that user belongs. If AVAIL is
+ true, the are added to the avail gids instead of the effective ones. */
+error_t ugids_add_user (struct ugids *ugids, uid_t uid, int avail);
+
+/* Install UID into UGIDS as the main user, making sure that the posix
+ `real' and `saved' uid slots are filled in, and similarly add all
+ groups to which UID belongs. */
+error_t ugids_set_posix_user (struct ugids *ugids, uid_t uid);
+
+/* Params to be passed as the input when parsing UGIDS_ARGP. */
+struct ugids_argp_params
+{
+ /* Parsed ids should be added here. */
+ struct ugids *ugids;
+
+ /* If true, parse multiple args as user otherwise, parse none. */
+ int parse_user_args;
+
+ /* If true, and PARSE_USER_ARGS is true, add user args to the available
+ ids, not the effective ones. If both are true, add them to both.
+ If both are false, use the special ugids_set_posix_user instead (which
+ sets both, in a particular way). */
+ int user_args_are_effective;
+ int user_args_are_available;
+
+ /* If >= 0, a user that should be added if none are specified on the
+ command line (following the same rules). */
+ int default_user;
+
+ /* If true, at least one id has to be specified. */
+ int require_ids;
+};
+
+/* A parser for selecting a set of ugids. */
+extern struct argp ugids_argp;
+
+#endif /* __UGIDS_H__ */
diff --git a/libshouldbeinlibc/wire.c b/libshouldbeinlibc/wire.c
index 7be04dee..bafc9599 100644
--- a/libshouldbeinlibc/wire.c
+++ b/libshouldbeinlibc/wire.c
@@ -1,5 +1,5 @@
/* Function to wire down text and data (including from shared libraries)
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996,99,2000,01,02 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -20,14 +20,28 @@
#include <link.h>
+#include <dlfcn.h>
#include <mach.h>
#include <hurd.h>
+#include <error.h>
+
+#pragma weak _DYNAMIC
+#pragma weak dlopen
+#pragma weak dlclose
+#pragma weak dlerror
+#pragma weak dlsym
+#ifndef RTLD_NOLOAD
+#define RTLD_NOLOAD 0
+#endif
/* Find the list of shared objects */
static struct link_map *
loaded (void)
{
- Elf32_Dyn *d;
+ ElfW(Dyn) *d;
+
+ if (&_DYNAMIC == 0) /* statically linked */
+ return 0;
for (d = _DYNAMIC; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_DEBUG)
@@ -40,13 +54,27 @@ loaded (void)
}
/* Compute the extent of a particular shared object. */
-static Elf32_Addr
+static ElfW(Addr)
map_extent (struct link_map *map)
{
- /* Find the last load cmd; they are in ascending p_vaddr order. */
- Elf32_Word n = map->l_phnum;
- while (n-- > 0 && map->l_phdr[n].p_type != PT_LOAD);
- return map->l_phdr[n].p_vaddr + map->l_phdr[n].p_filesz;
+ /* In fact, LIB == MAP, but doing it this way makes it entirely kosher. */
+ void *lib = dlopen (map->l_name, RTLD_NOLOAD);
+ if (lib == 0)
+ {
+ error (2, 0, "cannot dlopen %s: %s", map->l_name, dlerror ());
+ /* NOTREACHED */
+ return 0;
+ }
+ else
+ {
+ /* Find the _end symbol's runtime address and subtract the load base. */
+ void *end = dlsym (lib, "_end");
+ if (end == 0)
+ error (2, 0, "cannot wire library %s with no _end symbol: %s",
+ map->l_name, dlerror ());
+ dlclose (lib);
+ return (ElfW(Addr)) end - map->l_addr;
+ }
}
/* Wire down all memory currently allocated at START for LEN bytes;
@@ -70,7 +98,7 @@ wire_segment_internal (vm_address_t start,
do
{
addr = start;
- err = vm_region (mach_task_self (), &addr, &size, &protection,
+ err = vm_region (mach_task_self (), &addr, &size, &protection,
&max_protection, &inheritance, &shared, &object_name,
&offset);
if (err)
@@ -80,25 +108,25 @@ wire_segment_internal (vm_address_t start,
extends beyond the LEN, prune it. */
if (addr + size > start + len)
size = len - (addr - start);
-
+
/* Set protection to allow all access possible */
vm_protect (mach_task_self (), addr, size, 0, max_protection);
-
+
/* Generate write faults */
- for (poke = (char *) addr;
- (vm_address_t) poke < addr + size;
+ for (poke = (char *) addr;
+ (vm_address_t) poke < addr + size;
poke += vm_page_size)
*poke = *poke;
/* Wire pages */
vm_wire (host_priv, mach_task_self (), addr, size, max_protection);
-
+
/* Set protection back to what it was */
vm_protect (mach_task_self (), addr, size, 0, protection);
mach_port_deallocate (mach_task_self (), object_name);
-
+
len -= (addr - start) + size;
start = addr + size;
}
@@ -112,7 +140,7 @@ wire_segment (vm_address_t start,
{
mach_port_t host, device;
error_t error;
-
+
error = get_privileged_ports (&host, &device);
if (!error)
{
@@ -132,17 +160,17 @@ wire_task_self ()
mach_port_t host, device;
error_t error;
extern char _edata, _etext, __data_start;
-
+
error = get_privileged_ports (&host, &device);
if (error)
return;
-
+
map = loaded ();
if (!map)
{
extern void _start ();
vm_address_t text_start = (vm_address_t) &_start;
- wire_segment_internal (text_start,
+ wire_segment_internal (text_start,
(vm_size_t) (&_etext - text_start),
host);
wire_segment_internal ((vm_address_t) &__data_start,
@@ -156,4 +184,3 @@ wire_task_self ()
mach_port_deallocate (mach_task_self (), host);
mach_port_deallocate (mach_task_self (), device);
}
-
diff --git a/libshouldbeinlibc/xportinfo.c b/libshouldbeinlibc/xportinfo.c
index cdd1da38..cce6fb6c 100644
--- a/libshouldbeinlibc/xportinfo.c
+++ b/libshouldbeinlibc/xportinfo.c
@@ -1,6 +1,6 @@
/* Print information about a port, with the name translated between tasks
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1999 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -18,6 +18,9 @@
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 <sys/mman.h>
+
#include "portinfo.h"
/* Prints info about NAME translated through X to STREAM, in a way described
@@ -32,7 +35,7 @@ print_xlated_port_info (mach_port_t name, mach_port_type_t type,
error_t err = port_name_xlator_xlate (x, name, type, &name, &type);
if (! err)
{
- fprintf (stream, (show & PORTINFO_HEX_NAMES) ? "%#6x => " : "%6d => ",
+ fprintf (stream, (show & PORTINFO_HEX_NAMES) ? "%#6zx => " : "%6zd => ",
old_name);
err = print_port_info (name, type, x->to_task, show, stream);
}
@@ -59,10 +62,8 @@ print_xlated_task_ports_info (struct port_name_xlator *x,
if (types[i] & only)
print_xlated_port_info (names[i], types[i], x, show, stream);
- vm_deallocate (mach_task_self (),
- (vm_address_t)names, names_len * sizeof *names);
- vm_deallocate (mach_task_self (),
- (vm_address_t)types, types_len * sizeof *types);
+ munmap ((caddr_t) names, names_len * sizeof *names);
+ munmap ((caddr_t) types, types_len * sizeof *types);
return 0;
}