diff options
author | Roland McGrath <roland@gnu.org> | 1996-05-23 03:15:42 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1996-05-23 03:15:42 +0000 |
commit | fa0bc87c32d02cd81ec4d0ae00e0d943c683e6e1 (patch) | |
tree | 197250e2e9e1f2c900d3bf042dbf14898dc0fb73 | |
parent | Wed May 22 21:21:15 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> (diff) | |
download | glibc-fa0bc87c32d02cd81ec4d0ae00e0d943c683e6e1.tar.gz glibc-fa0bc87c32d02cd81ec4d0ae00e0d943c683e6e1.tar.bz2 glibc-fa0bc87c32d02cd81ec4d0ae00e0d943c683e6e1.zip |
Wed May 22 22:10:01 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* stdlib/canonicalize.c: New file.
* stdlib/stdlib.h: Declare canonicalize_file_name, realpath.
* stdlib/Makefile (routines): Add canonicalize.
* posix/unistd.h: Declare __canonicalize_directory_name_internal.
Thu May 23 00:01:10 1996 Ulrich Drepper <drepper@cygnus.com>
* db/recno/rec_seq.c: Prevent `sccsid' definition by using the
same #if condition as in the other db files.
* intl/Makefile: Add -Wno-unused CFLAGS for compilation of
bindtextdom.c, finddomain.c, and localealias.c.
* intl/dcgettext.c: Don't define prototype for getcwd() when
compiling in glibc.
* libio/cleanup.c: Add prototype for _IO_register_cleanup.
* libio/filedoalloc.c, libio/fileops.c, libio/iopopen.c: Don't
define _POSIX_SOURCE unconditionally.
* libio/filedoalloc.c, libio/iopopen.c: Include <unistd.h> if
compiling in glibc.
* libio/fileops.c (_IO_file_close_it): Don't sync file, call
flush instead. This relaxes the rules from POSIX.1 about
changing the active handle a bit.
* libio/iofopncook.c (struct _IO_cookie_file): Move definition
into <libio.h>.
Add prototypes for local functions to prevent warnings.
* libio/iopopen.c: Change prototypes for _IO_fork, _IO_pipe, and
_IO_DUP2 to contain complete parameter list.
* libio/libio.h: Add definition of struct _IO_cookie_file.
* libio/libioP.h: Add prototypes for _IO_vasprintf, _IO_vdprintf,
and _IO_vsnprintf.
* libio/memstream.c: Include <stdio.h>.
* libio/stdio.h: Add prototypes for fopencookie,
__stdio_gen_tempname, __vfscanf, __vsscanf, and __vsnprintf.
* libio/strops.c: Avoid useless expression in `for' initializer.
* locale/findlocale.c: Add some casts to prevent warnings.
* locale/programs/locfile.c (write_locale_data): Don't use
double `/' in locale binary file.
* posix/unistd.h: Remove prototype for `reboot'.
Update from bind-4.9.4-T1A.
* resolv/Makefile (routines): Add inet_ntop and inet_pton.
* resolv/arpa/nameser.h: Add definition of IN6ADDRSZ.
* resolv/gethnamaddr.c, resolv/getnetnamadr.c, resolv/res_comp.c,
resolv/res_debug.c, resolv/res_init.c
* resolv/inet_ntop.c, resolv/inet_pton.c: New files.
* resolv/resolv.h: Add RES_USE_INET6 flag.
(__dn_isvalid): Renamed to __res_dnok.
Add prototypes for __res_ownok and __res_mailok.
* stdio-common/Makefile: Add -Wno-unused to CFLAGS for _itoa.c.
* stdio-common/getline.c, stdio-common/vfscanf.c,
sysdeps/posix/tempname.c: Don't use <ansidecl.h> anymore.
* sysdeps/unix/sysv/linux/Makefile [$subdir == misc]
(sysdep_routines): Add s_reboot.
(install-others): Add $(includedir)/sys/syscall.h.
New rule for $(includedir)/sys/syscall.h to produce from
<asm/unistd.h>.
* sysdeps/unix/sysv/linux/reboot.c: New file. Make single
argument function call 3 argument system call.
* sysdeps/unix/sysv/linux/sys/reboot.h: New file. Linux specific
definition for reboot function.
* sysdeps/unix/sysv/linux/syscall.h: Remove old and obsolete
comment.
* sysdeps/unix/sysv/linux/syscalls.list: Rename function for
reboot syscall to __syscall_reboot.
* wcsmbs/wchar.h: Protect prototypes for wcstof and wcstold by
__USE_GNU, not USE_GNU.
Tue May 21 21:55:49 1996 David Mosberger-Tang <davidm@AZStarNet.com>
* locale/programs/charset.c, locale/programs/ld-collate.c:
Add casts to prevent warnings on 64-bit machines.
* locale/programs/ld-monetary.c: Don't do unnecessary tests for
int_frac_digits and frac_digits which only produce warnings.
Mon May 13 23:45:29 1996 David Mosberger-Tang <davidm@AZStarNet.com>
* inet/arpa/inet.h: Backup return type of inet_addr to u_long.
* resolv/inet_addr.c: Likewise.
* resolv/Makefile (distribute): Add res_hconf.h
(routines): Add res_hconf.
* resolv/gethnamaddr.c: Add support for /etc/host.conf.
* resolv/res_init.c: Initialize /etc/host.conf reader.
* resolv/res_hconf.c, resolv/res_hconf.h: New files.
Implementation of reading /etc/host.conf.
Wed May 22 21:21:15 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* Rules (%.out rules): Prepend $($*-ENV) to the command.
* sysdeps/unix/sysv/linux/i386/brk.c (___brk_addr): Define as weak
alias for __curbrk.
Wed May 22 19:37:27 1996 Miles Bader <miles@gnu.ai.mit.edu>
* hurd/hurdexec.c (_hurd_exec): Pass INIT_TRACEMASK.
* hurd/hurdmsg.c (set_int): Support INIT_TRACEMASK.
Wed May 22 18:47:31 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* sysdeps/mach/hurd/getcwd.c
(_hurd_canonicalize_directory_name_internal): New function, broken out
of __getcwd.
(__getcwd): Use it.
(__canonicalize_directory_name_internal): New function using it.
* sysdeps/posix/getcwd.c (__canonicalize_directory_name_internal): New
function, broken out of __getcwd.
(__getcwd): Use it.
Wed May 22 18:14:05 1996 Miles Bader <miles@gnu.ai.mit.edu>
* string/argz-create.c (__argz_create): Correctly calculate length.
* string/argz-extract.c (__argz_extract): Add terminating 0 entry.
* hurd/hurdstartup.c (_hurd_startup): ... and don't so here.
[HAVE_VMSDIR_H]: Include "vmsdir.h".
(glob) [VMS]: Don't grok ~.
51 files changed, 2371 insertions, 307 deletions
@@ -1,6 +1,157 @@ +Wed May 22 22:10:01 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * stdlib/canonicalize.c: New file. + * stdlib/stdlib.h: Declare canonicalize_file_name, realpath. + * stdlib/Makefile (routines): Add canonicalize. + + * posix/unistd.h: Declare __canonicalize_directory_name_internal. + +Thu May 23 00:01:10 1996 Ulrich Drepper <drepper@cygnus.com> + + * db/recno/rec_seq.c: Prevent `sccsid' definition by using the + same #if condition as in the other db files. + + * intl/Makefile: Add -Wno-unused CFLAGS for compilation of + bindtextdom.c, finddomain.c, and localealias.c. + + * intl/dcgettext.c: Don't define prototype for getcwd() when + compiling in glibc. + + * libio/cleanup.c: Add prototype for _IO_register_cleanup. + + * libio/filedoalloc.c, libio/fileops.c, libio/iopopen.c: Don't + define _POSIX_SOURCE unconditionally. + + * libio/filedoalloc.c, libio/iopopen.c: Include <unistd.h> if + compiling in glibc. + + * libio/fileops.c (_IO_file_close_it): Don't sync file, call + flush instead. This relaxes the rules from POSIX.1 about + changing the active handle a bit. + + * libio/iofopncook.c (struct _IO_cookie_file): Move definition + into <libio.h>. + Add prototypes for local functions to prevent warnings. + + * libio/iopopen.c: Change prototypes for _IO_fork, _IO_pipe, and + _IO_DUP2 to contain complete parameter list. + + * libio/libio.h: Add definition of struct _IO_cookie_file. + + * libio/libioP.h: Add prototypes for _IO_vasprintf, _IO_vdprintf, + and _IO_vsnprintf. + + * libio/memstream.c: Include <stdio.h>. + + * libio/stdio.h: Add prototypes for fopencookie, + __stdio_gen_tempname, __vfscanf, __vsscanf, and __vsnprintf. + + * libio/strops.c: Avoid useless expression in `for' initializer. + + * locale/findlocale.c: Add some casts to prevent warnings. + + * locale/programs/locfile.c (write_locale_data): Don't use + double `/' in locale binary file. + + * posix/unistd.h: Remove prototype for `reboot'. + + Update from bind-4.9.4-T1A. + * resolv/Makefile (routines): Add inet_ntop and inet_pton. + * resolv/arpa/nameser.h: Add definition of IN6ADDRSZ. + * resolv/gethnamaddr.c, resolv/getnetnamadr.c, resolv/res_comp.c, + resolv/res_debug.c, resolv/res_init.c + + * resolv/inet_ntop.c, resolv/inet_pton.c: New files. + + * resolv/resolv.h: Add RES_USE_INET6 flag. + (__dn_isvalid): Renamed to __res_dnok. + Add prototypes for __res_ownok and __res_mailok. + + * stdio-common/Makefile: Add -Wno-unused to CFLAGS for _itoa.c. + + * stdio-common/getline.c, stdio-common/vfscanf.c, + sysdeps/posix/tempname.c: Don't use <ansidecl.h> anymore. + + * sysdeps/unix/sysv/linux/Makefile [$subdir == misc] + (sysdep_routines): Add s_reboot. + (install-others): Add $(includedir)/sys/syscall.h. + New rule for $(includedir)/sys/syscall.h to produce from + <asm/unistd.h>. + + * sysdeps/unix/sysv/linux/reboot.c: New file. Make single + argument function call 3 argument system call. + + * sysdeps/unix/sysv/linux/sys/reboot.h: New file. Linux specific + definition for reboot function. + + * sysdeps/unix/sysv/linux/syscall.h: Remove old and obsolete + comment. + + * sysdeps/unix/sysv/linux/syscalls.list: Rename function for + reboot syscall to __syscall_reboot. + + * wcsmbs/wchar.h: Protect prototypes for wcstof and wcstold by + __USE_GNU, not USE_GNU. + +Tue May 21 21:55:49 1996 David Mosberger-Tang <davidm@AZStarNet.com> + + * locale/programs/charset.c, locale/programs/ld-collate.c: + Add casts to prevent warnings on 64-bit machines. + + * locale/programs/ld-monetary.c: Don't do unnecessary tests for + int_frac_digits and frac_digits which only produce warnings. + +Mon May 13 23:45:29 1996 David Mosberger-Tang <davidm@AZStarNet.com> + + * inet/arpa/inet.h: Backup return type of inet_addr to u_long. + * resolv/inet_addr.c: Likewise. + + * resolv/Makefile (distribute): Add res_hconf.h + (routines): Add res_hconf. + + * resolv/gethnamaddr.c: Add support for /etc/host.conf. + + * resolv/res_init.c: Initialize /etc/host.conf reader. + + * resolv/res_hconf.c, resolv/res_hconf.h: New files. + Implementation of reading /etc/host.conf. + +Wed May 22 21:21:15 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * Rules (%.out rules): Prepend $($*-ENV) to the command. + + * sysdeps/unix/sysv/linux/i386/brk.c (___brk_addr): Define as weak + alias for __curbrk. + +Wed May 22 19:37:27 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * hurd/hurdexec.c (_hurd_exec): Pass INIT_TRACEMASK. + * hurd/hurdmsg.c (set_int): Support INIT_TRACEMASK. + +Wed May 22 18:47:31 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * sysdeps/mach/hurd/getcwd.c + (_hurd_canonicalize_directory_name_internal): New function, broken out + of __getcwd. + (__getcwd): Use it. + (__canonicalize_directory_name_internal): New function using it. + + * sysdeps/posix/getcwd.c (__canonicalize_directory_name_internal): New + function, broken out of __getcwd. + (__getcwd): Use it. + +Wed May 22 18:14:05 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * string/argz-create.c (__argz_create): Correctly calculate length. + + * string/argz-extract.c (__argz_extract): Add terminating 0 entry. + * hurd/hurdstartup.c (_hurd_startup): ... and don't so here. + Wed May 22 17:22:14 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> * posix/glob.c [VMS]: Don't include <pwd.h>. + [HAVE_VMSDIR_H]: Include "vmsdir.h". + (glob) [VMS]: Don't grok ~. Wed May 22 14:46:53 1996 Miles Bader <miles@gnu.ai.mit.edu> @@ -96,13 +96,13 @@ ifneq "$(strip $(tests))" "" # These are the implicit rules for making test outputs # from the test programs and whatever input files are present. $(objpfx)%.out: %.args $(objpfx)% %.input - $(built-program-cmd) `cat $(word 1,$^)` < $(word 3,$^) > $@ + $($*-ENV) $(built-program-cmd) `cat $(word 1,$^)` < $(word 3,$^) > $@ $(objpfx)%.out: %.args $(objpfx)% - $(built-program-cmd) `cat $(word 1,$^)` > $@ + $($*-ENV) $(built-program-cmd) `cat $(word 1,$^)` > $@ $(objpfx)%.out: %.input $(objpfx)% - $(built-program-cmd) < $(word 1,$^) > $@ + $($*-ENV) $(built-program-cmd) < $(word 1,$^) > $@ $(objpfx)%.out: /dev/null $(objpfx)% # Make it 2nd arg for canned sequence. - $(built-program-cmd) > $@ + $($*-ENV) $(built-program-cmd) > $@ endif # tests .PHONY: distclean realclean subdir_distclean subdir_realclean \ diff --git a/db/recno/rec_seq.c b/db/recno/rec_seq.c index f80992c598..2f8c7695c5 100644 --- a/db/recno/rec_seq.c +++ b/db/recno/rec_seq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -#ifndef lint +#if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94"; #endif /* not lint */ diff --git a/inet/arpa/inet.h b/inet/arpa/inet.h index 2413dcf76e..6cb672f336 100644 --- a/inet/arpa/inet.h +++ b/inet/arpa/inet.h @@ -42,7 +42,7 @@ #include <sys/types.h> __BEGIN_DECLS -u_int32_t inet_addr __P((const char *)); +u_long inet_addr __P((const char *)); int inet_aton __P((const char *, struct in_addr *)); u_int32_t inet_lnaof __P((struct in_addr)); struct in_addr inet_makeaddr __P((u_int32_t , u_int32_t)); diff --git a/intl/Makefile b/intl/Makefile index 9d97088d4a..01e1383cb8 100644 --- a/intl/Makefile +++ b/intl/Makefile @@ -50,3 +50,7 @@ test ! -d CVS || cvs commit -m'Updated from $<' $@ endef endif + +CFLAGS-bindtextdom.c = -Wno-unused +CFLAGS-finddomain.c = -Wno-unused +CFLAGS-localealias.c = -Wno-unused diff --git a/intl/dcgettext.c b/intl/dcgettext.c index 6c8963f720..a18be16631 100644 --- a/intl/dcgettext.c +++ b/intl/dcgettext.c @@ -87,13 +87,13 @@ void free (); file and the name space must not be polluted. */ # define getcwd __getcwd # define stpcpy __stpcpy -#endif - -#if !defined HAVE_GETCWD && !defined _LIBC -char *getwd (); -# define getcwd(buf, max) getwd (buf) #else +# if !defined HAVE_GETCWD +char *getwd (); +# define getcwd(buf, max) getwd (buf) +# else char *getcwd (); +# endif #endif /* Amount to increase buffer size by in each try. */ diff --git a/libio/cleanup.c b/libio/cleanup.c index a0c5052d39..1f316ebb33 100644 --- a/libio/cleanup.c +++ b/libio/cleanup.c @@ -4,6 +4,9 @@ typedef void (*voidfunc) __P((void)); +/* Prototype. */ +static void DEFUN_VOID (_IO_register_cleanup); + static void DEFUN_VOID(_IO_register_cleanup) { diff --git a/libio/filedoalloc.c b/libio/filedoalloc.c index 0ebb75d9c5..f71656478c 100644 --- a/libio/filedoalloc.c +++ b/libio/filedoalloc.c @@ -41,13 +41,18 @@ the executable file might be covered by the GNU General Public License. */ /* Modified for GNU iostream by Per Bothner 1991, 1992. */ -#define _POSIX_SOURCE +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif #include "libioP.h" #include <sys/types.h> #include <sys/stat.h> #ifdef __STDC__ #include <stdlib.h> #endif +#ifdef _LIBC +# include <unistd.h> +#endif /* * Allocate a file buffer, or switch to unbuffered I/O. diff --git a/libio/fileops.c b/libio/fileops.c index 89381ec699..828f99db96 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -24,7 +24,9 @@ the executable file might be covered by the GNU General Public License. */ /* written by Per Bothner (bothner@cygnus.com) */ -#define _POSIX_SOURCE +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif #include "libioP.h" #include <fcntl.h> #include <sys/types.h> @@ -102,11 +104,11 @@ int DEFUN(_IO_file_close_it, (fp), register _IO_FILE* fp) { - int sync_status, close_status; + int write_status, close_status; if (!_IO_file_is_open(fp)) return EOF; - sync_status = _IO_file_sync (fp); + write_status = _IO_do_flush (fp); _IO_unsave_markers(fp); @@ -122,7 +124,7 @@ DEFUN(_IO_file_close_it, (fp), fp->_fileno = EOF; fp->_offset = _IO_pos_BAD; - return close_status ? close_status : sync_status; + return close_status ? close_status : write_status; } void diff --git a/libio/iofopncook.c b/libio/iofopncook.c index 0b57ecd344..989f6d6fe7 100644 --- a/libio/iofopncook.c +++ b/libio/iofopncook.c @@ -23,14 +23,18 @@ This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ #include <libioP.h> +#include <stdio.h> #include <stdlib.h> -struct _IO_cookie_file { - struct _IO_FILE file; - const void *vtable; - void *cookie; - _IO_cookie_io_functions_t io_functions; -}; + +/* Prototyped for local functions. */ +static _IO_ssize_t _IO_cookie_read __P ((register _IO_FILE* fp, void* buf, + _IO_ssize_t size)); +static _IO_ssize_t _IO_cookie_write __P ((register _IO_FILE* fp, + const void* buf, _IO_ssize_t size)); +static _IO_fpos_t _IO_cookie_seek __P ((_IO_FILE *fp, _IO_off_t offset, + int dir)); +static int _IO_cookie_close __P ((_IO_FILE* fp)); static _IO_ssize_t diff --git a/libio/iopopen.c b/libio/iopopen.c index 349a4cc8d6..b9ee737502 100644 --- a/libio/iopopen.c +++ b/libio/iopopen.c @@ -24,7 +24,9 @@ the executable file might be covered by the GNU General Public License. */ /* written by Per Bothner (bothner@cygnus.com) */ -#define _POSIX_SOURCE +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif #include "libioP.h" #if _IO_HAVE_SYS_WAIT #include <signal.h> @@ -32,24 +34,27 @@ the executable file might be covered by the GNU General Public License. */ #ifdef __STDC__ #include <stdlib.h> #endif +#ifdef _LIBC +# include <unistd.h> +#endif #include <sys/types.h> #include <sys/wait.h> #ifndef _IO_fork #define _IO_fork vfork /* defined in libiberty, if needed */ -_IO_pid_t _IO_fork(); +extern _IO_pid_t _IO_fork __P ((void)); #endif #endif /* _IO_HAVE_SYS_WAIT */ #ifndef _IO_pipe #define _IO_pipe pipe -extern int _IO_pipe(); +extern int _IO_pipe __P ((int des[2])); #endif #ifndef _IO_dup2 #define _IO_dup2 dup2 -extern int _IO_dup2(); +extern int _IO_dup2 __P ((int fd, int fd2)); #endif #ifndef _IO_waitpid diff --git a/libio/libio.h b/libio/libio.h index fce8a77bf7..b498f125eb 100644 --- a/libio/libio.h +++ b/libio/libio.h @@ -228,6 +228,16 @@ extern struct _IO_FILE_plus _IO_stdin_, _IO_stdout_, _IO_stderr_; #define _IO_stdout ((_IO_FILE*)(&_IO_stdout_)) #define _IO_stderr ((_IO_FILE*)(&_IO_stderr_)) + +/* Special file type for fopencookie function. */ +struct _IO_cookie_file { + struct _IO_FILE file; + const void *vtable; + void *cookie; + _IO_cookie_io_functions_t io_functions; +}; + + #ifdef __cplusplus extern "C" { #endif diff --git a/libio/libioP.h b/libio/libioP.h index a955151ade..173e75b86f 100644 --- a/libio/libioP.h +++ b/libio/libioP.h @@ -266,6 +266,13 @@ extern void _IO_str_init_static __P((_IO_FILE *, char*, int, char*)); extern void _IO_str_init_readonly __P((_IO_FILE *, const char*, int)); extern _IO_ssize_t _IO_str_count __P ((_IO_FILE*)); +extern int _IO_vasprintf __P ((char **result_ptr, __const char *format, + _IO_va_list args)); +extern int _IO_vdprintf __P ((int d, __const char *format, _IO_va_list arg)); +extern int _IO_vsnprintf __P ((char *string, _IO_size_t maxlen, + __const char *format, _IO_va_list args)); + + extern _IO_size_t _IO_getline __P((_IO_FILE*,char*,_IO_size_t,int,int)); extern _IO_ssize_t _IO_getdelim __P((char**, _IO_size_t*, int, _IO_FILE*)); extern double _IO_strtod __P((const char *, char **)); diff --git a/libio/memstream.c b/libio/memstream.c index 71519a5190..a2fe8447cb 100644 --- a/libio/memstream.c +++ b/libio/memstream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996 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 @@ -18,6 +18,7 @@ Boston, MA 02111-1307, USA. */ #include "strfile.h" #include "libioP.h" +#include <stdio.h> #include <stdlib.h> diff --git a/libio/stdio.h b/libio/stdio.h index bd271ce1fb..70728ed8d9 100644 --- a/libio/stdio.h +++ b/libio/stdio.h @@ -108,6 +108,8 @@ extern int fgetc __P ((FILE *)); extern int fgetpos __P ((FILE* fp, fpos_t *pos)); extern char* fgets __P ((char*, int, FILE*)); extern FILE* fopen __P ((__const char*, __const char*)); +extern FILE* fopencookie __P ((void *cookie, __const char *mode, + _IO_cookie_io_functions_t io_functions)); extern int fprintf __P ((FILE*, __const char* format, ...)); extern int fputc __P ((int, FILE*)); extern int fputs __P ((__const char *str, FILE *fp)); @@ -138,6 +140,9 @@ extern int sprintf __P ((char*, __const char* format, ...)); extern int sscanf __P ((__const char* string, __const char* format, ...)); extern FILE* tmpfile __P ((void)); extern char* tmpnam __P ((char*)); +extern char *__stdio_gen_tempname __P ((__const char *dir, __const char *pfx, + int dir_search, size_t *lenptr, + FILE **streamptr)); extern int ungetc __P ((int c, FILE* fp)); extern int vfprintf __P ((FILE *fp, char __const *fmt0, _G_va_list)); extern int vprintf __P ((char __const *fmt, _G_va_list)); @@ -147,8 +152,10 @@ extern int vsprintf __P ((char* string, __const char* format, _G_va_list)); extern int dprintf __P ((int, __const char *, ...)); extern int vdprintf __P ((int, __const char *, _G_va_list)); extern int vfscanf __P ((FILE*, __const char *, _G_va_list)); +extern int __vfscanf __P ((FILE*, __const char *, _G_va_list)); extern int vscanf __P ((__const char *, _G_va_list)); extern int vsscanf __P ((__const char *, __const char *, _G_va_list)); +extern int __vsscanf __P ((__const char *, __const char *, _G_va_list)); #endif #if !defined(__STRICT_ANSI__) || defined(_POSIX_SOURCE) @@ -166,6 +173,7 @@ extern _IO_ssize_t __getline __P ((char **, size_t *, FILE *)); extern int snprintf __P ((char *, size_t, __const char *, ...)); extern int __snprintf __P ((char *, size_t, __const char *, ...)); extern int vsnprintf __P ((char *, size_t, __const char *, _G_va_list)); +extern int __vsnprintf __P ((char *, size_t, __const char *, _G_va_list)); extern int asprintf __P ((char **, const char *, ...)); extern int vasprintf __P ((char **, const char *, _G_va_list)); diff --git a/libio/strops.c b/libio/strops.c index f4f45259fb..98c5b263d5 100644 --- a/libio/strops.c +++ b/libio/strops.c @@ -51,7 +51,7 @@ DEFUN(_IO_str_init_static, (fp, ptr, size, pstart), This can lose in pathological cases (ptr near the end of the address space). A better solution might be to adjust the size on underflow/overflow. FIXME. */ - for (s; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; ) + for ( ; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; ) size = s; size = s; #else diff --git a/locale/findlocale.c b/locale/findlocale.c index 35b1971aa9..5e87a33886 100644 --- a/locale/findlocale.c +++ b/locale/findlocale.c @@ -85,7 +85,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len, /* We really have to load some data. First see whether the name is an alias. Please note that this makes it impossible to have "C" or "POSIX" as aliases. */ - loc_name = _nl_expand_alias (*name); + loc_name = (char *) _nl_expand_alias (*name); if (loc_name == NULL) /* It is no alias. */ loc_name = *name; @@ -144,7 +144,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len, /* If the addressed locale is already available it should be freed. If we would not do this switching back and force between two locales would slowly eat up all memory.*/ - free (loc_name); + free ((void *) loc_name); if (locale_file->decided == 0) _nl_load_locale (locale_file, category); diff --git a/locale/programs/charset.c b/locale/programs/charset.c index 2e2f63bd9a..a7f988d3a5 100644 --- a/locale/programs/charset.c +++ b/locale/programs/charset.c @@ -66,7 +66,7 @@ charset_find_value (const struct charset_t *cs, const char *name, size_t len) if (find_entry ((hash_table *) &cs->char_table, name, len, &result) < 0) return ILLEGAL_CHAR_VALUE; - return (unsigned int) result; + return (unsigned int) ((unsigned long int) result); } @@ -81,7 +81,8 @@ insert_char (struct linereader *lr, struct charset_t *cs, int bytes, if (to == NULL) { - if (insert_entry (&cs->char_table, from, strlen (from), (void *) value) + if (insert_entry (&cs->char_table, from, strlen (from), + (void *) (unsigned long int) value) < 0) lr_error (lr, _("duplicate character name `%s'"), from); @@ -126,7 +127,8 @@ insert_char (struct linereader *lr, struct charset_t *cs, int bytes, { sprintf (&buf[prefix_len], "%0d", cnt); - if (insert_entry (&cs->char_table, buf, len1, (void *) cnt) < 0) + if (insert_entry (&cs->char_table, buf, len1, + (void *) (unsigned long int) cnt) < 0) lr_error (lr, _("duplicate character name `%s'"), buf); } } diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c index 629df90ced..4bdf0b2256 100644 --- a/locale/programs/ld-collate.c +++ b/locale/programs/ld-collate.c @@ -233,7 +233,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset) else if (find_entry (&collate->symbols, patch->token, toklen, &ptmp) >= 0) { - value = (unsigned int) ptmp; + value = (unsigned long int) ptmp; } else value = 0; diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c index a717377a8b..5efa969baa 100644 --- a/locale/programs/ld-monetary.c +++ b/locale/programs/ld-monetary.c @@ -164,8 +164,12 @@ value for field `%s' in category `%s' must not be the empty string"), value for field `%s' in category `%s' must be in range %d...%d"), \ #cat, "LC_MONETARY", min, max) +#if 0 + /* The following two test are not really necessary because all values + the variable could have are valid. */ TEST_ELEM (int_frac_digits, -128, 127); /* No range check. */ TEST_ELEM (frac_digits, -128, 127); /* No range check. */ +#endif TEST_ELEM (p_cs_precedes, -1, 1); TEST_ELEM (p_sep_by_space, -1, 2); TEST_ELEM (n_cs_precedes, -1, 1); diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c index 89dc6bb539..3bbe479017 100644 --- a/locale/programs/locfile.c +++ b/locale/programs/locfile.c @@ -935,7 +935,7 @@ write_locale_data (const char *output_path, const char *category, int fd; char *fname; - asprintf (&fname, "%s/%s", output_path, category); + asprintf (&fname, "%s%s", output_path, category); fd = creat (fname, 0666); if (fd == -1) { @@ -944,7 +944,7 @@ write_locale_data (const char *output_path, const char *category, if (errno == EISDIR) { free (fname); - asprintf (&fname, "%1$s/%2$s/SYS_%2$s", output_path, category); + asprintf (&fname, "%1$s%2$s/SYS_%2$s", output_path, category); fd = creat (fname, 0666); if (fd == -1) save_err = errno; diff --git a/manual/errno.texi b/manual/errno.texi index a00ac7859d..6b8b9834ef 100644 --- a/manual/errno.texi +++ b/manual/errno.texi @@ -836,7 +836,7 @@ of error you get if you request them and they are not supported. @end deftypevr @comment errno.h -@comment ISO C: Invalid or incomplete multibyte or wide character +@comment ISO: Invalid or incomplete multibyte or wide character @deftypevr Macro int EILSEQ @comment errno 106 @c DO NOT REMOVE While decoding a multibyte character the function came along an invalid diff --git a/posix/unistd.h b/posix/unistd.h index 15c40c434d..89c8fd4db9 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -252,6 +252,16 @@ extern char *getcwd __P ((char *__buf, size_t __size)); If the environment variable `PWD' is set, and its value is correct, that value is used. */ extern char *get_current_dir_name __P ((void)); + +/* Get the canonical absolute name of the named directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined or + SIZE was too small. If successful, returns BUF. In GNU, if BUF is + NULL, an array is allocated with `malloc'; the array is SIZE bytes long, + unless SIZE <= 0, in which case it is as big as necessary. */ + +char *__canonicalize_directory_name_internal __P ((const char *__thisdir, + char *__buf, + size_t __size)); #endif #ifdef __USE_BSD @@ -653,9 +663,6 @@ extern int swapon __P ((__const char *__path)); /* Stop using block special device PATH for swapping. */ extern int swapoff __P ((__const char *__path)); -/* Reboot or halt the system. */ -extern int reboot __P ((int __howto)); - /* Successive calls return the shells listed in `/etc/shells'. */ extern char *getusershell __P ((void)); diff --git a/resolv/Makefile b/resolv/Makefile index ebb8967155..58f32821fe 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -22,11 +22,12 @@ subdir := resolv headers := resolv.h netdb.h arpa/nameser.h sys/bitypes.h -distribute := ../conf/portability.h +distribute := ../conf/portability.h res_hconf.h routines := gethnamaddr getnetbyaddr getnetbyname getnetent getnetnamadr \ herror nsap_addr res_comp res_debug res_data res_init res_mkquery \ - res_query res_send sethostent inet_addr + res_query res_send sethostent inet_addr inet_ntop inet_pton \ + res_hconf include ../Rules diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h index 3792b7963c..0fb04a1a02 100644 --- a/resolv/arpa/nameser.h +++ b/resolv/arpa/nameser.h @@ -3,7 +3,7 @@ * - * Copyright (c) 1983, 1989, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -97,7 +97,8 @@ #define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ #define INT32SZ 4 /* for systems without 32-bit ints */ #define INT16SZ 2 /* for systems without 16-bit ints */ -#define INADDRSZ 4 /* for sizeof(struct inaddr) != 4 */ +#define INADDRSZ 4 /* IPv4 T_A */ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ /* * Internet nameserver port number @@ -110,7 +111,7 @@ #define QUERY 0x0 /* standard query */ #define IQUERY 0x1 /* inverse query */ #define STATUS 0x2 /* nameserver status query */ -/*#define xxx 0x3 /* 0x3 reserved */ +/*#define xxx 0x3*/ /* 0x3 reserved */ #define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ #ifdef ALLOW_UPDATES /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */ diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c index f108f2778f..b80595b7d5 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/gethnamaddr.c @@ -3,7 +3,7 @@ * - * Copyright (c) 1985, 1988, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -71,13 +71,15 @@ static char rcsid[] = "$Id$"; #include <errno.h> #include <syslog.h> +#include "res_hconf.h" + #ifndef LOG_AUTH # define LOG_AUTH 0 #endif #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ -#if defined(BSD) && (BSD >= 199103) +#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6) # include <string.h> #else # include "../conf/portability.h" @@ -88,6 +90,7 @@ static char rcsid[] = "$Id$"; #define MAXALIASES 35 #define MAXADDRS 35 +#define MAXADDRBUFSIZE 8192 static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\""; @@ -97,11 +100,14 @@ static struct hostent *gethostbyname_ipv4 __P((const char *)); static struct hostent host; static char *host_aliases[MAXALIASES]; -static char hostbuf[8*1024]; -static struct in_addr host_addr; +static char hostbuf[MAXADDRBUFSIZE]; +static u_char host_addr[16]; /* IPv4 or IPv6 */ static FILE *hostf = NULL; static int stayopen = 0; +static void map_v4v6_address __P((const char *src, char *dst)); +static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len)); + #ifdef RESOLVSORT static void addrsort __P((char **, int)); #endif @@ -142,11 +148,11 @@ dprintf(msg, num) #endif static struct hostent * -getanswer(answer, anslen, qname, qclass, qtype) +getanswer(answer, anslen, qname, qtype) const querybuf *answer; int anslen; const char *qname; - int qclass, qtype; + int qtype; { register const HEADER *hp; register const u_char *cp; @@ -165,13 +171,14 @@ getanswer(answer, anslen, qname, qclass, qtype) eom = answer->buf + anslen; switch (qtype) { case T_A: + case T_AAAA: name_ok = res_hnok; break; case T_PTR: - name_ok = dn_isvalid; + name_ok = res_dnok; break; default: - abort(); + return (NULL); /* XXX should be abort(); */ } /* * find first satisfactory answer @@ -192,7 +199,7 @@ getanswer(answer, anslen, qname, qclass, qtype) return (NULL); } cp += n + QFIXEDSZ; - if (qtype == T_A) { + if (qtype == T_A || qtype == T_AAAA) { /* res_send() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). @@ -209,9 +216,7 @@ getanswer(answer, anslen, qname, qclass, qtype) host.h_aliases = host_aliases; hap = h_addr_ptrs; *hap = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ host.h_addr_list = h_addr_ptrs; -#endif haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { @@ -227,12 +232,12 @@ getanswer(answer, anslen, qname, qclass, qtype) cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); cp += INT16SZ; /* len */ - if (class != qclass) { + if (class != C_IN) { /* XXX - debug? syslog? */ cp += n; continue; /* XXX - had_error++ ? */ } - if (qtype == T_A && type == T_CNAME) { + if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { if (ap >= &host_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); @@ -241,12 +246,6 @@ getanswer(answer, anslen, qname, qclass, qtype) continue; } cp += n; - if (host.h_name && strcasecmp(host.h_name, bp) != 0) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"", - host.h_name, bp); - continue; /* XXX - had_error++ ? */ - } /* Store alias. */ *ap++ = bp; n = strlen(bp) + 1; /* for the \0 */ @@ -286,7 +285,7 @@ getanswer(answer, anslen, qname, qclass, qtype) if (type != qtype) { syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class(qclass), p_type(qtype), + qname, p_class(C_IN), p_type(qtype), p_type(type)); cp += n; continue; /* XXX - had_error++ ? */ @@ -320,10 +319,17 @@ getanswer(answer, anslen, qname, qclass, qtype) break; #else host.h_name = bp; + if (_res.options & RES_USE_INET6) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + map_v4v6_hostent(&host, &bp, &buflen); + } h_errno = NETDB_SUCCESS; return (&host); #endif case T_A: + case T_AAAA: if (strcasecmp(host.h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, host.h_name, bp); @@ -338,10 +344,6 @@ getanswer(answer, anslen, qname, qclass, qtype) } else { register int nn; - host.h_length = n; - host.h_addrtype = (class == C_IN) - ? AF_INET - : AF_UNSPEC; host.h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; @@ -367,13 +369,11 @@ getanswer(answer, anslen, qname, qclass, qtype) cp += n; break; default: - dprintf("Impossible condition (type=%d)\n", type); - h_errno = NO_RECOVERY; - return (NULL); - } /*switch*/ + abort(); + } if (!had_error) haveanswer++; - } /*while*/ + } if (haveanswer) { *ap = NULL; *hap = NULL; @@ -383,44 +383,39 @@ getanswer(answer, anslen, qname, qclass, qtype) * in its return structures - should give it the "best" * address in that case, not some random one */ - if (_res.nsort && haveanswer > 1 && - qclass == C_IN && qtype == T_A) + if (_res.nsort && haveanswer > 1 && qtype == T_A) addrsort(h_addr_ptrs, haveanswer); # endif /*RESOLVSORT*/ -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ - /* nothing */ -#else - host.h_addr = h_addr_ptrs[0]; -#endif /*BSD*/ if (!host.h_name) { n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen) + goto try_again; strcpy(bp, qname); host.h_name = bp; + bp += n; + buflen -= n; } + if (_res.options & RES_USE_INET6) + map_v4v6_hostent(&host, &bp, &buflen); h_errno = NETDB_SUCCESS; return (&host); - } else { - h_errno = TRY_AGAIN; - return (NULL); } + try_again: + h_errno = TRY_AGAIN; + return (NULL); } struct hostent * gethostbyname(name) const char *name; { - /* Moved #if line to here because declaring HP would lead to a - warning. --drepper@gnu */ -#if defined(AF_INET6) && defined(RES_TRY_INET6) struct hostent *hp; -/* #if defined(AF_INET6) && defined(RES_TRY_INET6) */ - if (_res.options & RES_TRY_INET6) { + if (_res.options & RES_USE_INET6) { hp = gethostbyname2(name, AF_INET6); if (hp) return (hp); } -#endif return (gethostbyname2(name, AF_INET)); } @@ -429,29 +424,35 @@ gethostbyname2(name, af) const char *name; int af; { - switch (af) { - case AF_INET: - return (gethostbyname_ipv4(name)); - } - errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; - return (NULL); -} - -static struct hostent * -gethostbyname_ipv4(name) - const char *name; -{ querybuf buf; register const char *cp; - int n; - extern struct hostent *_gethtbyname(); + char *bp; + int i, n, size, type, len; + extern struct hostent *_gethtbyname2(); if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (NULL); } + switch (af) { + case AF_INET: + size = INADDRSZ; + type = T_A; + break; + case AF_INET6: + size = IN6ADDRSZ; + type = T_AAAA; + break; + default: + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); + } + + host.h_addrtype = af; + host.h_length = size; + /* * if there aren't any dots, it could be a user-level alias. * this is also done in res_query() since we are not the only @@ -474,117 +475,254 @@ gethostbyname_ipv4(name) * Fake up a hostent as if we'd actually * done a lookup. */ - if (!inet_aton(name, &host_addr)) { + if (inet_pton(af, name, host_addr, + sizeof host_addr) <= 0) { h_errno = HOST_NOT_FOUND; return (NULL); } strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; + bp = hostbuf + MAXDNAME; + len = sizeof hostbuf - MAXDNAME; host.h_name = hostbuf; host.h_aliases = host_aliases; host_aliases[0] = NULL; - host.h_addrtype = AF_INET; - host.h_length = INT32SZ; h_addr_ptrs[0] = (char *)&host_addr; h_addr_ptrs[1] = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ host.h_addr_list = h_addr_ptrs; -#else - host.h_addr = h_addr_ptrs[0]; -#endif + if (_res.options & RES_USE_INET6) + map_v4v6_hostent(&host, &bp, &len); h_errno = NETDB_SUCCESS; return (&host); } - if (!isdigit(*cp) && *cp != '.') + if (!isdigit(*cp) && *cp != '.') break; } - if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { - dprintf("res_search failed (%d)\n", n); - if (errno == ECONNREFUSED) - return (_gethtbyname(name)); - return (NULL); + h_errno = HOST_NOT_FOUND; + for (i = 0; i < _res_hconf.num_services; ++i) { + struct hostent * hp; + char * cp = (char *) name; + + if (_res_hconf.num_trimdomains > 0) { + size_t name_len = strlen(name); + + cp = malloc(name_len + 1); + memcpy(cp, name, name_len + 1); + _res_hconf_trim_domain(cp); + } + + hp = NULL; + switch (_res_hconf.service[i]) { + case SERVICE_BIND: + if ((n = res_search(cp, C_IN, type, + buf.buf, sizeof(buf))) < 0) + { + dprintf("res_search failed (%d)\n", n); + break; + } + hp = getanswer(&buf, n, cp, type); + break; + + case SERVICE_HOSTS: + hp = _gethtbyname2(cp, af); + break; +#ifdef HAVE_NYS + case SERVICE_NIS: + hp = _getnishost(cp, "hosts.byname"); + break; +#endif + default: + break; + } + if (cp != name) + free(cp); + if (hp) { + if ((_res_hconf.flags & HCONF_FLAG_REORDER) + && hp->h_addr_list[0] && hp->h_addr_list[1]) + _res_hconf_reorder_addrs(hp); + _res_hconf_trim_domains(hp); + return hp; + } } - return (getanswer(&buf, n, name, C_IN, T_A)); + if (h_errno == NETDB_SUCCESS) + h_errno = HOST_NOT_FOUND; + return NULL; } struct hostent * -gethostbyaddr(addr, len, type) - const char *addr; - int len, type; +gethostbyaddr(addr, len, af) + const char *addr; /* XXX should have been def'd as u_char! */ + int len, af; { - int n; + const u_char *uaddr = (const u_char *)addr; + static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; + static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + int n, size; querybuf buf; register struct hostent *hp; - char qbuf[MAXDNAME+1]; -#ifdef SUNSECURITY + char qbuf[MAXDNAME+1], *qp; register struct hostent *rhp; char **haddr; u_long old_options; char hname2[MAXDNAME+1]; -#endif /*SUNSECURITY*/ + int i, old_num_trimdomains; extern struct hostent *_gethtbyaddr(); - + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (NULL); } - if (type != AF_INET || len != INADDRSZ) { + if (af == AF_INET6 && len == IN6ADDRSZ && + (!bcmp(uaddr, mapped, sizeof mapped) || + !bcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr += sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: errno = EAFNOSUPPORT; h_errno = NETDB_INTERNAL; return (NULL); } - (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", - ((unsigned)addr[3] & 0xff), - ((unsigned)addr[2] & 0xff), - ((unsigned)addr[1] & 0xff), - ((unsigned)addr[0] & 0xff)); - n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); - if (n < 0) { - dprintf("res_query failed (%d)\n", n); - if (errno == ECONNREFUSED) - return (_gethtbyaddr(addr, len, type)); - return (NULL); - } - if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR))) - return (NULL); /* h_errno was set by getanswer() */ -#ifdef SUNSECURITY - /* - * turn off search as the name should be absolute, - * 'localhost' should be matched by defnames - */ - strncpy(hname2, hp->h_name, MAXDNAME); - hname2[MAXDNAME] = '\0'; - old_options = _res.options; - _res.options &= ~RES_DNSRCH; - _res.options |= RES_DEFNAMES; - if (!(rhp = gethostbyname(hname2))) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostbyaddr: No A record for %s (verifying [%s])", - hname2, inet_ntoa(*((struct in_addr *)addr))); - _res.options = old_options; - h_errno = HOST_NOT_FOUND; + if (size != len) { + errno = EINVAL; + h_errno = NETDB_INTERNAL; return (NULL); } - _res.options = old_options; - for (haddr = rhp->h_addr_list; *haddr; haddr++) - if (!memcmp(*haddr, addr, INADDRSZ)) + + h_errno = NETDB_SUCCESS; + for (i = 0; i < _res_hconf.num_services; ++i) { + hp = NULL; + switch (_res_hconf.service[i]) { + case SERVICE_BIND: + switch (af) { + case AF_INET: + (void) sprintf(qbuf, + "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += sprintf(qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf); + } + strcpy(qp, "ip6.int"); + break; + default: + abort(); + } + n = res_query(qbuf, C_IN, T_PTR, + (u_char *)buf.buf, sizeof buf.buf); + if (n < 0) { + dprintf("res_query failed (%d)\n", n); + break; + } + hp = getanswer(&buf, n, qbuf, T_PTR); + if (!hp) + break; /* h_errno was set by getanswer() */ + if (af == AF_INET + && (_res_hconf.flags & HCONF_FLAG_SPOOF)) { + /* + * Turn off search as the name should + * be absolute, 'localhost' should be + * matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = _res.options; + /* + * Also turn off domain trimming to prevent it + * from causing the name comparison to fail. + */ + old_num_trimdomains = + _res_hconf.num_trimdomains; + _res.options &= ~RES_DNSRCH; + _res.options |= RES_DEFNAMES; + rhp = gethostbyname(hname2); + _res.options = old_options; + /* There must be an A record and + the names must match. */ + if (!rhp || strcmp(hname2, rhp->h_name)) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: No A record for" + " %s (verifying [%s])", + hname2, + inet_ntoa(*((struct in_addr *) + addr))); + h_errno = HOST_NOT_FOUND; + break; + } + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: A record of %s" + " != PTR record [%s]", + hname2, + inet_ntoa(*((struct in_addr *) + addr))); + h_errno = HOST_NOT_FOUND; + break; + } + } + hp->h_addrtype = af; + hp->h_length = len; + bcopy(addr, host_addr, len); + h_addr_ptrs[0] = (char *)host_addr; + h_addr_ptrs[1] = NULL; + if (af == AF_INET && (_res.options & RES_USE_INET6)) { + map_v4v6_address((char*)host_addr, + (char*)host_addr); + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + } + h_errno = NETDB_SUCCESS; break; - if (!*haddr) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostbyaddr: A record of %s != PTR record [%s]", - hname2, inet_ntoa(*((struct in_addr *)addr))); - h_errno = HOST_NOT_FOUND; - return (NULL); + + case SERVICE_HOSTS: + hp = _gethtbyaddr(addr, len, af); + break; + +#ifdef HAVE_NYS + case SERVICE_NIS: + if (af == AF_INET) { + sprintf(qbuf, "%u.%u.%u.%u", + (unsigned)addr[0] & 0xff, + (unsigned)addr[1] & 0xff, + (unsigned)addr[2] & 0xff, + (unsigned)addr[3] & 0xff); + hp = _getnishost(qbuf, "hosts.byaddr"); + } + break; +#endif + + default: + break; + } + if (hp) { + _res_hconf_trim_domains(hp); + return hp; + } } -#endif /*SUNSECURITY*/ - hp->h_addrtype = type; - hp->h_length = len; - h_addr_ptrs[0] = (char *)&host_addr; - h_addr_ptrs[1] = NULL; - host_addr = *(struct in_addr *)addr; - h_errno = NETDB_SUCCESS; - return (hp); + if (h_errno == NETDB_SUCCESS) + h_errno = HOST_NOT_FOUND; + return NULL; } void @@ -612,12 +750,13 @@ _gethtent() { char *p; register char *cp, **q; + int af, len; if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { h_errno = NETDB_INTERNAL; return (NULL); } -again: + again: if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { h_errno = HOST_NOT_FOUND; return (NULL); @@ -630,18 +769,27 @@ again: if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; - /* THIS STUFF IS INTERNET SPECIFIC */ - if (!inet_aton(p, &host_addr)) + if ((_res.options & RES_USE_INET6) && + inet_pton(AF_INET6, p, host_addr, sizeof host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, host_addr, sizeof host_addr) > 0) { + if (_res.options & RES_USE_INET6) { + map_v4v6_address((char*)&host_addr, (char*)&host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { goto again; + } h_addr_ptrs[0] = (char *)&host_addr; h_addr_ptrs[1] = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ host.h_addr_list = h_addr_ptrs; -#else - host.h_addr = h_addr_ptrs[0]; -#endif - host.h_length = INT32SZ; - host.h_addrtype = AF_INET; + host.h_length = len; + host.h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; host.h_name = cp; @@ -659,45 +807,275 @@ again: *cp++ = '\0'; } *q = NULL; + if (_res.options & RES_USE_INET6) { + char *bp = hostbuf; + int buflen = sizeof hostbuf; + + map_v4v6_hostent(&host, &bp, &buflen); + } h_errno = NETDB_SUCCESS; return (&host); } +struct hstorage { + char name[MAXHOSTNAMELEN + 1]; /* canonical name */ + char ** alp; /* address list pointer */ + char * abp; /* address buffer pointer */ + char * addr_list[MAXADDRS + 1]; /* address list storage */ + char addr_buf[MAXADDRBUFSIZE]; /* addresses storage */ +}; + +static void +append_addr (struct hstorage * hs, struct hostent *p) +{ + if (hs->alp < hs->addr_list + MAXADDRS + && hs->abp + p->h_length < hs->addr_buf + MAXADDRBUFSIZE) + { + hs->alp[0] = hs->abp; + hs->alp[1] = 0; + memcpy(hs->abp, p->h_addr_list[0], p->h_length); + hs->abp += p->h_length; + ++hs->alp; + } +} + +/* + * Lookup IP address and aliases for host NAME. If multiaddress mode + * is enabled, the entire /etc/hosts file is searched and the union of + * all addresses found for NAME is returned (this may be slow with + * large /etc/hosts files, but is convenient for smallish sites that + * don't want to go through the complexity of running named locally). + * If multiaddress mode is enabled, the address returned in + * h_addr_list[0] is one that is on the same net as one of the host's + * local addresses (if such an address exists). For compatibility + * with the BIND version of gethostbyname(), the alias field is empty + * unless the name being looked up is an alias itself. In the latter + * case, the name field contains the canonical name and the alias + * field the name that is being looked up. A difference from the BIND + * version is that this is true even if the alias applies only to one + * of the interfaces on the target host.o + */ struct hostent * _gethtbyname(name) - char *name; + const char *name; +{ + extern struct hostent *_gethtbyname2 __P((const char *, int)); + struct hostent *hp; + + if (_res.options & RES_USE_INET6) { + hp = _gethtbyname2(name, AF_INET6); + if (hp) + return (hp); + } + return (_gethtbyname2(name, AF_INET)); +} + +struct hostent * +_gethtbyname2(name, af) + const char *name; + int af; { register struct hostent *p; register char **cp; - + _sethtent(0); - while (p = _gethtent()) { - if (strcasecmp(p->h_name, name) == 0) - break; - for (cp = p->h_aliases; *cp != 0; cp++) - if (strcasecmp(*cp, name) == 0) - goto found; + + if (_res_hconf.flags & HCONF_FLAG_MULTI) { + /* + * More statics; not pretty, but it would require + * interface changes to make these functions + * reentrant. + */ + static char * aliases[2]; + static char alias[MAXHOSTNAMELEN + 1]; + static struct hstorage self, target; + static struct hostent ht; + int found; + + aliases[0] = aliases[1] = 0; + + gethostname(self.name, sizeof(self.name)); + self.alp = self.addr_list; + self.abp = self.addr_buf; + + strncpy(target.name, name, MAXHOSTNAMELEN); + target.name[MAXHOSTNAMELEN] = '\0'; + target.alp = target.addr_list; + target.abp = target.addr_buf; + + _sethtent(0); + while ((p = _gethtent()) != 0) { + found = 1; + + if (p->h_addrtype != af) + continue; + if (strcasecmp(p->h_name, name) != 0) { + found = 0; + for (cp = p->h_aliases; *cp; ++cp) + if (strcasecmp(*cp, name) == 0) { + found = 1; + if (!aliases[0]) { + strcpy(target.name, + p->h_name); + strncpy(alias, name, + MAXHOSTNAMELEN); + alias[MAXHOSTNAMELEN] + = '\0'; + aliases[0] = alias; + } + break; + } + } + if (found) { + /* they better be all the same type and length! */ + ht.h_addrtype = p->h_addrtype; + ht.h_length = p->h_length; + append_addr(&target, p); + /* + * If the current hostentry is for the target host, we don't + * check for the local host name. This nicely optimizes the + * case where NAME is a local name since address ordering + * doesn't matter in that case. + */ + continue; + } + found = 1; + if (strcasecmp(p->h_name, self.name) != 0) { + found = 0; + for (cp = p->h_aliases; *cp; ++cp) + if (strcasecmp(*cp, self.name) == 0) { + found = 1; + break; + } + } + if (found) { + append_addr(&self, p); + } + } + _endhtent(); + + if (target.alp == target.addr_list) + return NULL; /* found nothing */ + + ht.h_aliases = aliases; + ht.h_name = target.name; + ht.h_addr_list = target.addr_list; + /* + * XXX (davidm) Isn't this subsumed by REORDER??? + * + * Finding the `best' address is necessarily address + * specific. For now, we do IPv4 addresses only. + */ + if (af == AF_INET) { + u_int32_t a1, a2, diff, mindiff = ~0; + int i, j, bestaddr = 0; + + for (i = 0; self.addr_list[i]; ++i) { + for (j = 0; target.addr_list[j]; ++j) { + memcpy(&a1, self.addr_list[i], 4); + memcpy(&a2, target.addr_list[j], 4); + a1 = ntohl(a1); + a2 = ntohl(a2); + diff = a1 ^ a2; + if (diff < mindiff) { + bestaddr = j; + mindiff = diff; + } + } + } + if (bestaddr > 0) { + char * tmp; + + tmp = target.addr_list[0]; + target.addr_list[0] = target.addr_list[bestaddr]; + target.addr_list[bestaddr] = tmp; + } + } else if (af == AF_INET6) { + /* XXX To do!!! */ + } + ht.h_addr_list = target.addr_list; + return &ht; + } else { + _sethtent(0); + while (p = _gethtent()) { + if (p->h_addrtype != af) + continue; + if (strcasecmp(p->h_name, name) == 0) + break; + for (cp = p->h_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, name) == 0) + goto found; + } } -found: + found: _endhtent(); return (p); } struct hostent * -_gethtbyaddr(addr, len, type) +_gethtbyaddr(addr, len, af) const char *addr; - int len, type; + int len, af; { register struct hostent *p; _sethtent(0); while (p = _gethtent()) - if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) + if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) break; _endhtent(); return (p); } +static void +map_v4v6_address(src, dst) + const char *src; + char *dst; +{ + u_char *p = (u_char *)dst; + char tmp[INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + bcopy(src, tmp, INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + bcopy(tmp, (void*)p, INADDRSZ); +} + +static void +map_v4v6_hostent(hp, bpp, lenp) + struct hostent *hp; + char **bpp; + int *lenp; +{ + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); + + if (*lenp < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. XXX */ + *ap = NULL; + return; + } + *bpp += i; + *lenp -= i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= IN6ADDRSZ; + } +} + #ifdef RESOLVSORT static void addrsort(ap, num) @@ -712,7 +1090,7 @@ addrsort(ap, num) p = ap; for (i = 0; i < num; i++, p++) { for (j = 0 ; (unsigned)j < _res.nsort; j++) - if (_res.sort_list[j].addr.s_addr == + if (_res.sort_list[j].addr.s_addr == (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) break; aval[i] = j; @@ -766,17 +1144,57 @@ ht_gethostbyname(name) } struct hostent * -ht_gethostbyaddr(addr, len, type) +ht_gethostbyaddr(addr, len, af) const char *addr; - int len, type; + int len, af; { - return (_gethtbyaddr(addr, len, type)); + return (_gethtbyaddr(addr, len, af)); } struct hostent * gethostent() { - return (_gethtent()); + struct hostent * hp; + int i; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + + /* + * This doesn't look quite right. Shouldn't we read one + * service until it returns 0, then move on to the next + * service? If so, it requires adding some state and + * initializing that state in sethostent(). + * (davidm@azstarnet.com) + */ + for (i = 0; i < _res_hconf.num_services; ++i) { + hp = NULL; + switch (_res_hconf.service[i]) { + case SERVICE_HOSTS: + hp = _gethtent (); + break; + +#ifdef HAVE_NYS + case SERVICE_NIS: + hp = _getnishost (NULL, "hosts.byname"); + break; +#endif + + case SERVICE_BIND: + default: + break; + } + if (hp) { + if ((_res_hconf.flags & HCONF_FLAG_REORDER) + && hp->h_addr_list[0] && hp->h_addr_list[1]) + _res_hconf_reorder_addrs (hp); + return hp; + } + } + h_errno = HOST_NOT_FOUND; + return NULL; } void diff --git a/resolv/getnetnamadr.c b/resolv/getnetnamadr.c index fad2b8c0cd..9739995e36 100644 --- a/resolv/getnetnamadr.c +++ b/resolv/getnetnamadr.c @@ -139,7 +139,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1]; haveanswer = 0; while (--ancount >= 0 && cp < eom) { n = dn_expand(answer->buf, eom, cp, bp, buflen); - if ((n < 0) || !dn_isvalid(bp)) + if ((n < 0) || !res_dnok(bp)) break; cp += n; ans[0] = '\0'; @@ -209,7 +209,7 @@ getnetbyaddr(net, net_type) int nn, anslen; querybuf buf; char qbuf[MAXDNAME]; - u_int32_t net2; + u_int32_t net2; /* Changed from unsigned long --roland */ struct netent *net_entry; if (net_type != AF_INET) diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c index bcf7f0d336..2caf747acf 100644 --- a/resolv/inet_addr.c +++ b/resolv/inet_addr.c @@ -3,7 +3,7 @@ * - * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -70,7 +70,7 @@ static char rcsid[] = "$Id$"; * Ascii internet address interpretation routine. * The value returned is in network order. */ -u_int32_t +u_long inet_addr(cp) register const char *cp; { @@ -81,7 +81,7 @@ inet_addr(cp) return (INADDR_NONE); } -/* +/* * Check whether "cp" is a valid ascii representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. @@ -93,7 +93,7 @@ inet_aton(cp, addr) register const char *cp; struct in_addr *addr; { - register u_int32_t val; + register u_int32_t val; /* changed from u_long --david */ register int base, n; register char c; u_int parts[4]; diff --git a/resolv/inet_ntop.c b/resolv/inet_ntop.c new file mode 100644 index 0000000000..71db06d845 --- /dev/null +++ b/resolv/inet_ntop.c @@ -0,0 +1,189 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include "../conf/portability.h" + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + bzero(words, sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c new file mode 100644 index 0000000000..385dc25337 --- /dev/null +++ b/resolv/inet_pton.c @@ -0,0 +1,223 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <string.h> +#include <errno.h> +#include "../conf/portability.h" + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __P((const char *src, u_char *dst)); +static int inet_pton6 __P((const char *src, u_char *dst)); + +/* int + * inet_pton(af, src, dst, size) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst, size) + int af; + const char *src; + void *dst; + size_t size; +{ + switch (af) { + case AF_INET: + if (size < INADDRSZ) { + errno = ENOSPC; + return (-1); + } + return (inet_pton4(src, dst)); + case AF_INET6: + if (size < IN6ADDRSZ) { + errno = ENOSPC; + return (-1); + } + return (inet_pton6(src, dst)); + default: + errno = EINVAL; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_pton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + u_char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + u_char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + u_int new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + bcopy(tmp, dst, INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + u_char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + + bzero((tp = tmp), IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const howmany = tp - colonp; + int i; + + for (i = 1; i <= howmany; i++) { + endp[- i] = colonp[howmany - i]; + colonp[howmany - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + bcopy(tmp, dst, IN6ADDRSZ); + return (1); +} diff --git a/resolv/res_comp.c b/resolv/res_comp.c index f234772e41..e105dbb0b6 100644 --- a/resolv/res_comp.c +++ b/resolv/res_comp.c @@ -3,7 +3,7 @@ * - * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -343,7 +343,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr) /**** To: "Lawrence R. Rogers" <lrr@cert.org> cc: cert@cert.org, pvm@home.net -Subject: Re: VU#14542 +Subject: Re: VU#14542 In-reply-to: Your message of "Mon, 19 Feb 1996 17:16:27 PST." Date: Tue, 20 Feb 1996 22:37:21 -0800 From: Paul A Vixie <vixie@wisdom.home.vix.com> @@ -359,7 +359,7 @@ in retrospect, should have been hostname = label ( "." label )+ - firstchar = [a-zA-Z0-9_] + firstchar = [a-zA-Z0-9] otherchar = [a-zA-Z0-9_-] label = firstchar otherchar* @@ -368,53 +368,98 @@ earlier. since i'm only trying to bend the spec to fit actual known uses, i should not have widened the rules as far as i did earlier. ****/ -#define firstchar(c) ((isascii(c) && isalnum(c)) || (c) == '_') -#define otherchar(c) (firstchar(c) || (c) == '-') -#define wildlabel(firstlabel, ch, nch) \ - ((firstlabel) && (ch) == '*' && ((nch) == '.' || (nch) == '\0')) +/* + * Note the conspicuous absence of ctype macros in these definitions. On + * non-ASCII hosts, we can't depend on string literals or ctype macros to + * tell us anything about network-format data. The rest of the BIND system + * is not careful about this, but for some reason, we're doing it right here. + */ +#define PERIOD 0x2e +#define hyphenchar(c) ((c) == 0x2d) +#define bslashchar(c) ((c) == 0x5c) +#define periodchar(c) ((c) == PERIOD) +#define asterchar(c) ((c) == 0x2a) +#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ + || ((c) >= 0x61 && (c) <= 0x7a)) +#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) + +#define borderchar(c) (alphachar(c) || digitchar(c)) +#define middlechar(c) (borderchar(c) || hyphenchar(c)) +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) int res_hnok(dn) const char *dn; { - int ppch = '\0', pch = '.', ch = *dn++, firstlabel = 1; + int ppch = '\0', pch = PERIOD, ch = *dn++; while (ch != '\0') { int nch = *dn++; - if (ch == '.' || (ch == '\\' && nch == '.')) { + if (periodchar(ch)) { NULL; - } else if (pch == '.' && ppch != '\\') { - if (!firstchar(ch) && !wildlabel(firstlabel, ch, nch)) + } else if (periodchar(pch)) { + if (!borderchar(ch)) + return (0); + } else if (periodchar(nch) || nch == '\0') { + if (!borderchar(ch)) return (0); } else { - if (!otherchar(ch)) + if (!middlechar(ch)) return (0); } ppch = pch, pch = ch, ch = nch; - firstlabel = 0; } return (1); } /* + * hostname-like (A, MX, WKS) owners can have "*" as their first label + * but must otherwise be as a host name. + */ +int +res_ownok(dn) + const char *dn; +{ + if (asterchar(dn[0]) && periodchar(dn[1])) + dn += 2; + return (res_hnok(dn)); +} + +/* + * SOA RNAMEs and RP RNAMEs can have any printable character in their first + * label, but the rest of the name has to look like a host name. + */ +int +res_mailok(dn) + const char *dn; +{ + int ch, pch; + + pch = '\0'; + while ((ch = *dn++) != '\0') { + if (!domainchar(ch)) + return (0); + if (periodchar(ch) && !bslashchar(pch)) + break; + pch = ch; + } + return (res_hnok(dn)); +} + +/* * This function is quite liberal, since RFC 1034's character sets are only * recommendations. - * - * Note that some char's are signed, so we have to cast to unsigned. */ int -dn_isvalid(dn) +res_dnok(dn) const char *dn; { - unsigned char *t = (unsigned char *)dn; int ch; - while ((ch = *t++) != '\0') - if (ch <= 0x1f || ch >= 0x7f) { - /* Unprintable in ASCII. */ + while ((ch = *dn++) != '\0') + if (!domainchar(ch)) return (0); - } return (1); } @@ -498,7 +543,7 @@ putlong(l, msgp) { __putlong(l, msgp); } - + #undef dn_skipname dn_skipname(comp_dn, eom) const u_char *comp_dn, *eom; diff --git a/resolv/res_debug.c b/resolv/res_debug.c index 85ec628b89..4f55804497 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -3,7 +3,7 @@ * - * Copyright (c) 1985, 1990, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -59,6 +59,8 @@ static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> @@ -66,7 +68,7 @@ static char rcsid[] = "$Id$"; #include <stdio.h> #include <netdb.h> #include <resolv.h> -#if defined(BSD) && (BSD >= 199103) +#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6) # include <string.h> #else # include "../conf/portability.h" @@ -295,7 +297,7 @@ __fp_nquery(msg, len, file) fprintf(file, ", Auth: %d", ntohs(hp->nscount)); fprintf(file, ", Addit: %d", ntohs(hp->arcount)); } - if ((!_res.pfcode) || (_res.pfcode & + if ((!_res.pfcode) || (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { putc('\n',file); } @@ -590,6 +592,13 @@ __p_rr(cp, msg, file) cp += dlen; break; + case T_AAAA: { + char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + fprintf(file, "\t%s\n", inet_ntop(AF_INET6, cp, t, sizeof t)); + break; + } + case T_MINFO: case T_RP: putc('\t', file); diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c new file mode 100644 index 0000000000..b08dd3ced7 --- /dev/null +++ b/resolv/res_hconf.c @@ -0,0 +1,566 @@ +/* Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file provides a Linux /etc/host.conf compatible front end to +the various name resolvers (/etc/hosts, named, NIS server, etc.). +Though mostly compatibly, the following differences exist compared +to the original implementation: + + - new command "spoof" takes an arguments like RESOLV_SPOOF_CHECK + environment variable (i.e., `off', `nowarn', or `warn'). + + - line comments can appear anywhere (not just at the beginning of + a line) +*/ +#include <ctype.h> +#include <memory.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "res_hconf.h" + +#define _PATH_HOSTCONF "/etc/host.conf" + +/* Environment vars that all user to override default behavior: */ +#define ENV_HOSTCONF "RESOLV_HOST_CONF" +#define ENV_SERVORDER "RESOLV_SERV_ORDER" +#define ENV_SPOOF "RESOLV_SPOOF_CHECK" +#define ENV_TRIM_OVERR "RESOLV_OVERRIDE_TRIM_DOMAINS" +#define ENV_TRIM_ADD "RESOLV_ADD_TRIM_DOMAINS" +#define ENV_MULTI "RESOLV_MULTI" +#define ENV_REORDER "RESOLV_REORDER" + +static const char * arg_service_list (const char *, int, const char *, + unsigned); +static const char * arg_trimdomain_list (const char *, int, const char *, + unsigned); +static const char * arg_spoof (const char *, int, const char *, unsigned); +static const char * arg_bool (const char *, int, const char *, unsigned); + +static struct cmd { + const char * name; + const char * (*parse_args)(const char * filename, int line_num, + const char * args, unsigned arg); + unsigned arg;; +} cmd[] = { + {"order", arg_service_list, 0}, + {"trim", arg_trimdomain_list, 0}, + {"spoof", arg_spoof, 0}, + {"multi", arg_bool, HCONF_FLAG_MULTI}, + {"nospoof", arg_bool, HCONF_FLAG_SPOOF}, + {"spoofalert", arg_bool, HCONF_FLAG_SPOOFALERT}, + {"reorder", arg_bool, HCONF_FLAG_REORDER} +}; + + +/* + * Why isn't this in stdlib? + */ +char * +strndup (const char * s, size_t n) +{ + char * retval; + + retval = malloc (n + 1); + if (!retval) + return retval; + + memcpy (retval, s, n); + retval[n] = '\0'; /* ensure return value is terminated */ + return retval; +} + + +/* Skip white space. */ +static const char * +skip_ws (const char * str) +{ + while (isspace (*str)) ++str; + return str; +} + + +/* Skip until whitespace, comma, end of line, or comment character. */ +static const char * +skip_string (const char * str) +{ + while (*str && !isspace (*str) && *str != '#' && *str != ',') ++str; + return str; +} + + +static const char * +arg_service_list (const char * fname, int line_num, const char * args, + unsigned arg) +{ + enum Name_Service service; + const char * start; + size_t len; + int i; + static struct { + const char * name; + enum Name_Service service; + } svcs[] = { + {"bind", SERVICE_BIND}, + {"hosts", SERVICE_HOSTS}, + {"nis", SERVICE_NIS}, + }; + + do + { + start = args; + args = skip_string (args); + len = args - start; + + service = SERVICE_NONE; + for (i = 0; i < sizeof (svcs) / sizeof (svcs[0]); ++i) + { + if (strncasecmp (start, svcs[i].name, len) == 0 + && len == strlen (svcs[i].name)) + { + service = svcs[i].service; + break; + } + } + if (service == SERVICE_NONE) + { + fprintf (stderr, "%s: line %d: expected service, found `%s'\n", + fname, line_num, start); + return 0; + } + if (_res_hconf.num_services >= SERVICE_MAX) + { + fprintf (stderr, "%s: line %d: cannot specify more than %d services", + fname, line_num, SERVICE_MAX); + return 0; + } + _res_hconf.service[_res_hconf.num_services++] = service; + + args = skip_ws (args); + switch (*args) + { + case ',': case ';': case ':': + args = skip_ws (++args); + if (!*args || *args == '#') + { + fprintf (stderr, + "%s: line %d: list delimiter not followed by keyword", + fname, line_num); + return 0; + } + default: + break; + } + } + while (*args && *args != '#'); + return args; +} + + +static const char * +arg_trimdomain_list (const char * fname, int line_num, const char * args, + unsigned flag) +{ + const char * start; + size_t len; + + do + { + start = args; + args = skip_string (args); + len = args - start; + + if (_res_hconf.num_trimdomains >= TRIMDOMAINS_MAX) + { + fprintf (stderr, + "%s: line %d: cannot specify more than %d trim domains", + fname, line_num, TRIMDOMAINS_MAX); + return 0; + } + _res_hconf.trimdomain[_res_hconf.num_trimdomains++] = + strndup (start, len); + args = skip_ws (args); + switch (*args) + { + case ',': case ';': case ':': + args = skip_ws (++args); + if (!*args || *args == '#') + { + fprintf (stderr, + "%s: line %d: list delimiter not followed by domain", + fname, line_num); + return 0; + } + default: + break; + } + } + while (*args && *args != '#'); + return args; +} + + +static const char * +arg_spoof (const char * fname, int line_num, const char * args, unsigned flag) +{ + const char * start = args; + size_t len; + + args = skip_string (args); + len = args - start; + + if (len == 3 && strncasecmp (start, "off", len) == 0) + _res_hconf.flags &= ~(HCONF_FLAG_SPOOF | HCONF_FLAG_SPOOFALERT); + else + { + _res_hconf.flags |= (HCONF_FLAG_SPOOF | HCONF_FLAG_SPOOFALERT); + if ((len == 6 && strncasecmp (start, "nowarn", len) == 0) + || !(len == 4 && strncasecmp (start, "warn", len) == 0)) + _res_hconf.flags &= ~HCONF_FLAG_SPOOFALERT; + } + return args; +} + + +static const char * +arg_bool (const char * fname, int line_num, const char * args, unsigned flag) +{ + if (strncasecmp (args, "on", 2) == 0) + { + args += 2; + _res_hconf.flags |= flag; + } + else if (strncasecmp (args, "off", 3) == 0) + { + args += 3; + _res_hconf.flags &= ~flag; + } + else + { + fprintf (stderr, "%s: line %d: expected `on' or `off', found `%s'\n", + fname, line_num, args); + return 0; + } + return args; +} + + +static void +parse_line (const char * fname, int line_num, const char * str) +{ + const char * start; + struct cmd * c = 0; + size_t len; + int i; + + str = skip_ws (str); + + if (*str == '#') return; /* skip line comment */ + + start = str; + str = skip_string (str); + len = str - start; + + for (i = 0; i < sizeof (cmd) / sizeof (cmd[0]); ++i) + { + if (strncasecmp (start, cmd[i].name, len) == 0 + && strlen (cmd[i].name) == len) + { + c = &cmd[i]; + break; + } + } + if (!c) + { + fprintf (stderr, "%s: line %d: bad command `%s'\n", + fname, line_num, start); + return; + } + + /* process args: */ + str = skip_ws (str); + str = (*c->parse_args) (fname, line_num, str, c->arg); + if (!str) + return; + + /* rest of line must contain white space or comment only: */ + while (*str) + { + if (!isspace (*str)) { + if (*str != '#') + fprintf (stderr, "%s: line %d: ignoring trailing garbage `%s'\n", + fname, line_num, str); + break; + } + ++str; + } +} + + +/* Initialize hconf datastructure by reading host.conf file and + environment variables. */ +void +_res_hconf_init (void) +{ + const char * hconf_name; + int line_num = 0; + char buf[256], * end, * envval; + FILE * fp; + + memset (&_res_hconf, 0, sizeof (_res_hconf)); + + hconf_name = getenv (ENV_HOSTCONF); + if (!hconf_name) + hconf_name = _PATH_HOSTCONF; + + fp = fopen (hconf_name, "r"); + if (!fp) + /* make up something reasonable: */ + _res_hconf.service[_res_hconf.num_services++] = SERVICE_BIND; + else + { + while (fgets (buf, sizeof (buf), fp)) + { + ++line_num; + end = strchr (buf, '\n'); + if (end) + *end = '\0'; + parse_line (hconf_name, line_num, buf); + } + fclose (fp); + } + + envval = getenv (ENV_SERVORDER); + if (envval) + { + _res_hconf.num_services = 0; + arg_service_list (ENV_SERVORDER, 1, envval, 0); + } + + envval = getenv (ENV_SPOOF); + if (envval) + arg_spoof (ENV_SPOOF, 1, envval, 0); + + envval = getenv (ENV_MULTI); + if (envval) + arg_bool (ENV_MULTI, 1, envval, HCONF_FLAG_MULTI); + + envval = getenv (ENV_REORDER); + if (envval) + arg_bool (ENV_REORDER, 1, envval, HCONF_FLAG_REORDER); + + envval = getenv (ENV_TRIM_ADD); + if (envval) + arg_trimdomain_list (ENV_TRIM_ADD, 1, envval, 0); + + envval = getenv (ENV_TRIM_OVERR); + if (envval) + { + _res_hconf.num_trimdomains = 0; + arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval, 0); + } +} + + +/* Reorder addresses returned in a hostent such that the first address + is an address on the local subnet, if there is such an address. + Otherwise, nothing is changed. */ + +void +_res_hconf_reorder_addrs (struct hostent * hp) +{ +#if defined (SIOCGIFCONF) && defined (SIOCGIFNETMASK) + static int num_ifs = -1; /* number of interfaces */ + static struct netaddr { + int addrtype; + union { + struct { + u_int32_t addr; + u_int32_t mask; + } ipv4 + } u; + } * ifaddrs; + + if (hp->h_addrtype != AF_INET) + return; /* can't deal with anything but IPv4 for now... */ + + if (num_ifs <= 0) + { + struct ifconf ifs; + struct ifreq * ifr; + size_t size, num; + int sd; + + /* initialize interface table: */ + + num_ifs = 0; + + sd = socket (AF_INET, SOCK_DGRAM, 0); + if (sd < 0) + return; + + /* Now get list of interfaces. Since we don't know how many + interfaces there are, we keep increasing the buffer size + until we have at least sizeof(struct ifreq) too many bytes. + That implies that the ioctl() return because it ran out of + interfaces, not memory */ + size = 0; + ifs.ifc_buf = 0; + do { + size += 4 * sizeof (struct ifreq); + ifs.ifc_buf = realloc (ifs.ifs_buf, size); + if (!ifs.ifc_buf) + { + close (sd); + return; + } + ifs.ifc_len = size; + if (ioctl (sd, SIOCGIFCONF, &ifs) < 0) + goto cleanup; + } while (size - ifs.ifc_len < sizeof (struct ifreq)); + + num = ifs.ifc_len / sizeof (struct ifreq); + + ifaddrs = malloc (num * sizeof (ifaddrs[0])); + if (!ifaddrs) + goto cleanup; + + ifr = ifs.ifc_req; + for (i = 0; i < num; ++i) { + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + ifaddrs[num_ifs].addrtype = AF_INET; + + memcpy (&ifaddrs[num_ifs].u.ipv4.addr, + &((struct sockaddr_in *)ifr->ifr_addr)->sin_addr, 4); + + if (ioctl (sd, SIOCGIFNETMASK, if) < 0) + continue; + memcpy (&ifaddrs[num_ifs].u.ipv4.mask, + ((struct sockaddr_in *)ifr->ifr_mask)->sin_addr, 4); + + ++num_ifs; /* now we're committed to this entry */ + } + /* just keep enough memory to hold all the interfaces we want: */ + ifaddrs = realloc (ifaddrs, num_ifs * sizeof (ifaddrs[0])); + + cleanup: + close (sd); + free (ifs.ifc_buf); + } + + if (num_ifs == 0) + return; + + /* find an address for which we have a direct connection: */ + for (i = 0; hp->h_addr_list[i]; ++i) + { + h_addr = (struct in_addr *) hp->h_addr_list[i]; + + for (j = 0; j < num_ifs; ++j) + { + if_addr = ifaddrs[j].u.ipv4.addr; + if_netmask = ifaddrs[j].u.ipv4.mask; + + if (((h_addr->s_addr ^ if_addr) & if_netmask) == 0) + { + void * tmp; + + tmp = hp->h_addr_list[i]; + hp->h_addr_list[i] = hp->h_addr_list[0]; + hp->h_addr_list[0] = tmp; + return; + } + } + } +#endif /* defined(SIOCGIFCONF) && ... */ +} + + +/* If HOSTNAME has a postfix matching any of the trimdomains, trim away + that postfix. Notice that HOSTNAME is modified inplace. Also, the + original code applied all trimdomains in order, meaning that the + same domainname could be trimmed multiple times. I believe this + was unintentional. */ +void +_res_hconf_trim_domain (char * hostname) +{ + size_t hostname_len, trim_len; + int i; + + hostname_len = strlen(hostname); + + for (i = 0; i < _res_hconf.num_trimdomains; ++i) + { + const char * trim = _res_hconf.trimdomain[i]; + + trim_len = strlen(trim); + if (hostname_len > trim_len + && strcasecmp(&hostname[hostname_len - trim_len], trim) == 0) + { + hostname[hostname_len - trim_len] = '\0'; + break; + } + } +} + + +/* Trim all hostnames/aliases in HP according to the trimdomain list. + Notice that HP is modified inplace! */ +void +_res_hconf_trim_domains (struct hostent * hp) +{ + int i; + + if (_res_hconf.num_trimdomains == 0) + return; + + _res_hconf_trim_domain (hp->h_name); + for (i = 0; hp->h_aliases[i]; ++i) + _res_hconf_trim_domain (hp->h_aliases[i]); +} + + +#if 0 + +struct hostent * +_hconf_gethostent (void) +{ +} + + +struct hostent * +_hconf_gethostbyname (const char * name) +{ + +} + + +struct hostent * +_hconf_gethostbyaddr (const char * addr, int len, int type) +{ +} + + +struct hostent * +_hconf_gethtbyname (const char * name) +{ +} + +#endif diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h new file mode 100644 index 0000000000..2165e40711 --- /dev/null +++ b/resolv/res_hconf.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@azstarnet.com). + +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _RES_HCONF_H_ +#define _RES_HCONF_H_ + +#include <netdb.h> + +#define TRIMDOMAINS_MAX 4 + +enum Name_Service { + SERVICE_NONE = 0, + SERVICE_BIND, SERVICE_HOSTS, SERVICE_NIS, + SERVICE_MAX +}; + +struct hconf { + int num_services; + enum Name_Service service[SERVICE_MAX]; + int num_trimdomains; + const char * trimdomain[TRIMDOMAINS_MAX]; + unsigned flags; +# define HCONF_FLAG_INITED (1 << 0) /* initialized? */ +# define HCONF_FLAG_SPOOF (1 << 1) /* refuse spoofed addresses */ +# define HCONF_FLAG_SPOOFALERT (1 << 2) /* syslog warning of spoofed */ +# define HCONF_FLAG_REORDER (1 << 3) /* list best address first */ +# define HCONF_FLAG_MULTI (1 << 4) /* see comments for gethtbyname() */ +} _res_hconf; + +extern void _res_hconf_init (void); +extern void _res_hconf_trim_domain (char * domain); +extern void _res_hconf_trim_domains (struct hostent * hp); +extern void _res_hconf_reorder_addrs (struct hostent * hp); + +#endif /* _RES_HCONF_H_ */ diff --git a/resolv/res_init.c b/resolv/res_init.c index 42c7c2ef8c..4e8af680c1 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -3,7 +3,7 @@ * - * Copyright (c) 1985, 1989, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -76,6 +76,8 @@ static char rcsid[] = "$Id$"; # include "../conf/portability.h" #endif +#include "res_hconf.h" + /*-------------------------------------- info about "sortlist" -------------- * Marc Majka 1994/04/16 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x) @@ -137,7 +139,7 @@ struct __res_state _res; * since it was noted that INADDR_ANY actually meant ``the first interface * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, * it had to be "up" in order for you to reach your own name server. It - * was later decided that since the recommended practice is to always + * was later decided that since the recommended practice is to always * install local static routes through 127.0.0.1 for all your network * interfaces, that we could solve this problem without a code change. * @@ -354,11 +356,11 @@ res_init() if (inet_aton(net, &a)) { _res.sort_list[nsort].mask = a.s_addr; } else { - _res.sort_list[nsort].mask = + _res.sort_list[nsort].mask = net_mask(_res.sort_list[nsort].addr); } } else { - _res.sort_list[nsort].mask = + _res.sort_list[nsort].mask = net_mask(_res.sort_list[nsort].addr); } nsort++; @@ -373,7 +375,7 @@ res_init() continue; } } - if (nserv > 1) + if (nserv > 1) _res.nscount = nserv; #ifdef RESOLVSORT _res.nsort = nsort; @@ -419,6 +421,8 @@ res_init() if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(cp, "env"); _res.options |= RES_INIT; + + _res_hconf_init (); return (0); } @@ -458,6 +462,8 @@ res_setoptions(options, source) } printf(";;\tdebug\n"); #endif + } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { + _res.options |= RES_USE_INET6; } else { /* XXX - print a warning here? */ } @@ -562,7 +568,7 @@ netinfo_res_init(haveenv, havesearch) } ni_namelist_free(&nl); } - + if (nserv > 1) _res.nscount = nserv; diff --git a/resolv/resolv.h b/resolv/resolv.h index 1a4a0dec89..0f5d5b855b 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -3,7 +3,7 @@ * - * Copyright (c) 1983, 1987, 1989, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -140,6 +140,7 @@ struct __res_state { #define RES_INSECURE1 0x00000400 /* type 1 security disabled */ #define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ #define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) @@ -185,7 +186,9 @@ extern struct __res_state _res; /* Private routines shared between libc/net, named, nslookup and others. */ #define res_hnok __res_hnok -#define dn_isvalid __dn_isvalid +#define res_ownok __res_ownok +#define res_mailok __res_mailok +#define res_dnok __res_dnok #define dn_skipname __dn_skipname #define fp_query __fp_query #define fp_nquery __fp_nquery @@ -206,7 +209,9 @@ extern struct __res_state _res; #define res_queriesmatch __res_queriesmatch __BEGIN_DECLS int __res_hnok __P((const char *)); -int __dn_isvalid __P((const char *)); +int __res_ownok __P((const char *)); +int __res_mailok __P((const char *)); +int __res_dnok __P((const char *)); int __dn_skipname __P((const u_char *, const u_char *)); void __fp_resstat __P((struct __res_state *, FILE *)); void __fp_query __P((const u_char *, FILE *)); diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 2970dd3db0..00e34c520e 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -46,4 +46,5 @@ tests := tst-printf tstscanf test_rdwr test-popen tstgetln test-fseek \ include ../Rules +CFLAGS-_itoa.c = -Wno-unused CFLAGS-tst-printf.c = -Wno-format diff --git a/stdio-common/getline.c b/stdio-common/getline.c index f103979333..7e78547c90 100644 --- a/stdio-common/getline.c +++ b/stdio-common/getline.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1992, 1995, 1996 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,21 +16,20 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> #include <stddef.h> #include <stdio.h> #undef __getline #ifdef USE_IN_LIBIO +# include "../libio/libioP.h" # define ssize_t _IO_ssize_t # define __getdelim _IO_getdelim #endif /* Like getdelim, but always looks for a newline. */ ssize_t -DEFUN(__getline, (lineptr, n, stream), - char **lineptr AND size_t *n AND FILE *stream) +__getline (char **lineptr, size_t *n, FILE *stream) { return __getdelim (lineptr, n, '\n', stream); } diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index d133ef1a02..badaa2f93d 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> #include "../locale/localeinfo.h" #include <errno.h> #include <limits.h> diff --git a/stdlib/Makefile b/stdlib/Makefile index ddcc385ab9..d30a0f2a06 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -40,7 +40,7 @@ routines := \ drand48-iter \ strtol strtoul strtoq strtouq \ strtof strtod strtold \ - system realpath \ + system canonicalize \ a64l l64a \ rpmatch strfmon diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c new file mode 100644 index 0000000000..55ac1bcf1d --- /dev/null +++ b/stdlib/canonicalize.c @@ -0,0 +1,196 @@ +/* Return the canonical absolute name of a given file. +Copyright (C) 1996 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <sys/stat.h> +#include <errno.h> + +/* Return the canonical absolute name of file NAME. The last file name + component need not exist, and may be a symlink to a nonexistent file. + If RESOLVED is null, the result is malloc'd; otherwise, if the canonical + name is PATH_MAX chars or more, returns null with `errno' set to + ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the + name in RESOLVED. */ + +static char * +canonicalize (const char *name, char *resolved) +{ + struct stat st; + const char *p; + long int path_max; + char *result, *dir, *end; + size_t namelen; + + if (! resolved) + path_max = 0; + else + { +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = sysconf (_SC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + } + + p = strrchr (name, '/'); + if (!p) + { + dir = (char *) "."; + p = name; + } + else + { + if (p++ == name) + dir = (char *) "/"; + else + { + dir = __alloca (p - name); + memcpy (dir, name, p - name - 1); + dir[p - name] = '\0'; + } + } + + result = __canonicalize_directory_name_internal (dir, resolved, path_max); + if (!result) + return NULL; + + /* Reconstruct the file name in the canonicalized directory. */ + namelen = strlen (name); + end = strchr (result, '\0'); + if (resolved) + { + /* Make sure the name is not too long. */ + if (end - result + namelen > path_max) + { + errno = ENAMETOOLONG; + return NULL; + } + } + else + { + /* The name is dynamically allocated. Extend it. */ + char *new = realloc (result, end - result + namelen + 1); + if (! new) + { + free (result); + return NULL; + } + end = new + (end - result); + result = new; + } + memcpy (end, name, namelen + 1); + + while (__lstat (result, &st) == 0 && S_ISLNK (st.st_mode)) + { + /* The file is a symlink. Read its contents. */ + ssize_t n; + read_link_contents: + n = readlink (result, end, + resolved ? result + path_max - end : namelen + 1); + if (n < 0) + /* Error reading the link contents. */ + return NULL; + + if (end[0] == '/') + { + /* Absolute symlink. */ + if (resolved ? (end + n < result + path_max) : (n < namelen + 1)) + { + /* It fit in our buffer, so we have the whole thing. */ + memcpy (result, end, n); + result[n] = '\0'; + } + else if (resolved) + { + /* It didn't fit in the remainder of the buffer. Either it + fits in the entire buffer, or it doesn't. Copy back the + unresolved name onto the canonical directory and try once + more. */ + memcpy (end, name, namelen + 1); + n = readlink (result, result, path_max); + if (n < 0) + return NULL; + if (n == path_max) + { + errno = ENAMETOOLONG; + return NULL; + } + result[n] = '\0'; + } + else + /* Try again with a bigger buffer. */ + goto extend_buffer; + + /* Check the resolved name for being a symlink too. */ + continue; + } + + if (resolved) + { + if (end + n == result + path_max) + { + /* The link contents we read fill the buffer completely. + There may be even more to read, and there is certainly no + space for the null terminator. */ + errno = ENAMETOOLONG; + return NULL; + } + } + else if (n == namelen + 1) + extend_buffer: + { + /* The name buffer is dynamically allocated. Extend it. */ + char *new; + + /* Copy back the unresolved name onto the canonical directory. */ + memcpy (end, name, namelen + 1); + + /* Make more space for readlink. */ + namelen *= 2; + new = realloc (result, end - result + namelen + 1); + if (! new) + { + free (result); + return NULL; + } + end = new + (end - result); + result = new; + + goto read_link_contents; + } + + /* Terminate the string; readlink does not. */ + end[n] = '\0'; + } + + return result; +} + +weak_alias (canonicalize, realpath) + +char * +canonicalize_file_name (const char *name) +{ + return canonicalize (name, NULL); +} diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h index 2fde1c806f..1853c5babb 100644 --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h @@ -364,6 +364,24 @@ extern void unsetenv __P ((__const char *__name)); extern int system __P ((__const char *__command)); +#ifdef __USE_GNU +/* Return a malloc'd string containing the canonical absolute name of the + named file. The last file name component need not exist, and may be a + symlink to a nonexistent file. */ +extern char *canonicalize_file_name __P ((__const char *__name)); +#endif + +#ifdef __USE_BSD +/* Return the canonical absolute name of file NAME. The last file name + component need not exist, and may be a symlink to a nonexistent file. + If RESOLVED is null, the result is malloc'd; otherwise, if the canonical + name is PATH_MAX chars or more, returns null with `errno' set to + ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the + name in RESOLVED. */ +extern char *realpath __P ((__const char *__name, char *__resolved)); +#endif + + /* Shorthand for type of comparison functions. */ #ifndef __COMPAR_FN_T #define __COMPAR_FN_T diff --git a/sysdeps/mach/hurd/getcwd.c b/sysdeps/mach/hurd/getcwd.c index ed8ed96697..463b28ce29 100644 --- a/sysdeps/mach/hurd/getcwd.c +++ b/sysdeps/mach/hurd/getcwd.c @@ -29,14 +29,16 @@ Cambridge, MA 02139, USA. */ #include <fcntl.h> -/* Get the pathname of the current working directory, and put it in SIZE - bytes of BUF. Returns NULL if the directory couldn't be determined or - SIZE was too small. If successful, returns BUF. In GNU, if BUF is - NULL, an array is allocated with `malloc'; the array is SIZE bytes long, - unless SIZE <= 0, in which case it is as big as necessary. */ +/* Get the canonical absolute name of the given directory port, and put it + in SIZE bytes of BUF. Returns NULL if the directory couldn't be + determined or SIZE was too small. If successful, returns BUF. In GNU, + if BUF is NULL, an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE <= 0, in which case it is as big as necessary. */ char * -__getcwd (char *buf, size_t size) +_hurd_canonicalize_directory_name_internal (file_t thisdir, + char *buf, + size_t size) { error_t err; mach_port_t rootid, thisid, rootdevid, thisdevid; @@ -91,10 +93,9 @@ __getcwd (char *buf, size_t size) return __hurd_fail (err), NULL; __mach_port_deallocate (__mach_task_self (), rootdevid); - /* Get a port to our current working directory and stat it. */ + /* Stat the port to the directory of interest. */ - if (err = __USEPORT (CRDIR, __io_identity (port, - &thisid, &thisdevid, &thisino))) + if (err = __io_identity (thisdir, &thisid, &thisdevid, &thisino)) { __mach_port_deallocate (__mach_task_self (), rootid); return __hurd_fail (err), NULL; @@ -255,4 +256,32 @@ __getcwd (char *buf, size_t size) cleanup (); return NULL; } + +char * +__canonicalize_directory_name_internal (thisdir, buf, size) + const char *thisdir; + char *buf; + size_t size; +{ + char *result; + file_t port = __file_name_lookup (thisdir, 0, 0); + if (port == MACH_PORT_NULL) + return NULL; + result = _hurd_canonicalize_directory_name_internal (port, buf, size); + __mach_port_deallocate (__mach_task_self (), port); + return result; +} + +/* Get the pathname of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined or + SIZE was too small. If successful, returns BUF. In GNU, if BUF is + NULL, an array is allocated with `malloc'; the array is SIZE bytes long, + unless SIZE <= 0, in which case it is as big as necessary. */ +char * +__getcwd (char *buf, size_t size) +{ + return __USEPORT (CWDIR, + _hurd_canonicalize_directory_name_internal (port, + buf, size)); +} weak_alias (__getcwd, getcwd) diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c index af858a2643..05f626f869 100644 --- a/sysdeps/posix/getcwd.c +++ b/sysdeps/posix/getcwd.c @@ -180,18 +180,15 @@ extern char *alloca (); #define __lstat stat #endif -#ifndef _LIBC -#define __getcwd getcwd -#endif - -/* Get the pathname of the current working directory, and put it in SIZE +/* Get the canonical absolute name of the named directory, and put it in SIZE bytes of BUF. Returns NULL if the directory couldn't be determined or SIZE was too small. If successful, returns BUF. In GNU, if BUF is NULL, an array is allocated with `malloc'; the array is SIZE bytes long, unless SIZE <= 0, in which case it is as big as necessary. */ char * -__getcwd (buf, size) +__canonicalize_directory_name_internal (thisdir, buf, size) + const char *thisdir; char *buf; size_t size; { @@ -230,7 +227,7 @@ __getcwd (buf, size) pathp = path + size; *--pathp = '\0'; - if (__lstat (".", &st) < 0) + if (__lstat (thisdir, &st) < 0) return NULL; thisdev = st.st_dev; thisino = st.st_ino; @@ -369,6 +366,24 @@ __getcwd (buf, size) free ((__ptr_t) dotlist); return NULL; } + +/* Get the pathname of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined or + SIZE was too small. If successful, returns BUF. In GNU, if BUF is + NULL, an array is allocated with `malloc'; the array is SIZE bytes long, + unless SIZE <= 0, in which case it is as big as necessary. */ + +#ifndef _LIBC +#define __getcwd getcwd +#endif + +char * +__getcwd (buf, size) + char *buf; + size_t size; +{ + return __canonicalize_directory_name_internal (".", buf, size); +} #ifdef _LIBC weak_alias (__getcwd, getcwd) diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index c70a6e8d35..fdddae2d0c 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 93, 94, 95, 96 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,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> #include <errno.h> #include <stddef.h> #include <stdio.h> @@ -34,7 +33,7 @@ Cambridge, MA 02139, USA. */ /* Return nonzero if DIR is an existent directory. */ static int -DEFUN(diraccess, (dir), CONST char *dir) +diraccess (const char *dir) { struct stat buf; return __stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); @@ -42,7 +41,7 @@ DEFUN(diraccess, (dir), CONST char *dir) /* Return nonzero if FILE exists. */ static int -DEFUN(exists, (file), CONST char *file) +exists (const char *file) { /* We can stat the file even if we can't read its data. */ struct stat st; @@ -64,7 +63,7 @@ DEFUN(exists, (file), CONST char *file) /* These are the characters used in temporary filenames. */ -static CONST char letters[] = +static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /* Generate a temporary filename and return it (in a static buffer). If @@ -82,13 +81,11 @@ static CONST char letters[] = existing file will be returned. When the cycle reaches its end (12345ZZZ), NULL is returned. */ char * -DEFUN(__stdio_gen_tempname, (dir, pfx, dir_search, lenptr, streamptr), - CONST char *dir AND CONST char *pfx AND - int dir_search AND size_t *lenptr AND - FILE **streamptr) +__stdio_gen_tempname (const char *dir, const char *pfx, int dir_search, + size_t *lenptr, FILE **streamptr) { int saverrno = errno; - static CONST char tmpdir[] = P_tmpdir; + static const char tmpdir[] = P_tmpdir; static size_t indices[2]; size_t *idx; static char buf[FILENAME_MAX]; @@ -98,7 +95,7 @@ DEFUN(__stdio_gen_tempname, (dir, pfx, dir_search, lenptr, streamptr), if (dir_search) { - register CONST char *d = getenv ("TMPDIR"); + register const char *d = getenv ("TMPDIR"); if (d != NULL && !diraccess (d)) d = NULL; if (d == NULL && dir != NULL && diraccess (dir)) diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index d25e0525ca..8c9fcfe934 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -16,8 +16,29 @@ endif ifeq ($(subdir), misc) sysdep_routines += mount umount xmknod s_ptrace s_sysctl sysctl llseek \ -setfsgid setfsuid sysinfo uselib +setfsgid setfsuid sysinfo uselib s_reboot headers += sys/mount.h sys/sysinfo.h sys/acct.h sys/sysctl.h + +install-others += $(includedir)/sys/syscall.h + +$(includedir)/sys/syscall.h:: + @rm -f $(objpfx)syscall.h $(objpfx)syscall.sed + @(os=`uname -sr`; \ + echo -e '1i\\\n#ifndef _SYS_SYSCALL_H\\'; \ + echo -e '#define _SYS_SYSCALL_H\t1\\\n\\'; \ + echo -e -n '/* This file is automatically generated as part of '; \ + echo -e 'GNU libc-$(version)\\'; \ + echo -e " on a system running $$os. */\\"; echo; \ + echo -e -n 's/#define __NR_\\([A-Za-z0-9_]*\\)[ \t]*__NR_\\(.*\\)/';\ + echo -e '#define SYS_\\1 SYS_\\2/p'; \ + echo -e -n 's/#define __NR_\\([A-Za-z0-9_]*\\)[ \t]*\\(.*\\)/';\ + echo -e '#define SYS_\\1 \\2/p'; \ + echo -e '$$i\\\n\\\n#endif\t/* sys/syscall.h */\nd') \ + > $(objpfx)syscall.sed + set -- `echo '#include <asm/unistd.h>'|$(CC) -M -E -`; \ + sed -f $(objpfx)syscall.sed $$2 > $(objpfx)syscall.h + $(INSTALL_DATA) $(objpfx)syscall.h $@ + rm -f $(objpfx)syscall.h $(objpfx)syscall.sed endif ifeq ($(subdir), time) diff --git a/sysdeps/unix/sysv/linux/reboot.c b/sysdeps/unix/sysv/linux/reboot.c new file mode 100644 index 0000000000..ecda522444 --- /dev/null +++ b/sysdeps/unix/sysv/linux/reboot.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1996 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 <unistd.h> + +extern int __syscall_reboot (int magic, int magic_too, int flag); + +/* Call kernel with additional two arguments the syscall requires. */ +int +reboot (int howto) +{ + return __syscall_reboot (0xfee1dead, 672274793, howto); +} diff --git a/sysdeps/unix/sysv/linux/sys/reboot.h b/sysdeps/unix/sysv/linux/sys/reboot.h new file mode 100644 index 0000000000..a7b86fa804 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sys/reboot.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1996 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. */ + +/* This file should define RB_* macros to be used as flag + bits in the argument to the `reboot' system call. */ + +#ifndef _SYS_REBOOT_H + +#define _SYS_REBOOT_H 1 +#include <features.h> + +/* Perform a hard reset now. */ +#define RB_AUTOBOOT 0x01234567 + +/* Halt the system. */ +#define RB_HALT_SYSTEM 0xcdef0123 + +/* Enable reboot using Ctrl-Alt-Delete keystroke. */ +#define RB_ENABLE_CAD 0x89abcdef + +/* Disable reboot using Ctrl-Alt-Delete keystroke. */ +#define RB_DISABLE_CAD 0 + + +/* Reboot or halt the system. */ +extern int reboot __P ((int __howto)); + +#endif /* sys/reboot.h */ diff --git a/sysdeps/unix/sysv/linux/syscall.h b/sysdeps/unix/sysv/linux/syscall.h index efe285c1fe..62fca57d70 100644 --- a/sysdeps/unix/sysv/linux/syscall.h +++ b/sysdeps/unix/sysv/linux/syscall.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1995 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996 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 @@ -24,12 +24,4 @@ Cambridge, MA 02139, USA. */ from the kernel sources. */ #include <asm/unistd.h> -/* Among the system calls defined there are - _setdomainname - _fchdir - _readv - _writev - (This is a hack for the autoconf mechanism. Don't change a single - character, esp white spaces, unless you know what you are doing!) */ - #endif diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 019d746a73..f401bc8c60 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -23,7 +23,7 @@ munlockall - munlockall 0 __munlockall munlockall nanosleep - nanosleep 2 nanosleep personality init-first personality 1 __personality personality pipe - pipe 1 __pipe pipe -reboot - reboot 3 reboot +s_reboot - reboot 3 __syscall_reboot s_getpriority getpriority getpriority 2 __syscall_getpriority s_ptrace ptrace ptrace 4 __syscall_ptrace s_sigsuspend sigsuspend sigsuspend 3 __syscall_sigsuspend diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h index 2292bd84b6..3b15d9f38a 100644 --- a/wcsmbs/wchar.h +++ b/wcsmbs/wchar.h @@ -192,7 +192,7 @@ extern int wcswidth __P ((__const wchar_t *__s, size_t __n)); representation. */ extern double wcstod __P ((__const wchar_t *__nptr, wchar_t **__endptr)); -#ifdef USE_GNU +#ifdef __USE_GNU /* Likewise for `float' and `long double' sizes of floating-point numbers. */ extern float wcstof __P ((__const wchar_t *__nptr, wchar_t **__endptr)); extern __long_double_t wcstold __P ((__const wchar_t *__nptr, |