diff options
| -rw-r--r-- | ChangeLog | 34 | ||||
| -rw-r--r-- | login/programs/pt_chown.c | 153 | ||||
| -rw-r--r-- | login/pty-private.h (renamed from login/pty-internal.h) | 23 | ||||
| -rw-r--r-- | posix/wordexp-test.c | 4 | ||||
| -rw-r--r-- | posix/wordexp.c | 344 | ||||
| -rw-r--r-- | sysdeps/unix/bsd/getpt.c | 74 | ||||
| -rw-r--r-- | sysdeps/unix/bsd/ptsname.c | 78 | ||||
| -rw-r--r-- | sysdeps/unix/bsd/unlockpt.c | 20 | ||||
| -rw-r--r-- | sysdeps/unix/grantpt.c | 150 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/getpt.c | 51 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/grantpt.c | 64 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/ptsname.c | 141 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/sparc/sparc64/socket.S | 80 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/unlockpt.c | 20 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/sysv4/bits/utsname.h | 4 |
15 files changed, 847 insertions, 393 deletions
@@ -1,3 +1,37 @@ +1998-09-17 19:34 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/unix/sysv/sysv4/bits/utsname.h: Fix typo. + Patch by John Tobey <jtobey@banta-im.com>. + +1998-09-17 Mark Kettenis <kettenis@phys.uva.nl> + + * login/pty-internal.h: Removed. Moved constants related to the + `grantpt' helper program protocol to ... + * login/pty-private.h: ... here. New file. + * sysdeps/unix/sysv/linux/ptsname.c (ptsname): Reimplementation + to make the function work with kernels >= 2.1.115. + * sysdeps/unix/sysv/linux/getpt.c (getpt): Reimplement to call BSD + version if using the cloning device fails. + * sysdeps/unix/sysv/linux/grantpt.c: New file. + * sysdeps/unix/sysv/linux/unlockpt.c: General cleanup. + * sysdeps/unix/bsd/getpt.c (__getpt): Largely rewritten to allow + use by Linux specific code. + * sysdeps/unix/bsd/unlockpt.c: General cleanup. + * sysdeps/unix/grantpt.c: Largely rewritten. (pts_name): New + function. (grantpt): Use pts_name, check group and permission + mode in addition to owner. Try to set the owner, group and + permission mode first without invoking the helper program. + * login/programs/pt_chown.c: Largely rewritten. Add argp and + internationalization support. Use symbolic constants instead of + hardwired numbers for permission mode. + * sysdeps/unix/bsd/ptsname.c: New file. + +1998-09-17 22:04 Tim Waugh <tim@cyberelk.demon.co.uk> + + * posix/wordexp-test.c: Undo last change. + + * posix/wordexp.c: Undo last change. + 1998-09-16 Ulrich Drepper <drepper@cygnus.com> * nscd/grpcache.c (save_grp): Partly undo last change. diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c index dbf79fc6ad..6ed8e82d5b 100644 --- a/login/programs/pt_chown.c +++ b/login/programs/pt_chown.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* pt_chmod - helper program for `grantpt'. + Copyright (C) 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998. @@ -17,72 +18,136 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* pt_chmod.c ... securely implement grantpt in user-land. */ - -#include <sys/stat.h> -#include <sys/types.h> -#include <stdlib.h> -#include <unistd.h> +#include <argp.h> #include <errno.h> -#include <stdio.h> +#include <error.h> #include <grp.h> +#include <libintl.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "pty-private.h" -#include "pty-internal.h" -#define Str(x) _Str(x) -#define _Str(x) #x +/* Get libc version number. */ +#include "../version.h" -void -usage (void) +#define PACKAGE _libc_intl_domainname + +/* Name and version of program. */ +static void print_version (FILE *stream, struct argp_state *state); +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Function to print some extra text in the help message. */ +static char *more_help (int key, const char *text, void *input); + +/* Data structure to communicate with argp functions. */ +static struct argp argp = { - fprintf (stderr, _("usage: pt_chown FD>&%s\n" - "This program is used internally by grantpt(3).\n"), - Str (PTY_FD)); - exit (0); + NULL, NULL, NULL, NULL, NULL, more_help +}; + + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "pt_chmod (GNU %s) %s\n", PACKAGE, VERSION); + fprintf (stream, gettext ("\ +Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), "1998"); } -void -bad_installation (void) +static char * +more_help (int key, const char *text, void *input) { - fputs (_("pt_chown: installation problem: " - "This program needs to be setuid root.\n"), stderr); - exit (FAIL_EXEC); + char *cp; + + switch (key) + { + case ARGP_KEY_HELP_PRE_DOC: + asprintf (&cp, gettext ("\ +Set the owner, group and access permission of the terminal passed on\ + file descriptor `%d'. This is the helper program for the `grantpt'\ + function. It is not intended to be run directly from the command\ + line.\n"), + PTY_FILENO); + return cp; + case ARGP_KEY_HELP_EXTRA: + /* We print some extra information. */ + asprintf (&cp, gettext ("\ +The owner is set to the current user, the group is set to `%s',\ + and the access permission is set to `%o'.\n\n\ +%s"), + TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, gettext ("\ +Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n")); + return cp; + default: + break; + } + return (char *) text; } int -main (int argc, char **argv) +main (int argc, char *argv[]) { - struct group *grp; - struct stat s; char *pty; + int remaining; + struct stat st; + struct group *p; gid_t gid; - uid_t uid; - if (argc != 1) - usage (); + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); + + /* Set the text message domain. */ + textdomain (PACKAGE); + + /* parse and process arguments. */ + argp_parse (&argp, argc, argv, 0, &remaining, NULL); + + if (remaining < argc) + { + /* We should not be called with any non-option parameters. */ + error (0, 0, gettext ("too many arguments")); + argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, + program_invocation_short_name); + exit (EXIT_FAILURE); + } + + /* Check if we are properly installed. */ if (geteuid () != 0) - bad_installation (); - - grp = getgrnam (TTY_GROUP); - gid = grp ? grp->gr_gid : getgid (); - uid = getuid (); + error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'")); - /* Check that fd is a valid pty master -- call ptsname(). */ - pty = ptsname (PTY_FD); + /* Check that PTY_FILENO is a valid master pseudo terminal. */ + pty = ptsname (PTY_FILENO); if (pty == NULL) return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL; - close (PTY_FD); + close (PTY_FILENO); - /* Check that target file is a character device. */ - if (stat (pty, &s)) - return FAIL_EINVAL; /* This should only fail if pty doesn't exist. */ - if (!S_ISCHR (s.st_mode)) + /* Check that the returned slave pseudo terminal is a + character device. */ + if (stat (pty, &st) < 0 || !S_ISCHR(st.st_mode)) return FAIL_EINVAL; - if (chmod (pty, 0620)) - return FAIL_EACCES; /* XXX: Probably not true. */ + /* Get the group ID of the special `tty' group. */ + p = getgrnam (TTY_GROUP); + gid = p ? p->gr_gid : getgid (); + + /* Set the owner to the real user ID, and the group to that special + group ID. */ + if (chown (pty, getuid (), gid) < 0) + return FAIL_EACCES; - if (chown (pty, uid, gid)) + /* Set the permission mode to readable and writable by the owner, + and writable by the group. */ + if (chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0) return FAIL_EACCES; - return 0; + exit (EXIT_SUCCESS); } diff --git a/login/pty-internal.h b/login/pty-private.h index c1858861ec..b20fd0edcc 100644 --- a/login/pty-internal.h +++ b/login/pty-private.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Internal defenitions and declarations for pseudo terminal functions. + Copyright (C) 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. @@ -17,19 +18,19 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Internal constants used by the pseudoterminal handling code. */ +#ifndef _PTY_PRIVATE_H +#define _PTY_PRIVATE_H 1 -#ifndef _PTY_INTERNAL_H -#define _PTY_INTERNAL_H 1 +/* The group slave pseudo terminals belong to. */ +#define TTY_GROUP "tty" -/* Length of a buffer to hold a pty name. */ -#define PTYNAMELEN 15 /* "/dev/pts/65535$" */ +/* The file descriptor connected to the master pseudo terminal. */ +#define PTY_FILENO 3 -/* Which group should pty slaves belong to: */ -#define TTY_GROUP "tty" +/* Path to the helper program that implements `grantpt' in user space. */ +#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown" -/* Communication between grantpt and pt_chown. */ -#define PTY_FD 3 +/* Exit codes for the helper program. */ enum /* failure modes */ { FAIL_EBADF = 1, @@ -38,4 +39,4 @@ enum /* failure modes */ FAIL_EXEC }; -#endif +#endif /* pty-private.h */ diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c index 746b817c46..8e709c7569 100644 --- a/posix/wordexp-test.c +++ b/posix/wordexp-test.c @@ -63,8 +63,8 @@ struct test_case_struct { 0, NULL, ":abc:", 0, 1, { ":abc:", }, ":" }, { 0, NULL, "$(echo :abc:)def", 0, 3, { "", "abc", "def", }, ":" }, { 0, NULL, "$(echo abc:de)f", 0, 2, { "abc", "def", }, ":" }, - { 0, NULL, "$(echo abc:de)f:ghi", 0, 3, { "abc", "def", "ghi", }, ":" }, - { 0, NULL, "abc:d$(echo ef:ghi)", 0, 3, { "abc", "def", "ghi", }, ":" }, + { 0, NULL, "$(echo abc:de)f:ghi", 0, 2, { "abc", "def:ghi", }, ":" }, + { 0, NULL, "abc:d$(echo ef:ghi)", 0, 2, { "abc:def", "ghi", }, ":" }, { 0, "abc:", "$var$(echo def:ghi)", 0, 3, { "abc", "def", "ghi", }, ":" }, { 0, "abc:d", "$var$(echo ef:ghi)", 0, 3, { "abc", "def", "ghi", }, ":" }, { 0, "def:ghi", "$(echo abc:)$var", 0, 3, { "abc", "def", "ghi", }, ":" }, diff --git a/posix/wordexp.c b/posix/wordexp.c index 0cda9deb76..4a377001e7 100644 --- a/posix/wordexp.c +++ b/posix/wordexp.c @@ -56,7 +56,7 @@ extern char **__libc_argv; static int parse_dollars (char **word, size_t *word_length, size_t *max_length, const char *words, size_t *offset, int flags, wordexp_t *pwordexp, const char *ifs, - const char *ifs_white, int quoted, int *fsplit) + const char *ifs_white, int quoted) internal_function; static int parse_backtick (char **word, size_t *word_length, size_t *max_length, const char *words, @@ -183,78 +183,6 @@ no_space: return WRDE_NOSPACE; } -static int -internal_function -field_split_word (char *word, wordexp_t *pwordexp, const char *ifs, - const char *ifs_white) -{ - size_t field_length; - size_t field_maxlen; - char *field = w_newword (&field_length, &field_maxlen); - char *field_begin = word; - int seen_nonws_ifs = 0; - - if (!word) - return 0; - - do - { - char *field_end = field_begin; - char *next_field; - - /* If this isn't the first field, start a new word */ - if (field_begin != word) - { - if (w_addword (pwordexp, field) == WRDE_NOSPACE) - goto no_space; - - field = w_newword (&field_length, &field_maxlen); - } - - /* Skip IFS whitespace before the field */ - field_begin += strspn (field_begin, ifs_white); - - if (!seen_nonws_ifs && *field_begin == 0) - /* Nothing but whitespace */ - break; - - /* Search for the end of the field */ - field_end = field_begin + strcspn (field_begin, ifs); - - /* Set up pointer to the character after end of field and - skip whitespace IFS after it. */ - next_field = field_end + strspn (field_end, ifs_white); - - /* Skip at most one non-whitespace IFS character after the field */ - seen_nonws_ifs = 0; - if (*next_field && strchr (ifs, *next_field)) - { - seen_nonws_ifs = 1; - next_field++; - } - - /* Null-terminate it */ - *field_end = 0; - - /* Tag a copy onto the current word */ - field = w_addstr (field, &field_length, &field_maxlen, field_begin); - - if (field == NULL && *field_begin != '\0') - goto no_space; - - field_begin = next_field; - } - while (seen_nonws_ifs || *field_begin); - - if (field && w_addword (pwordexp, field)) - goto no_space; - - return 0; - -no_space: - return WRDE_NOSPACE; -} - /* The parse_*() functions should leave *offset being the offset in 'words' * to the last character processed. */ @@ -496,15 +424,15 @@ parse_glob (char **word, size_t *word_length, size_t *max_length, int quoted = 0; /* 1 if singly-quoted, 2 if doubly */ int i; wordexp_t glob_list; /* List of words to glob */ - int fieldsplit = 0; glob_list.we_wordc = 0; glob_list.we_wordv = NULL; glob_list.we_offs = 0; for (; words[*offset] != '\0'; ++*offset) { - if (strchr (" \t\n", words[*offset])) - /* Reached end of word */ + if ((ifs && strchr (ifs, words[*offset])) || + (!ifs && strchr (" \t\n", words[*offset]))) + /* Reached IFS */ break; /* Sort out quoting */ @@ -540,7 +468,7 @@ parse_glob (char **word, size_t *word_length, size_t *max_length, { error = parse_dollars (word, word_length, max_length, words, offset, flags, &glob_list, ifs, ifs_white, - quoted == 2, &fieldsplit); + quoted == 2); if (error) goto tidy_up; @@ -569,16 +497,8 @@ parse_glob (char **word, size_t *word_length, size_t *max_length, /* Don't forget to re-parse the character we stopped at. */ --*offset; - if (fieldsplit) - { - error = field_split_word (*word, &glob_list, ifs, ifs_white); - if (*word) - free (*word); - } - else - error = w_addword (&glob_list, *word); - /* Glob the words */ + error = w_addword (&glob_list, *word); *word = w_newword (word_length, max_length); for (i = 0; error == 0 && i < glob_list.we_wordc; i++) error = do_parse_glob (glob_list.we_wordv[i], word, word_length, @@ -756,8 +676,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length, { case '$': error = parse_dollars (&expr, &expr_length, &expr_maxlen, - words, offset, flags, NULL, NULL, NULL, 1, - NULL); + words, offset, flags, NULL, NULL, NULL, 1); /* The ``1'' here is to tell parse_dollars not to * split the fields. */ @@ -898,6 +817,7 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length, int fildes[2]; int bufsize = 128; int buflen; + int i; char *buffer; pid_t pid; @@ -951,20 +871,100 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length, __close (fildes[1]); buffer = __alloca (bufsize); - /* Read fildes[0] and put it into a word. */ - while (1) - { - if ((buflen = __read (fildes[0], buffer, bufsize)) < 1) + if (!pwordexp) + { /* Quoted - no field splitting */ + + while (1) { - if (__waitpid (pid, NULL, WNOHANG) == 0) - continue; if ((buflen = __read (fildes[0], buffer, bufsize)) < 1) - break; + { + if (__waitpid (pid, NULL, WNOHANG) == 0) + continue; + if ((buflen = __read (fildes[0], buffer, bufsize)) < 1) + break; + } + + *word = w_addmem (*word, word_length, max_length, buffer, buflen); + if (*word == NULL) + goto no_space; } + } + else + /* Not quoted - split fields */ + { + int copying = 0; + /* 'copying' is: + * 0 when searching for first character in a field not IFS white space + * 1 when copying the text of a field + * 2 when searching for possible non-whitespace IFS + */ + + while (1) + { + if ((buflen = __read (fildes[0], buffer, bufsize)) < 1) + { + if (__waitpid (pid, NULL, WNOHANG) == 0) + continue; + if ((__read (fildes[0], buffer, bufsize)) < 1) + break; + } - *word = w_addmem (*word, word_length, max_length, buffer, buflen); - if (*word == NULL) - goto no_space; + for (i = 0; i < buflen; ++i) + { + if (strchr (ifs, buffer[i]) != NULL) + { + /* Current character is IFS */ + if (strchr (ifs_white, buffer[i]) == NULL) + { + /* Current character is IFS but not whitespace */ + if (copying == 2) + { + /* current character + * | + * V + * eg: text<space><comma><space>moretext + * + * So, strip whitespace IFS (like at the start) + */ + copying = 0; + continue; + } + + copying = 0; + /* fall through and delimit field.. */ + } + else + { + /* Current character is IFS white space */ + + /* If not copying a field, ignore it */ + if (copying != 1) + continue; + + /* End of field (search for non-ws IFS afterwards) */ + copying = 2; + } + + /* First IFS white space, or IFS non-whitespace. + * Delimit the field. Nulls are converted by w_addword. */ + if (w_addword (pwordexp, *word) == WRDE_NOSPACE) + goto no_space; + + *word = w_newword (word_length, max_length); + /* fall back round the loop.. */ + } + else + { + /* Not IFS character */ + copying = 1; + + *word = w_addchar (*word, word_length, max_length, + buffer[i]); + if (*word == NULL) + goto no_space; + } + } + } } /* Bash chops off trailing newlines, which seems sensible. */ @@ -1701,11 +1701,87 @@ envsubst: if (value == NULL) return 0; - *word = w_addstr (*word, word_length, max_length, value); - if (free_value) - free (value); + if (quoted || !pwordexp) + { + /* Quoted - no field split */ + *word = w_addstr (*word, word_length, max_length, value); + if (free_value) + free (value); - return *word ? 0 : WRDE_NOSPACE; + return *word ? 0 : WRDE_NOSPACE; + } + else + { + /* Need to field-split */ + char *value_copy = __strdup (value); /* Don't modify value */ + char *field_begin = value_copy; + int seen_nonws_ifs = 0; + + if (free_value) + free (value); + + if (value_copy == NULL) + goto no_space; + + do + { + char *field_end = field_begin; + char *next_field; + + /* If this isn't the first field, start a new word */ + if (field_begin != value_copy) + { + if (w_addword (pwordexp, *word) == WRDE_NOSPACE) + { + free (value_copy); + goto no_space; + } + + *word = w_newword (word_length, max_length); + } + + /* Skip IFS whitespace before the field */ + field_begin += strspn (field_begin, ifs_white); + + if (!seen_nonws_ifs && *field_begin == 0) + /* Nothing but whitespace */ + break; + + /* Search for the end of the field */ + field_end = field_begin + strcspn (field_begin, ifs); + + /* Set up pointer to the character after end of field and + skip whitespace IFS after it. */ + next_field = field_end + strspn (field_end, ifs_white); + + /* Skip at most one non-whitespace IFS character after the field */ + seen_nonws_ifs = 0; + if (*next_field && strchr (ifs, *next_field)) + { + seen_nonws_ifs = 1; + next_field++; + } + + /* Null-terminate it */ + *field_end = 0; + + /* Tag a copy onto the current word */ + *word = w_addstr (*word, word_length, max_length, field_begin); + + if (*word == NULL && *field_begin != '\0') + { + free (value_copy); + goto no_space; + } + + field_begin = next_field; + } + while (seen_nonws_ifs || *field_begin); + + free (value_copy); + } + + return 0; success: error = 0; @@ -1733,7 +1809,7 @@ internal_function parse_dollars (char **word, size_t *word_length, size_t *max_length, const char *words, size_t *offset, int flags, wordexp_t *pwordexp, const char *ifs, const char *ifs_white, - int quoted, int *fsplit) + int quoted) |
