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.
This commit is contained in:
Ulrich Drepper 1998-09-17 19:51:33 +00:00
parent d8f2b9ea8c
commit 9b3c7c3c71
15 changed files with 857 additions and 403 deletions

View File

@ -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.

View File

@ -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-internal.h"
#define Str(x) _Str(x)
#define _Str(x) #x
#include "pty-private.h"
void
usage (void)
/* Get libc version number. */
#include "../version.h"
#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 ();
error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
grp = getgrnam (TTY_GROUP);
gid = grp ? grp->gr_gid : getgid ();
uid = getuid ();
/* 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 ();
if (chown (pty, uid, gid))
/* 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;
return 0;
/* 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;
exit (EXIT_SUCCESS);
}

View File

@ -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
/* Length of a buffer to hold a pty name. */
#define PTYNAMELEN 15 /* "/dev/pts/65535$" */
/* Which group should pty slaves belong to: */
/* The group slave pseudo terminals belong to. */
#define TTY_GROUP "tty"
/* Communication between grantpt and pt_chown. */
#define PTY_FD 3
/* The file descriptor connected to the master pseudo terminal. */
#define PTY_FILENO 3
/* Path to the helper program that implements `grantpt' in user space. */
#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown"
/* 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 */

View File

@ -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", }, ":" },

View File

@ -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 (__waitpid (pid, NULL, WNOHANG) == 0)
continue;
if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
break;
}
if (!pwordexp)
{ /* Quoted - no field splitting */
*word = w_addmem (*word, word_length, max_length, buffer, buflen);
if (*word == NULL)
goto no_space;
while (1)
{
if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
{
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;
}
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:

View File

@ -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>
#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";
/* Prefix for master pseudo terminal nodes. */
#define _PATH_PTY "/dev/pty"
/* Open the master side of a pseudoterminal and return its file
descriptor, or -1 on error. BSD version. */
/* Letters indicating a series of pseudo terminals. */
#ifndef PTYNAME1
#define PTYNAME1 "pqrsPQRS"
#endif
const char *__libc_ptyname1 = PTYNAME1;
/* 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;
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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"
#include "pty-internal.h"
/* 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. */
/* 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 };
int
grantpt (fd)
int fd;
/* 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. */
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;
}
if (rv == 0)
*pts = buf; /* Return buffer to the user. */
else if (buf != *pts)
free (buf); /* Free what we malloced when returning an error. */
return rv;
}
/* Change the ownership and access permission of the slave pseudo
terminal associated with the master pseudo terminal specified
by FD. */
int
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];
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;
/* Some systems do it for us. */
if (__ptsname_r (fd, namebuf, PTYNAMELEN) != 0)
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;
}
/* We have to do it in user space. */
/* 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 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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
__stpcpy (__stpcpy (buf, devpts), p);
}
else if (errno == EINVAL)
#endif
if (__fxstat (_STAT_VER, fd, &st) < 0)
{
char *p;
if (buflen < strlen (_PATH_TTY) + 3)
{
__set_errno (ERANGE);
return ERANGE;
}
if (__fstat (fd, &st) < 0)
return errno;
ptyno = minor (st.st_rdev);
if (major (st.st_rdev) == 4)
ptyno -= 128;
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;
ptyno = minor (st.st_rdev);
if (major (st.st_rdev) == 4)
ptyno -= 128;
#ifdef TIOCGPTN
gotit:
#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';
if (__xstat (_STAT_VER, nbuf, &st) < 0)
return errno;
}
if (buflen < strlen (nbuf) + 1)
{
__set_errno (ERANGE);
return ERANGE;
}
cp = __stpncpy (buf, nbuf, buflen);
cp[0] = '\0';
__set_errno (save);
__set_errno (save_errno);
return 0;
}
weak_alias (__ptsname_r, ptsname_r)

View File

@ -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)

View File

@ -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;
}

View File

@ -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