diff options
author | Ulrich Drepper <drepper@redhat.com> | 1998-09-17 19:51:33 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1998-09-17 19:51:33 +0000 |
commit | 9b3c7c3c713d7018c79f0b0ca0b34d386e8a25dd (patch) | |
tree | 77802928e3a7d3163bc63c89979295da8260112a | |
parent | d8f2b9ea8cf4fb6d043f2dbbeaaca04d4fd70fc6 (diff) | |
download | glibc-9b3c7c3c713d7018c79f0b0ca0b34d386e8a25dd.tar.gz glibc-9b3c7c3c713d7018c79f0b0ca0b34d386e8a25dd.tar.xz glibc-9b3c7c3c713d7018c79f0b0ca0b34d386e8a25dd.zip |
Update.
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.
-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
diff --git a/ChangeLog b/ChangeLog index 0a7b4228fc..3125a77135 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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) { /* We are poised _at_ "$" */ switch (words[1 + *offset]) @@ -1763,12 +1839,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length, if (words[i] == ')' && words[i + 1] == ')') { (*offset) += 3; - - /* This word is subject to field-splitting as long as - * it isn't quoted. */ - if (fsplit) - *fsplit = !quoted; - /* Call parse_arith -- 0 is for "no brackets" */ return parse_arith (word, word_length, max_length, words, offset, flags, 0); @@ -1779,23 +1849,11 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length, return WRDE_CMDSUB; (*offset) += 2; - - /* This word is subject to field-splitting as long as - * it isn't quoted. */ - if (fsplit) - *fsplit = !quoted; - return parse_comm (word, word_length, max_length, words, offset, flags, quoted? NULL : pwordexp, ifs, ifs_white); case '[': (*offset) += 2; - - /* This word is subject to field-splitting as long as - * it isn't quoted. */ - if (fsplit) - *fsplit = !quoted; - /* Call parse_arith -- 1 is for "brackets" */ return parse_arith (word, word_length, max_length, words, offset, flags, 1); @@ -1803,12 +1861,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length, case '{': default: ++(*offset); /* parse_param needs to know if "{" is there */ - - /* This word is subject to field-splitting as long as - * it isn't quoted. */ - if (fsplit) - *fsplit = !quoted; - return parse_param (word, word_length, max_length, words, offset, flags, pwordexp, ifs, ifs_white, quoted); } @@ -1896,7 +1948,7 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length, case '$': error = parse_dollars (word, word_length, max_length, words, offset, - flags, pwordexp, ifs, ifs_white, 1, NULL); + flags, pwordexp, ifs, ifs_white, 1); /* The ``1'' here is to tell parse_dollars not to * split the fields. It may need to, however ("$@"). */ @@ -1978,7 +2030,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) char ifs_white[4]; char **old_wordv = pwordexp->we_wordv; size_t old_wordc = (flags & WRDE_REUSE) ? pwordexp->we_wordc : 0; - int fieldsplit_this_word = 0; if (flags & WRDE_REUSE) { @@ -2049,8 +2100,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) *whch = '\0'; } - fieldsplit_this_word = 0; - for (words_offset = 0 ; ; ++words_offset) + for (words_offset = 0 ; words[words_offset] ; ++words_offset) switch (words[words_offset]) { case '\\': @@ -2065,7 +2115,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) case '$': error = parse_dollars (&word, &word_length, &max_length, words, &words_offset, flags, pwordexp, ifs, ifs_white, - 0, &fieldsplit_this_word); + 0); if (error) goto do_error; @@ -2087,8 +2137,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) if (error) goto do_error; - fieldsplit_this_word = 1; - break; case '"': @@ -2133,8 +2181,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) default: /* Is it a word separator? */ - if (words[words_offset] != '\0' && - strchr (" \t", words[words_offset]) == NULL) + if (strchr (" \t", words[words_offset]) == NULL) { char ch = words[words_offset]; @@ -2163,29 +2210,22 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) /* If a word has been delimited, add it to the list. */ if (word != NULL) { - if (fieldsplit_this_word) - { - error = field_split_word (word, pwordexp, ifs, ifs_white); - free (word); - } - else - error = w_addword (pwordexp, word); - + error = w_addword (pwordexp, word); if (error) goto do_error; } - fieldsplit_this_word = 0; - - if (words[words_offset] == '\0') - /* End of string. */ - goto end_of_string; - word = w_newword (&word_length, &max_length); } -end_of_string: - return 0; + /* End of string */ + + /* There was a word separator at the end */ + if (word == NULL) /* i.e. w_newword */ + return 0; + + /* There was no field separator at the end */ + return w_addword (pwordexp, word); do_error: /* Error: diff --git a/sysdeps/unix/bsd/getpt.c b/sysdeps/unix/bsd/getpt.c index 3bc34b1814..ec339c8335 100644 --- a/sysdeps/unix/bsd/getpt.c +++ b/sysdeps/unix/bsd/getpt.c @@ -17,43 +17,67 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <sys/types.h> -#include <fcntl.h> #include <errno.h> -#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + + +/* Prefix for master pseudo terminal nodes. */ +#define _PATH_PTY "/dev/pty" -#include "pty-internal.h" -/* Per the FreeBSD-3.0 manpages: pty masters are named - /dev/pty[p-sP-S][0-9a-v]. I hope EIO is the right - errno in the "already open" case; it doesn't say. */ -static const char pn1[] = "pqrsPQRS"; -static const char pn2[] = "0123456789abcdefghijklmnopqrstuv"; +/* Letters indicating a series of pseudo terminals. */ +#ifndef PTYNAME1 +#define PTYNAME1 "pqrsPQRS" +#endif +const char *__libc_ptyname1 = PTYNAME1; -/* Open the master side of a pseudoterminal and return its file - descriptor, or -1 on error. BSD version. */ +/* Letters indicating the position within a series. */ +#ifndef PTYNAME2 +#define PTYNAME2 "0123456789abcdefghijklmnopqrstuv"; +#endif +const char *__libc_ptyname2 = PTYNAME2; + + +/* Open a master pseudo terminal and return its file descriptor. */ int -__getpt () +__getpt (void) { - int fd; - const char *i, *j; - char namebuf[PTYNAMELEN]; + char buf[sizeof (_PATH_PTY) + 2]; + const char *p, *q; + char *s; + + s = __stpcpy (buf, _PATH_PTY); + s[0] = '?'; + s[1] = '?'; + s[2] = 0; - strcpy (namebuf, "/dev/pty"); - namebuf[10] = '\0'; - for (i = pn1; *i; ++i) + for (p = __libc_ptyname1; *p; p++) { - namebuf[8] = *i; - for (j = pn2; *j; ++j) - { - namebuf[9] = *j; - fd = open (namebuf, O_RDWR); + s[0] = *p; + + for (q = __libc_ptyname2; *q; q++) + { + int fd; + + s[1] = *q; + + fd = __open (buf, O_RDWR); if (fd != -1) - return fd; + { + if (__isatty (fd)) + return fd; + + __close (fd); + continue; + } + if (errno != EIO) return -1; - } + } } + __set_errno (ENFILE); return -1; } diff --git a/sysdeps/unix/bsd/ptsname.c b/sysdeps/unix/bsd/ptsname.c new file mode 100644 index 0000000000..83e3890e7c --- /dev/null +++ b/sysdeps/unix/bsd/ptsname.c @@ -0,0 +1,78 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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. */ + +#include <errno.h> +#include <paths.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +/* Static buffer for `ptsname'. */ +static char buffer[sizeof (_PATH_TTY) + 2]; + + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +char * +ptsname (int fd) +{ + return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer; +} + + +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +int +__ptsname_r (int fd, char *buf, size_t buflen) +{ + int save_errno = errno; + struct stat st; + + if (buf == NULL) + { + __set_errno (EINVAL); + return EINVAL; + } + + if (!__isatty (fd)) + { + __set_errno (ENOTTY); + return ENOTTY; + } + + if (buflen < strlen (_PATH_TTY) + 3) + { + __set_errno (ERANGE); + return ERANGE; + } + + if (__ttyname_r (fd, buf, buflen) != 0) + return errno; + + buf[sizeof (_PATH_DEV) - 1] = 't'; + + if (__stat (buf, &st) < 0) + return errno; + + __set_errno (save_errno); + return 0; +} +weak_alias (__ptsname_r, ptsname_r) diff --git a/sysdeps/unix/bsd/unlockpt.c b/sysdeps/unix/bsd/unlockpt.c index b25231c865..de4db5a48e 100644 --- a/sysdeps/unix/bsd/unlockpt.c +++ b/sysdeps/unix/bsd/unlockpt.c @@ -17,25 +17,21 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <paths.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> -#include "pty-internal.h" - -/* Given a fd on a master pseudoterminal, clear a kernel lock so that - the slave can be opened. This is to avoid a race between opening the - master and calling grantpt() to take possession of the slave. - - BSD doesn't have this lock, but what it does have is revoke(). */ +/* Unlock the slave pseudo terminal associated with the master pseudo + terminal specified by FD. */ int -unlockpt (fd) - int fd; +unlockpt (int fd) { - char buf[PTYNAMELEN]; + char buf[sizeof (_PATH_TTY) + 2]; - if (__ptsname_r (fd, buf, PTYNAMELEN)) + /* BSD doesn't have a lock, but it does have `revoke'. */ + if (__ptsname_r (fd, buf, sizeof (buf))) return -1; - return revoke (buf); } diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c index 5d33a515f1..d216baa476 100644 --- a/sysdeps/unix/grantpt.c +++ b/sysdeps/unix/grantpt.c @@ -17,65 +17,158 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <assert.h> #include <errno.h> +#include <grp.h> +#include <limits.h> #include <stdlib.h> -#include <unistd.h> +#include <string.h> #include <sys/resource.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> +#include <unistd.h> -#include <assert.h> +#include "pty-private.h" + + +/* Return the result of ptsname_r in the buffer pointed to by PTS, + which should be of length BUF_LEN. If it is too long to fit in + this buffer, a sufficiently long buffer is allocated using malloc, + and returned in PTS. 0 is returned upon success, -1 otherwise. */ +static int +pts_name (int fd, char **pts, size_t buf_len) +{ + int rv; + char *buf = *pts; + + for (;;) + { + char *new_buf; + + if (buf_len) + { + rv = ptsname_r (fd, buf, buf_len); + + if (rv != 0 || memchr (buf, '\0', buf_len)) + /* We either got an error, or we succeeded and the + returned name fit in the buffer. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ -#include "pty-internal.h" + if (buf != *pts) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + __set_errno (ENOMEM); + break; + } + buf = new_buf; + } -/* Given a fd on a master pseudoterminal, chown the file associated - with the slave to the calling process, and set its group and - mode appropriately. Note that this is an unprivileged operation. */ + if (rv == 0) + *pts = buf; /* Return buffer to the user. */ + else if (buf != *pts) + free (buf); /* Free what we malloced when returning an error. */ -/* This "generic Unix" implementation works because we provide the program - /usr/libexec/pt_chown, and it only depends on ptsname() working. */ -static const char helper[] = LIBEXECDIR "/pt_chown"; -static const char *const argv[] = { "pt_chown", NULL }; + return rv; +} +/* Change the ownership and access permission of the slave pseudo + terminal associated with the master pseudo terminal specified + by FD. */ int -grantpt (fd) - int fd; +grantpt (int fd) { +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; struct stat st; - int w, pid; - char namebuf[PTYNAMELEN]; - - /* Some systems do it for us. */ - if (__ptsname_r (fd, namebuf, PTYNAMELEN) != 0) + char *grtmpbuf; + struct group grbuf; + size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX); + struct group *p; + uid_t uid; + gid_t gid; + pid_t pid; + + if (pts_name (fd, &buf, sizeof (_buf))) return -1; - if (__xstat (_STAT_VER, namebuf, &st) != 0) + + if (__stat (buf, &st) < 0) return -1; - if (st.st_uid == __getuid ()) - return 0; + /* Make sure that we own the device. */ + uid = __getuid (); + if (st.st_uid != uid) + { + if (__chown (buf, uid, st.st_gid) < 0) + goto helper; + } + + /* Get the group ID of the special `tty' group. */ + if (grbuflen == -1) + /* `sysconf' does not support _SC_GETGR_R_SIZE_MAX. + Try a moderate value. */ + grbuflen = 1024; + grtmpbuf = (char *) __alloca (grbuflen); + getgrnam_r (TTY_GROUP, &grbuf, grtmpbuf, grbuflen, &p); + gid = p ? p->gr_gid : __getgid (); + + /* Make sure the group of the device is that special group. */ + if (st.st_gid != gid) + { + if (__chown (buf, uid, gid) < 0) + goto helper; + } + + /* Make sure the permission mode is set to readable and writable by + the owner, and writable by the group. */ + if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)) + { + if (__chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0) + goto helper; + } + + return 0; - /* We have to do it in user space. */ + /* We have to use the helper program. */ + helper: pid = __fork (); if (pid == -1) return -1; else if (pid == 0) { - /* Disable core dumps in the child. */ - struct rlimit off = { 0, 0 }; - setrlimit (RLIMIT_CORE, &off); + /* Disable core dumps. */ + struct rlimit rl = { 0, 0 }; + setrlimit (RLIMIT_CORE, &rl); - /* The helper does its thing on fd PTY_FD. */ - if (fd != PTY_FD) - if (__dup2 (fd, PTY_FD) == -1) + /* We pase the master pseudo terminal as file descriptor PTY_FILENO. */ + if (fd != PTY_FILENO) + if (__dup2 (fd, PTY_FILENO) < 0) _exit (FAIL_EBADF); - __execve (helper, (char *const *) argv, 0); + execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL); _exit (FAIL_EXEC); } else { + int w; + if (__waitpid (pid, &w, 0) == -1) return -1; if (!WIFEXITED (w)) @@ -106,6 +199,5 @@ grantpt (fd) } } - /* Success. */ return 0; } diff --git a/sysdeps/unix/sysv/linux/getpt.c b/sysdeps/unix/sysv/linux/getpt.c index 0f5949d1bc..8165eccc1b 100644 --- a/sysdeps/unix/sysv/linux/getpt.c +++ b/sysdeps/unix/sysv/linux/getpt.c @@ -17,33 +17,26 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <sys/types.h> -#include <fcntl.h> #include <errno.h> +#include <fcntl.h> #include <stdlib.h> -#include <string.h> -#include "pty-internal.h" +/* Path to the master pseudo terminal cloning device. */ +#define _PATH_DEVPTMX "/dev/ptmx" -/* Per Documentation/devices.txt: pty masters are /dev/pty[p-za-e][0-9a-f]. - These strings are used also in ptsname.c. */ -const char __ptyname1[] = "pqrstuvwxyzabcde"; -const char __ptyname2[] = "0123456789abcdef"; +/* Prototype for function that opens BSD-style master pseudo-terminals. */ +int __bsd_getpt (void); -/* Open the master side of a pseudoterminal and return its file - descriptor, or -1 on error. Linux version. */ +/* Open a master pseudo terminal and return its file descriptor. */ int -__getpt () +__getpt (void) { - int fd; - const char *i, *j; static int have_dev_ptmx = 1; - char namebuf[PTYNAMELEN]; + int fd; - /* The new way: */ if (have_dev_ptmx) { - fd = __open ("/dev/ptmx", O_RDWR); + fd = __open (_PATH_DEVPTMX, O_RDWR); if (fd != -1) return fd; else @@ -55,23 +48,11 @@ __getpt () } } - /* The old way: */ - strcpy (namebuf, "/dev/pty"); - namebuf[10] = '\0'; - for (i = __ptyname1; *i; ++i) - { - namebuf[8] = *i; - for (j = __ptyname2; *j; ++j) - { - namebuf[9] = *j; - fd = __open (namebuf, O_RDWR); - if (fd != -1) - return fd; - if (errno != EIO) - return -1; - } - } - __set_errno (ENFILE); - return -1; + return __bsd_getpt (); } -weak_alias (__getpt, getpt) + +#define PTYNAME1 "pqrstuvwxyzabcde"; +#define PTYNAME2 "0123456789abcdef"; + +#define __getpt __bsd_getpt +#include <sysdeps/unix/bsd/getpt.c> diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c new file mode 100644 index 0000000000..668f13192e --- /dev/null +++ b/sysdeps/unix/sysv/linux/grantpt.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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. */ + +#include <limits.h> +#include <stdlib.h> +#include <sys/statfs.h> + +/* Constant that identifies the `devpts' filesystem. */ +#define DEVPTS_SUPER_MAGIC 0x1cd1 + +/* Prototype for function that changes ownership and access permission + for slave pseudo terminals that do not live on a `devpts' + filesystem. */ +int __unix_grantpt (int fd); + +/* Prototype for private function that gets the name of the slave + pseudo terminal in a safe way. */ +static int pts_name (int fd, char **pts, size_t buf_len); + +/* Change the ownership and access permission of the slave pseudo + terminal associated with the master pseudo terminal specified + by FD. */ +int +grantpt (int fd) +{ + struct statfs fsbuf; +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; + + if (pts_name (fd, &buf, sizeof (_buf))) + return -1; + + if (__statfs (buf, &fsbuf) < 0) + return -1; + + /* If the slave pseudo terminal lives on a `devpts' filesystem, the + ownership and access permission are already set. */ + if (fsbuf.f_type == DEVPTS_SUPER_MAGIC) + return 0; + + return __unix_grantpt (fd); +} + +#define grantpt __unix_grantpt +#include <sysdeps/unix/grantpt.c> diff --git a/sysdeps/unix/sysv/linux/ptsname.c b/sysdeps/unix/sysv/linux/ptsname.c index 052516c7ac..048ac96551 100644 --- a/sysdeps/unix/sysv/linux/ptsname.c +++ b/sysdeps/unix/sysv/linux/ptsname.c @@ -17,50 +17,50 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <sys/types.h> +#include <errno.h> +#include <paths.h> +#include <stdlib.h> +#include <string.h> #include <sys/ioctl.h> #include <sys/stat.h> +#include <sys/sysmacros.h> #include <termios.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> #include <unistd.h> -#include "pty-internal.h" - #include <stdio-common/_itoa.h> -#include <sys/sysmacros.h> -/* Given the file descriptor of a master pty, return the pathname - of the associated slave. */ +/* Directory where we can find the slave pty nodes. */ +#define _PATH_DEVPTS "/dev/pts/" -static char namebuf[PTYNAMELEN]; -extern const char __ptyname1[], __ptyname2[]; /* Defined in getpt.c. */ +/* The are declared in getpt.c. */ +extern const char *__libc_ptyname1; +extern const char *__libc_ptyname2; +/* Static buffer for `ptsname'. */ +static char buffer[sizeof (_PATH_DEVPTS) + 20]; + + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ char * -ptsname (fd) - int fd; +ptsname (int fd) { - return __ptsname_r (fd, namebuf, PTYNAMELEN) != 0 ? NULL : namebuf; + return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer; } + +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ int -__ptsname_r (fd, buf, buflen) - int fd; - char *buf; - size_t buflen; +__ptsname_r (int fd, char *buf, size_t buflen) { + int save_errno = errno; struct stat st; - int save = errno; int ptyno; - char nbuf[PTYNAMELEN], idbuf[6]; - char *cp; - -#ifdef TIOCGPTN - static int tiocgptn_works = 1; -#endif - - if (!buf) + + if (buf == NULL) { __set_errno (EINVAL); return EINVAL; @@ -73,61 +73,60 @@ __ptsname_r (fd, buf, buflen) } #ifdef TIOCGPTN - if (tiocgptn_works) + if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) { - if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) - goto gotit; - else + /* Buffer we use to print the number in. For a maximum size for + `int' of 8 bytes we never need more than 20 digits. */ + char numbuf[21]; + const char *devpts = _PATH_DEVPTS; + const size_t devptslen = strlen (devpts); + char *p; + + numbuf[20] = '\0'; + p = _itoa_word (ptyno, &numbuf[20], 10, 0); + + if (buflen < devptslen + strlen (p) + 1) { - if(errno != EINVAL) - return errno; - else - tiocgptn_works = 0; + __set_errno (ERANGE); + return ERANGE; } - } -#endif - if (__fxstat (_STAT_VER, fd, &st) < 0) - return errno; - ptyno = minor (st.st_rdev); - if (major (st.st_rdev) == 4) - ptyno -= 128; - -#ifdef TIOCGPTN - gotit: + __stpcpy (__stpcpy (buf, devpts), p); + } + else if (errno == EINVAL) #endif - /* Two different possible naming schemes for pty slaves: - the SVr4 way. */ - - idbuf[5] = '\0'; - __stpcpy (__stpcpy (nbuf, "/dev/pts/"), - _itoa_word (ptyno, &idbuf[5], 10, 0)); - if (__xstat (_STAT_VER, nbuf, &st) < 0) { - if (errno != ENOENT) - return errno; - - /* ...and the BSD way. */ - nbuf[5] = 't'; - nbuf[7] = 'y'; - nbuf[8] = __ptyname1[ptyno / 16]; - nbuf[9] = __ptyname2[ptyno % 16]; - nbuf[10] = '\0'; + char *p; + + if (buflen < strlen (_PATH_TTY) + 3) + { + __set_errno (ERANGE); + return ERANGE; + } - if (__xstat (_STAT_VER, nbuf, &st) < 0) + if (__fstat (fd, &st) < 0) return errno; - } - if (buflen < strlen (nbuf) + 1) - { - __set_errno (ERANGE); - return ERANGE; - } + ptyno = minor (st.st_rdev); + if (major (st.st_rdev) == 4) + ptyno -= 128; - cp = __stpncpy (buf, nbuf, buflen); - cp[0] = '\0'; + if (ptyno / 16 >= strlen (__libc_ptyname1)) + { + __set_errno (ENOTTY); + return ENOTTY; + } + + p = __stpcpy (buf, _PATH_TTY); + p[0] = __libc_ptyname1[ptyno / 16]; + p[1] = __libc_ptyname2[ptyno % 16]; + p[2] = '\0'; + } + + if (__stat (buf, &st) < 0) + return errno; - __set_errno (save); + __set_errno (save_errno); return 0; } weak_alias (__ptsname_r, ptsname_r) diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/socket.S b/sysdeps/unix/sysv/linux/sparc/sparc64/socket.S new file mode 100644 index 0000000000..84f2eeca2f --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/socket.S @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Miguel de Icaza <miguel@gnu.ai.mit.edu>, 1997. + + 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. */ + +#include <sysdep.h> +#include <socketcall.h> + +#define P(a, b) P2(a, b) +#define P2(a, b) a##b + +#ifndef NARGS +#ifdef socket +#error NARGS not defined +#endif +#define NARGS 3 +#endif + + .text +/* The socket-oriented system calls are handled unusually in Linux. + They are all gated through the single `socketcall' system call number. + `socketcall' takes two arguments: the first is the subcode, specifying + which socket function is being called; and the second is a pointer to + the arguments to the specific function. + + The .S files for the other calls just #define socket and #include this. */ + +#ifndef __socket +#define __socket P(__,socket) +#endif + +.globl __socket +ENTRY (__socket) + + /* Drop up to 6 arguments (recvfrom) into the memory allocated by + the caller for varargs, since that's really what we have. */ + stx %o0, [%sp + STACK_BIAS + 128 + 0] + stx %o1, [%sp + STACK_BIAS + 128 + 8] +#if NARGS > 2 + stx %o2, [%sp + STACK_BIAS + 128 + 16] +#if NARGS > 3 + stx %o3, [%sp + STACK_BIAS + 128 + 24] +#if NARGS > 4 + stx %o4, [%sp + STACK_BIAS + 128 + 32] +#if NARGS > 5 + stx %o5, [%sp + STACK_BIAS + 128 + 40] +#endif +#endif +#endif +#endif + + mov P(SOCKOP_,socket), %o0 /* arg 1: socket subfunction */ + add %sp, STACK_BIAS + 128, %o1 /* arg 2: parameter block */ + LOADSYSCALL(socketcall) + ta 0x6d + + bcs,pn %xcc, 1f + nop + retl + nop + +1: SYSCALL_ERROR_HANDLER + +END (__socket) + +weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/unlockpt.c b/sysdeps/unix/sysv/linux/unlockpt.c index e20545fe80..4df33198ef 100644 --- a/sysdeps/unix/sysv/linux/unlockpt.c +++ b/sysdeps/unix/sysv/linux/unlockpt.c @@ -17,33 +17,33 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <sys/ioctl.h> -#include <termios.h> #include <errno.h> #include <stdlib.h> +#include <sys/ioctl.h> +#include <termios.h> + -/* Given a fd on a master pseudoterminal, clear a kernel lock so that - the slave can be opened. This is to avoid a race between opening the - master and calling grantpt() to take possession of the slave. */ +/* Unlock the slave pseudo terminal associated with the master pseudo + terminal specified by FD. */ int -unlockpt (fd) - int fd __attribute__ ((unused)); +unlockpt (int fd) { #ifdef TIOCSPTLCK - int serrno = errno; + int save_errno = errno; int unlock = 0; if (__ioctl (fd, TIOCSPTLCK, &unlock)) { if (errno == EINVAL) { - __set_errno (serrno); + __set_errno (save_errno); return 0; } else return -1; } #endif - /* On pre-/dev/ptmx kernels this function should be a no-op. */ + /* If we have no TIOCSPTLCK ioctl, all slave pseudo terminals are + unlocked by default. */ return 0; } diff --git a/sysdeps/unix/sysv/sysv4/bits/utsname.h b/sysdeps/unix/sysv/sysv4/bits/utsname.h index bf2c0a8da5..dfe46b851b 100644 --- a/sysdeps/unix/sysv/sysv4/bits/utsname.h +++ b/sysdeps/unix/sysv/sysv4/bits/utsname.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,7 +16,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _UTSNAME_H +#ifndef _SYS_UTSNAME_H # error "Never include <bits/utsname.h> directly; use <sys/utsname.h> instead." #endif |