1997-05-29 12:48  Ulrich Drepper  <drepper@cygnus.com>

	* io/ftw.c: Complete rewrite.  Add implementation of `nftw'.
	* io/ftw.h: Update for new implementation and XPG4.2.

	* login/Makefile: Update for UTMP daemon implementation.

	Update resolver code to bind-4.9.6-T1A.
	* resolv/Banner: Update.
	* nss/digits_dots.c: Adapt text address matching to T1A.
	* nss/nss_files/files-hosts.c: Always use inet_pton.
	* resolv/base64.c (b64_pton): Follow T1A but don't use this code since
	it would lead to warnings.
	* resolv/gethnamaddr.c (getanswer): Test host name for maximal length
	at several places.
	* resolv/inet_net_pton.c (inet_net_pton_ipv4): Correct typo in comment.
	* resolv/res_comp.c (dn_expand): Check for overflow.
	(dn_comp): Likewise.
	* resolv/res_debug.c (precsize_aton): Better implementation.
	* resolv/res_init.c (res_init): Make `buf' of size MAXDNAME.
	* resolv/res_send.c (res_send): Check for overflow in descriptor set.
	* resolv/nss_dns/dns-host.c (getanswer_r): Test host name for maximal
	length at several places.

1997-05-29 12:51  Mark Kettenis  <kettenis@phys.uva.nl>

	* login/utmp-private.h (struct utfuncs): Add one more parameter
	to updwtmp function.
	Declare all three function jump tables.
	* login/utmp.h: Declare __utmpname.
	* login/getutent_r.c: Remove db backend and provide support for
	utmpd backend.
	* login/login.c: Use `updwtmp' function insteead of writing the
	record ourself.
	* login/logwtmp.c: Move `updwtmp' function to...
	* login/updwtmp.c: ...here.  New file.
	* login/utmp_db.h: Removed.
	* login/utmp_file.c: Add updwtmp function to write to file.
	* login/utmp_daemon.c: New file.  Daemon backend.
	* login/utmpname.c: New file.  Implementation of utmpname function.
	* login/utmpdump.c: New file.  Tool to dump utmp-like files.
	* login/utmpd/connection.c: New file.
	* login/utmpd/database.c: New file.
	* login/utmpd/error.c: New file.
	* login/utmpd/request.c: New file.
	* login/utmpd/utmpd-private.h: New file.
	* login/utmpd/utmpd.c: New file.
	* login/utmpd/utmpd.h: New file.
	* login/utmpd/xtmp.c: New file.
	* login/utmpd/xtmp.h: New file.

1997-05-29 12:28  Jim Meyering  <meyering@eng.ascend.com>

	* time/strftime.c: Correct/normalize indentation in cpp directives.

1997-05-28 20:43  Philip Blundell  <pjb27@cam.ac.uk>

	* nis/nis_error.c: Include <string.h> to fix warning.
	* nis/nis_print.c: Likewise.
	* nis/nss_nisplus/nisplus-hosts.c: Arg 3 of map_v4v6_hostent
	is int* not size_t*.

1997-05-28 21:56  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* math/cmathcalls.h: Correct typo in comment.

	* inet/netinet/icmp6.h: Include <netinet/in.h> for in6_addr.

	* sysdeps/unix/sysv/linux/netinet/ip_fw.h: Include <net/if.h> for
	IFNAMSIZ.

	* sysdeps/unix/sysv/linux/net/ppp_defs.h: Include <time.h> for
	time_t.

	* login/pty.h: Include <ioctl-types.h> for definition of struct
	winsize.

	* misc/regexp.h (compile): Correct typo.

	* argp/argp.h: Put extern before __const in defintion of
	argp_program_bug_address.

1997-05-29 00:20  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/wordsize-32/inttypes.h: Correct names of unsigned fast
	and least types.  Correct names of ?INT_FAST*_{MIN,MAX} macros.
	* sysdeps/wordsize-64/inttypes.h: Likewise.
	Reported by Andreas Jaeger <aj@arthur.rhein-neckar.de>.

1997-05-28 22:51  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/Makefile (make-ioctls-CFLAGS): Use generic
	ttydefaults.h file instead of non-existing version in termios/sys.
	Reported by Zack Weinberg <zack@rabi.phys.columbia.edu>.

	* time/strptime.c (strptime_internal, case 'Y'): Restrict year
	number to four digits and to representable range for 4 byte time_t
	values.
	Patch by H.J. Lu <hjl@lucon.org>.

1997-05-28 18:19  Philip Blundell  <pjb27@cam.ac.uk>

	* posix/execl.c: Include <alloca.h> to avoid warning.

1997-05-27 18:19  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* math/libm-test.c: Implement testing of inlined functions, make
	output nicer, update comments.

	* math/test-idouble.c: New file.  Frontend for double tests of
	inlined functions.
	* math/test-ildoubl.c: New file.  Frontend for long double tests of
	inlined functions.
	* math/test-ifloat.c: New file.  Frontend for float tests of
	inlined functions.

	* math/test-longdouble.c: Rename to...
	* math/test-ldouble.c: ...this.

	* math/Makefile: Add rules for new test programs, change rules for
	renaming of longdouble test.

1997-05-20 15:50  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* sunrpc/rpc/svc.h (__dispatch_fn_t): New.
	(svc_register): Use __dispatch_fn_t in prototype.

1997-05-28 17:02  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/generic/bzero.c (bzero): Fix typo.
	Patch by Witek Wnuk <spider@pest.waw.ids.edu.pl>.

1997-05-27 12:00  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* sysdeps/generic/vtimes.c: Use ISO C declaration style.

	* sysdeps/unix/bsd/ualarm.c: Include <unistd.h> for prototype.

	* sysdeps/generic/memccpy.c: Include <string.h> for prototype.

	* signal/tst-signal.c (handler): Correct function declaration to
	avoid warning.
	* stdlib/testsort.c (compare): Likewise.
	* string/tester.c: Likewise.

1997-05-27 14:16  Miles Bader  <miles@gnu.ai.mit.edu>

	* argp-help.c (argp_args_usage): Supply correct argp to filter_doc.

1997-05-27 17:51  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* db/hash/extern.h, db/hash/hash.c, db/hash/hash.h,
	db/hash/hash_log2.c: Rename __log2 to __hash_log2 to avoid clash
	with libm.

1997-05-27 14:47  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/m68k/fpu/e_atan2.c: Fix missing negate.  Use __m81_test
	instead of explicit comparisons.

1997-05-26 18:36  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* inet/netinet/icmp6.h: Remove use of <asm/bitops.h> which has no
	place in a generic header and is no user include file.
This commit is contained in:
Ulrich Drepper 1997-05-29 12:06:58 +00:00
parent 06bdbaa0a6
commit 76b87c039b
72 changed files with 4290 additions and 704 deletions

165
ChangeLog
View File

@ -1,3 +1,168 @@
1997-05-29 12:48 Ulrich Drepper <drepper@cygnus.com>
* io/ftw.c: Complete rewrite. Add implementation of `nftw'.
* io/ftw.h: Update for new implementation and XPG4.2.
* login/Makefile: Update for UTMP daemon implementation.
Update resolver code to bind-4.9.6-T1A.
* resolv/Banner: Update.
* nss/digits_dots.c: Adapt text address matching to T1A.
* nss/nss_files/files-hosts.c: Always use inet_pton.
* resolv/base64.c (b64_pton): Follow T1A but don't use this code since
it would lead to warnings.
* resolv/gethnamaddr.c (getanswer): Test host name for maximal length
at several places.
* resolv/inet_net_pton.c (inet_net_pton_ipv4): Correct typo in comment.
* resolv/res_comp.c (dn_expand): Check for overflow.
(dn_comp): Likewise.
* resolv/res_debug.c (precsize_aton): Better implementation.
* resolv/res_init.c (res_init): Make `buf' of size MAXDNAME.
* resolv/res_send.c (res_send): Check for overflow in descriptor set.
* resolv/nss_dns/dns-host.c (getanswer_r): Test host name for maximal
length at several places.
1997-05-29 12:51 Mark Kettenis <kettenis@phys.uva.nl>
* login/utmp-private.h (struct utfuncs): Add one more parameter
to updwtmp function.
Declare all three function jump tables.
* login/utmp.h: Declare __utmpname.
* login/getutent_r.c: Remove db backend and provide support for
utmpd backend.
* login/login.c: Use `updwtmp' function insteead of writing the
record ourself.
* login/logwtmp.c: Move `updwtmp' function to...
* login/updwtmp.c: ...here. New file.
* login/utmp_db.h: Removed.
* login/utmp_file.c: Add updwtmp function to write to file.
* login/utmp_daemon.c: New file. Daemon backend.
* login/utmpname.c: New file. Implementation of utmpname function.
* login/utmpdump.c: New file. Tool to dump utmp-like files.
* login/utmpd/connection.c: New file.
* login/utmpd/database.c: New file.
* login/utmpd/error.c: New file.
* login/utmpd/request.c: New file.
* login/utmpd/utmpd-private.h: New file.
* login/utmpd/utmpd.c: New file.
* login/utmpd/utmpd.h: New file.
* login/utmpd/xtmp.c: New file.
* login/utmpd/xtmp.h: New file.
1997-05-29 12:28 Jim Meyering <meyering@eng.ascend.com>
* time/strftime.c: Correct/normalize indentation in cpp directives.
1997-05-28 20:43 Philip Blundell <pjb27@cam.ac.uk>
* nis/nis_error.c: Include <string.h> to fix warning.
* nis/nis_print.c: Likewise.
* nis/nss_nisplus/nisplus-hosts.c: Arg 3 of map_v4v6_hostent
is int* not size_t*.
1997-05-28 21:56 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* math/cmathcalls.h: Correct typo in comment.
* inet/netinet/icmp6.h: Include <netinet/in.h> for in6_addr.
* sysdeps/unix/sysv/linux/netinet/ip_fw.h: Include <net/if.h> for
IFNAMSIZ.
* sysdeps/unix/sysv/linux/net/ppp_defs.h: Include <time.h> for
time_t.
* login/pty.h: Include <ioctl-types.h> for definition of struct
winsize.
* misc/regexp.h (compile): Correct typo.
* argp/argp.h: Put extern before __const in defintion of
argp_program_bug_address.
1997-05-29 00:20 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/wordsize-32/inttypes.h: Correct names of unsigned fast
and least types. Correct names of ?INT_FAST*_{MIN,MAX} macros.
* sysdeps/wordsize-64/inttypes.h: Likewise.
Reported by Andreas Jaeger <aj@arthur.rhein-neckar.de>.
1997-05-28 22:51 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/Makefile (make-ioctls-CFLAGS): Use generic
ttydefaults.h file instead of non-existing version in termios/sys.
Reported by Zack Weinberg <zack@rabi.phys.columbia.edu>.
* time/strptime.c (strptime_internal, case 'Y'): Restrict year
number to four digits and to representable range for 4 byte time_t
values.
Patch by H.J. Lu <hjl@lucon.org>.
1997-05-28 18:19 Philip Blundell <pjb27@cam.ac.uk>
* posix/execl.c: Include <alloca.h> to avoid warning.
1997-05-27 18:19 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* math/libm-test.c: Implement testing of inlined functions, make
output nicer, update comments.
* math/test-idouble.c: New file. Frontend for double tests of
inlined functions.
* math/test-ildoubl.c: New file. Frontend for long double tests of
inlined functions.
* math/test-ifloat.c: New file. Frontend for float tests of
inlined functions.
* math/test-longdouble.c: Rename to...
* math/test-ldouble.c: ...this.
* math/Makefile: Add rules for new test programs, change rules for
renaming of longdouble test.
1997-05-20 15:50 H.J. Lu <hjl@gnu.ai.mit.edu>
* sunrpc/rpc/svc.h (__dispatch_fn_t): New.
(svc_register): Use __dispatch_fn_t in prototype.
1997-05-28 17:02 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/generic/bzero.c (bzero): Fix typo.
Patch by Witek Wnuk <spider@pest.waw.ids.edu.pl>.
1997-05-27 12:00 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* sysdeps/generic/vtimes.c: Use ISO C declaration style.
* sysdeps/unix/bsd/ualarm.c: Include <unistd.h> for prototype.
* sysdeps/generic/memccpy.c: Include <string.h> for prototype.
* signal/tst-signal.c (handler): Correct function declaration to
avoid warning.
* stdlib/testsort.c (compare): Likewise.
* string/tester.c: Likewise.
1997-05-27 14:16 Miles Bader <miles@gnu.ai.mit.edu>
* argp-help.c (argp_args_usage): Supply correct argp to filter_doc.
1997-05-27 17:51 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* db/hash/extern.h, db/hash/hash.c, db/hash/hash.h,
db/hash/hash_log2.c: Rename __log2 to __hash_log2 to avoid clash
with libm.
1997-05-27 14:47 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* sysdeps/m68k/fpu/e_atan2.c: Fix missing negate. Use __m81_test
instead of explicit comparisons.
1997-05-26 18:36 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* inet/netinet/icmp6.h: Remove use of <asm/bitops.h> which has no
place in a generic header and is no user include file.
1997-05-27 02:20 Ulrich Drepper <drepper@cygnus.com>
* stdio/obstream.c (obstack_printf): Fix bug in

2
FAQ
View File

@ -432,7 +432,7 @@ ship the cryptographic function together with the libc.
But of course we provide the code and there is an very easy way to use
this code. First get the extra package. People in the US way get it
from the same place they got the GNU libc from. People outside the US
should get the code from ftp.uni-c.dk [129.142.6.74], or another
should get the code from ftp://ftp.ifi.uio.no/pub/gnu, or another
archive site outside the USA. The README explains how to install the
sources.

View File

@ -1315,8 +1315,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
int multiple = 0;
const struct argp_child *child = argp->children;
const char *tdoc = gettext (argp->args_doc), *nl = 0;
const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC,
state ? state->root_argp : 0, state);
const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
if (fdoc)
{

View File

@ -396,7 +396,7 @@ extern void (*argp_program_version_hook) __P ((FILE *__stream,
argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
standard help messages), embedded in a sentence that says something like
`Report bugs to ADDR.'. */
__const extern char *argp_program_bug_address;
extern __const char *argp_program_bug_address;
/* The exit status that argp will use when exiting due to a parsing error.
If not defined or set by the user program, this defaults to EX_USAGE from

View File

@ -52,7 +52,7 @@ void __free_ovflpage __P((HTAB *, BUFHEAD *));
BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int));
int __get_page __P((HTAB *, char *, u_int32_t, int, int, int));
int __ibitmap __P((HTAB *, int, int, int));
u_int32_t __log2 __P((u_int32_t));
u_int32_t __hash_log2 __P((u_int32_t));
int __put_page __P((HTAB *, char *, u_int32_t, int, int));
void __reclaim_buf __P((HTAB *, BUFHEAD *));
int __split_page __P((HTAB *, u_int32_t, u_int32_t));

View File

@ -303,13 +303,13 @@ init_hash(hashp, file, info)
if (stat(file, &statbuf))
return (NULL);
hashp->BSIZE = statbuf.st_blksize;
hashp->BSHIFT = __log2(hashp->BSIZE);
hashp->BSHIFT = __hash_log2(hashp->BSIZE);
}
if (info) {
if (info->bsize) {
/* Round pagesize up to power of 2 */
hashp->BSHIFT = __log2(info->bsize);
hashp->BSHIFT = __hash_log2(info->bsize);
hashp->BSIZE = 1 << hashp->BSHIFT;
if (hashp->BSIZE > MAX_BSIZE) {
errno = EINVAL;
@ -358,7 +358,7 @@ init_htab(hashp, nelem)
*/
nelem = (nelem - 1) / hashp->FFACTOR + 1;
l2 = __log2(MAX(nelem, 2));
l2 = __hash_log2(MAX(nelem, 2));
nbuckets = 1 << l2;
hashp->SPARES[l2] = l2 + 1;
@ -376,7 +376,7 @@ init_htab(hashp, nelem)
hashp->BSHIFT) + 1;
nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
nsegs = 1 << __log2(nsegs);
nsegs = 1 << __hash_log2(nsegs);
if (nsegs > hashp->DSIZE)
hashp->DSIZE = nsegs;
@ -843,7 +843,7 @@ __expand_table(hashp)
* * increases), we need to copy the current contents of the spare
* split bucket to the next bucket.
*/
spare_ndx = __log2(hashp->MAX_BUCKET + 1);
spare_ndx = __hash_log2(hashp->MAX_BUCKET + 1);
if (spare_ndx > hashp->OVFL_POINT) {
hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
hashp->OVFL_POINT = spare_ndx;

View File

@ -170,7 +170,7 @@ typedef struct htab { /* Memory resident data structure */
#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
#define BUCKET_TO_PAGE(B) \
(B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0)
(B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__hash_log2((B)+1)-1] : 0)
#define OADDR_TO_PAGE(B) \
BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));

View File

@ -42,10 +42,10 @@ static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
#include <db.h>
u_int32_t __log2 __P((u_int32_t));
u_int32_t __hash_log2 __P((u_int32_t));
u_int32_t
__log2(num)
__hash_log2(num)
u_int32_t num;
{
register u_int32_t i, limit;

View File

@ -20,6 +20,7 @@
#define _NETINET_ICMP6_H 1
#include <sys/types.h>
#include <netinet/in.h>
#define ICMPV6_FILTER 1
@ -77,21 +78,6 @@ struct icmpv6hdr
#define ICMPV6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
#define ICMPV6_PARAMPROB_OPTION 2 /* unrecognized option */
#if defined(__OPTIMIZE__)
#include <asm/bitops.h>
#define ICMPV6_FILTER_WILLPASS(type, filterp) \
(test_bit (type, filterp) == 0)
#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \
test_bit (type, filterp)
#define ICMPV6_FILTER_SETPASS(type, filterp) \
clear_bit (type & 0x1f, &((filterp)->data[type >> 5]))
#define ICMPV6_FILTER_SETBLOCK(type, filterp) \
set_bit (type & 0x1f, &((filterp)->data[type >> 5]))
#else
#define ICMPV6_FILTER_WILLPASS(type, filterp) \
((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) == 0)
@ -103,7 +89,6 @@ struct icmpv6hdr
#define ICMPV6_FILTER_SETBLOCK(type, filterp) \
((((filterp)->data[(type) >> 5]) |= (1 << ((type) & 31))))
#endif
#define ICMPV6_FILTER_SETPASSALL(filterp) \
memset (filterp, 0, sizeof (struct icmpv6_filter));

621
io/ftw.c
View File

@ -1,6 +1,7 @@
/* Copyright (C) 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
/* File tree walker functions.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ian Lance Taylor (ian@airs.com).
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
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
@ -17,197 +18,507 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <ftw.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ftw.h>
/* #define NDEBUG 1 */
#include <assert.h>
#ifndef PATH_MAX
#define PATH_MAX 1024 /* XXX */
#endif
/* Traverse one level of a directory tree. */
static int
ftw_dir (DIR **dirs, int level, int descriptors, char *dir, size_t len,
int (*func) (const char *file, const struct stat *status, int flag))
struct dir_data
{
int got;
struct dirent *entry;
DIR *stream;
char *content;
};
got = 0;
struct ftw_data
{
struct dir_data **dirstreams;
size_t actdir;
size_t maxdir;
__set_errno (0);
char *dirbuf;
size_t dirbufsize;
struct FTW ftw;
while ((entry = readdir (dirs[level])) != NULL)
int flags;
int *cvt_arr;
__nftw_func_t func;
struct stat st;
dev_t dev;
};
/* Internally we use the FTW_* constants used for `nftw'. When the
process called `ftw' we must reduce the flag to the known flags
for `ftw'. */
static int nftw_arr[] =
{
FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN
};
static int ftw_arr[] =
{
FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS
};
/* Forward declarations of local functions. */
static int ftw_dir (struct ftw_data *data);
static inline int
open_dir_stream (struct ftw_data *data, struct dir_data *dirp)
{
int result = 0;
if (data->dirstreams[data->actdir] != NULL)
{
struct stat s;
int flag, retval, newlev;
size_t namlen;
/* Oh, oh. We must close this stream. Get all remaining
entries and store them as a list in the `content' member of
the `struct dir_data' variable. */
size_t bufsize = 1024;
char *buf = malloc (bufsize);
++got;
if (entry->d_name[0] == '.'
&& (entry->d_name[1] == '\0' ||
(entry->d_name[1] == '.' && entry->d_name[2] == '\0')))
if (buf == NULL)
result = -1;
else
{
__set_errno (0);
continue;
}
DIR *st = data->dirstreams[data->actdir]->stream;
struct dirent *d;
size_t actsize = 0;
namlen = _D_EXACT_NAMLEN (entry);
while ((d = readdir (st)) != NULL)
{
size_t this_len = _D_EXACT_NAMLEN (d);
if (actsize + this_len + 2 >= bufsize)
{
char *newp;
bufsize += MAX (1024, 2 * this_len);
newp = realloc (buf, bufsize);
if (newp == NULL)
{
/* No more memory. */
int save_err = errno;
free (buf);
__set_errno (save_err);
result = -1;
break;
}
buf = newp;
}
if (namlen + len + 1 > PATH_MAX)
{
#ifdef ENAMETOOLONG
__set_errno (ENAMETOOLONG);
#else
__set_errno (ENOMEM);
#endif
return -1;
}
memcpy (buf + actsize, d->d_name, this_len);
actsize += this_len;
buf[actsize++] = '\0';
}
dir[len] = '/';
memcpy ((void *) (dir + len + 1), (void *) entry->d_name,
namlen + 1);
/* Terminate the list with an additional NUL byte. */
buf[actsize++] = '\0';
if (stat (dir, &s) < 0)
{
if (errno != EACCES && errno != ENOENT)
return -1;
flag = FTW_NS;
}
else if (S_ISDIR (s.st_mode))
{
newlev = (level + 1) % descriptors;
if (dirs[newlev] != NULL)
closedir (dirs[newlev]);
dirs[newlev] = opendir (dir);
if (dirs[newlev] != NULL)
flag = FTW_D;
/* Shrink the buffer to what we actually need. */
data->dirstreams[data->actdir]->content = realloc (buf, actsize);
if (data->dirstreams[data->actdir]->content == NULL)
{
int save_err = errno;
free (buf);
__set_errno (save_err);
result = -1;
}
else
{
if (errno != EACCES)
return -1;
flag = FTW_DNR;
closedir (st);
data->dirstreams[data->actdir]->stream = NULL;
data->dirstreams[data->actdir] = NULL;
}
}
else
flag = FTW_F;
retval = (*func) (dir, &s, flag);
if (flag == FTW_D)
{
if (retval == 0)
retval = ftw_dir (dirs, newlev, descriptors, dir,
namlen + len + 1, func);
if (dirs[newlev] != NULL)
{
int save;
save = errno;
closedir (dirs[newlev]);
__set_errno (save);
dirs[newlev] = NULL;
}
}
if (retval != 0)
return retval;
if (dirs[level] == NULL)
{
int skip;
dir[len] = '\0';
dirs[level] = opendir (dir);
if (dirs[level] == NULL)
return -1;
skip = got;
while (skip-- != 0)
{
__set_errno (0);
if (readdir (dirs[level]) == NULL)
return errno == 0 ? 0 : -1;
}
}
__set_errno (0);
}
return errno == 0 ? 0 : -1;
/* Open the new stream. */
if (result == 0)
{
assert (data->dirstreams[data->actdir] == NULL);
dirp->stream = opendir (data->dirbuf);
if (dirp->stream == NULL)
result = -1;
else
{
dirp->content = NULL;
data->dirstreams[data->actdir] = dirp;
if (++data->actdir == data->maxdir)
data->actdir = 0;
}
}
return result;
}
/* Call a function on every element in a directory tree. */
int
ftw (const char *dir,
int (*func) (const char *file, const struct stat *status, int flag),
int descriptors)
static inline int
process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
size_t namlen)
{
DIR **dirs;
size_t len;
char buf[PATH_MAX + 1];
struct stat s;
int flag, retval;
int i;
int result = 0;
int flag;
if (descriptors <= 0)
descriptors = 1;
if (name[0] == '.' && (name[1] == '\0'
|| (name[1] == '.' && name[2] == '\0')))
/* Don't process the "." and ".." entries. */
return 0;
dirs = (DIR **) __alloca (descriptors * sizeof (DIR *));
i = descriptors;
while (i-- > 0)
dirs[i] = NULL;
if (data->dirbufsize < data->ftw.base + namlen + 2)
{
/* Enlarge the buffer. */
char *newp;
if (stat (dir, &s) < 0)
data->dirbufsize *= 2;
newp = realloc (data->dirbuf, data->dirbufsize);
if (newp == NULL)
return -1;
data->dirbuf = newp;
}
memcpy (data->dirbuf + data->ftw.base, name, namlen);
data->dirbuf[data->ftw.base + namlen] = '\0';
if (((data->flags & FTW_PHYS) ? lstat : stat) (data->dirbuf, &data->st) < 0)
{
if (errno != EACCES && errno != ENOENT)
return -1;
flag = FTW_NS;
}
else if (S_ISDIR (s.st_mode))
{
dirs[0] = opendir (dir);
if (dirs[0] != NULL)
flag = FTW_D;
result = -1;
else if (!(data->flags & FTW_PHYS)
&& lstat (data->dirbuf, &data->st) == 0
&& S_ISLNK (data->st.st_mode))
flag = FTW_SLN;
else
{
if (errno != EACCES)
return -1;
flag = FTW_DNR;
}
flag = FTW_NS;
}
else
flag = FTW_F;
len = strlen (dir);
memcpy ((void *) buf, (void *) dir, len + 1);
retval = (*func) (buf, &s, flag);
if (flag == FTW_D)
{
if (retval == 0)
retval = ftw_dir (dirs, 0, descriptors, buf, len, func);
if (dirs[0] != NULL)
{
int save;
if (S_ISDIR (data->st.st_mode))
flag = FTW_D;
else if (S_ISLNK (data->st.st_mode))
flag = FTW_SL;
else
flag = FTW_F;
}
save = errno;
closedir (dirs[0]);
__set_errno (save);
if (result == 0
&& (!(data->flags & FTW_MOUNT) || data->st.st_dev == data->dev))
{
if (flag == FTW_D)
{
result = ftw_dir (data);
if (result == 0 && (data->flags & FTW_CHDIR))
{
/* Change back to current directory. */
int done = 0;
if (dir->stream != NULL)
if (fchdir (dirfd (dir->stream)) == 0)
done = 1;
if (!done)
{
if (data->ftw.base == 1)
{
if (chdir ("/") < 0)
result = -1;
}
else
{
/* Please note that we overwrite a slash. */
data->dirbuf[data->ftw.base - 1] = '\0';
if (chdir (data->dirbuf) < 0)
result = -1;
else
data->dirbuf[data->ftw.base - 1] = '/';
}
}
}
}
else
result = (*data->func) (data->dirbuf, &data->st, data->cvt_arr[flag],
&data->ftw);
}
return result;
}
static int
ftw_dir (struct ftw_data *data)
{
struct dir_data dir;
struct dirent *d;
int previous_base = data->ftw.base;
int result = 0;
char *startp;
/* First, report the directory (if not depth-first). */
if (!(data->flags & FTW_DEPTH))
{
result = (*data->func) (data->dirbuf, &data->st, FTW_D, &data->ftw);
if (result != 0)
return result;
}
/* Open the stream for this directory. This might require that
another stream has to be closed. */
result = open_dir_stream (data, &dir);
if (result != 0)
return result;
/* If necessary, change to this directory. */
if (data->flags & FTW_CHDIR)
{
if (fchdir (dirfd (dir.stream)) < 0)
{
if (errno == ENOSYS)
{
if (chdir (data->dirbuf) < 0)
result = -1;
}
else
result = -1;
}
if (result != 0)
{
int save_err = errno;
closedir (dir.stream);
__set_errno (save_err);
if (data->actdir-- == 0)
data->actdir = data->maxdir - 1;
data->dirstreams[data->actdir] = NULL;
return result;
}
}
return retval;
/* Next, update the `struct FTW' information. */
++data->ftw.level;
startp = strchr (data->dirbuf, '\0');
*startp++ = '/';
data->ftw.base = startp - data->dirbuf;
while (dir.stream != NULL && (d = readdir (dir.stream)) != NULL)
{
result = process_entry (data, &dir, d->d_name, _D_EXACT_NAMLEN (d));
if (result != 0)
break;
}
if (dir.stream != NULL)
{
/* The stream is still open. I.e., we did not need more
descriptors. Simply close the stream now. */
int save_err = errno;
assert (dir.content == NULL);
closedir (dir.stream);
__set_errno (save_err);
if (data->actdir-- == 0)
data->actdir = data->maxdir - 1;
data->dirstreams[data->actdir] = NULL;
}
else
{
int save_err;
char *runp = dir.content;
assert (result == 0);
while (*runp != '\0')
{
char *endp = strchr (runp, '\0');
result = process_entry (data, &dir, runp, endp - runp);
if (result != 0)
break;
runp = endp + 1;
}
save_err = errno;
free (dir.content);
__set_errno (save_err);
}
/* Prepare the return, revert the `struct FTW' information. */
--data->ftw.level;
data->ftw.base = previous_base;
/* Finally, if we process depth-first report the directory. */
if (result == 0 && (data->flags & FTW_DEPTH))
result = (*data->func) (data->dirbuf, &data->st, FTW_DP, &data->ftw);
return result;
}
static int
ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
int flags)
{
struct ftw_data data;
int result = 0;
int save_err;
char *cwd;
char *cp;
/* First make sure the parameters are reasonable. */
if (dir[0] == '\0')
{
__set_errno (ENOTDIR);
return -1;
}
data.maxdir = descriptors < 1 ? 1 : descriptors;
data.actdir = 0;
data.dirstreams = (struct dir_data **) alloca (data.maxdir
* sizeof (struct dir_data *));
memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));
data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
data.dirbuf = (char *) malloc (data.dirbufsize);
if (data.dirbuf == NULL)
return -1;
cp = stpcpy (data.dirbuf, dir);
/* Strip trailing slashes. */
while (cp > data.dirbuf + 1 && cp[-1] == '/')
--cp;
*cp = '\0';
data.ftw.level = 0;
/* Find basename. */
while (cp > data.dirbuf && cp[-1] != '/')
--cp;
data.ftw.base = cp - data.dirbuf;
data.flags = flags;
/* This assignment might seem to be strange but it is what we want.
The trick is that the first three arguments to the `ftw' and
`nftw' callback functions are equal. Therefore we can call in
every case the callback using the format of the `nftw' version
and get the correct result since the stack layout for a function
call in C allows this. */
data.func = (__nftw_func_t) func;
/* Since we internally use the complete set of FTW_* values we need
to reduce the value range before calling a `ftw' callback. */
data.cvt_arr = is_nftw ? nftw_arr : ftw_arr;
/* Now go to the directory containing the initial file/directory. */
if ((flags & FTW_CHDIR) && data.ftw.base > 0)
{
/* GNU extension ahead. */
cwd = getcwd (NULL, 0);
if (cwd == NULL)
result = -1;
else
{
/* Change to the directory the file is in. In data.dirbuf
we have a writable copy of the file name. Just NUL
terminate it for now and change the directory. */
if (data.ftw.base == 1)
/* I.e., the file is in the root directory. */
result = chdir ("/");
else
{
char ch = data.dirbuf[data.ftw.base - 1];
data.dirbuf[data.ftw.base - 1] = '\0';
result = chdir (data.dirbuf);
data.dirbuf[data.ftw.base - 1] = ch;
}
}
}
/* Get stat info for start directory. */
if (result == 0)
if (((flags & FTW_PHYS) ? lstat : stat) (data.dirbuf, &data.st) < 0)
{
if (errno == EACCES)
result = (*data.func) (data.dirbuf, &data.st, FTW_NS, &data.ftw);
else if (!(flags & FTW_PHYS)
&& errno == ENOENT
&& lstat (dir, &data.st) == 0 && S_ISLNK (data.st.st_mode))
result = (*data.func) (data.dirbuf, &data.st, data.cvt_arr[FTW_SLN],
&data.ftw);
else
/* No need to call the callback since we cannot say anything
about the object. */
result = -1;
}
else
{
if (S_ISDIR (data.st.st_mode))
{
data.dev = data.st.st_dev;
result = ftw_dir (&data);
}
else
{
int flag = S_ISLNK (data.st.st_mode) ? FTW_SL : FTW_F;
result = (*data.func) (data.dirbuf, &data.st, data.cvt_arr[flag],
&data.ftw);
}
}
/* Return to the start directory (if necessary). */
if (cwd != NULL)
{
int save_err = errno;
chdir (cwd);
free (cwd);
__set_errno (save_err);
}
/* Free all memory. */
save_err = errno;
free (data.dirbuf);
__set_errno (save_err);
return result;
}
/* Entry points. */
int
ftw (path, func, descriptors)
const char *path;
__ftw_func_t func;
int descriptors;
{
return ftw_startup (path, 0, func, descriptors, 0);
}
int
nftw (path, func, descriptors, flags)
const char *path;
__nftw_func_t func;
int descriptors;
int flags;
{
return ftw_startup (path, 1, func, descriptors, flags);
}

View File

@ -1,6 +1,5 @@
/* Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ian Lance Taylor (ian@airs.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
@ -26,22 +25,82 @@
#define _FTW_H 1
#include <features.h>
#include <sys/types.h>
#include <statbuf.h>
/* The FLAG argument to the user function passed to ftw. */
#define FTW_F 0 /* Regular file. */
#define FTW_D 1 /* Directory. */
#define FTW_DNR 2 /* Unreadable directory. */
#define FTW_NS 3 /* Unstatable file. */
__BEGIN_DECLS
/* Values for the FLAG argument to the user function passed to `ftw'
and 'nftw'. */
enum
{
FTW_F, /* Regular file. */
#define FTW_F FTW_F
FTW_D, /* Directory. */
#define FTW_D FTW_D
FTW_DNR, /* Unreadable directory. */
#define FTW_DNR FTW_DNR
FTW_NS, /* Unstatable file. */
#define FTW_NS FTW_NS
#ifdef __USE_XOPEN_EXTENDED
FTW_SL, /* Symbolic link. */
# define FTW_SL FTW_SL
/* These flags are only passed from the `nftw' function. */
FTW_DP, /* Directory, all subdirs have been visited. */
# define FTW_DP FTW_DP
FTW_SLN /* Symbolic link naming non-existing file. */
# define FTW_SLN FTW_SLN
#endif /* extended X/Open */
};
#ifdef __USE_XOPEN_EXTENDED
/* Flags for fourth argument of `nftw'. */
enum
{
FTW_PHYS = 1, /* Perform physical walk, ignore symlinks. */
# define FTW_PHYS FTW_PHYS
FTW_MOUNT = 2, /* Report only files on same file system as the
argument. */
# define FTW_MOUNT FTW_MOUNT
FTW_CHDIR = 4, /* Change to current directory while processing it. */
# define FTW_CHDIR FTW_CHDIR
FTW_DEPTH = 8 /* Report files in directory before directory itself.*/
# define FTW_DEPTH FTW_DEPTH
};
/* Structure used for fourth argument to callback function for `nftw'. */
struct FTW
{
int base;
int level;
};
#endif /* extended X/Open */
/* Convenient types for callback functions. */
typedef int (*__ftw_func_t) __P ((__const char *filename,
__const struct stat *status, int flag));
#ifdef __USE_XOPEN_EXTENDED
typedef int (*__nftw_func_t) __P ((__const char *filename,
__const struct stat *status, int flag,
struct FTW *));
#endif
/* Call a function on every element in a directory tree. */
extern int ftw __P ((__const char *__dir,
int (*__func) (__const char *__file,
__const struct stat *__status,
int __flag),
int __descriptors));
extern int ftw __P ((__const char *dir, __ftw_func_t func, int descriptors));
#ifdef __USE_XOPEN_EXTENDED
/* Call a function on every element in a directory tree. FLAG allows
to specify the behaviour more detailed. */
extern int nftw __P ((__const char *dir, __nftw_func_t func,
int descriptors, int flag));
#endif
__END_DECLS

View File

@ -25,9 +25,15 @@ subdir := login
headers := utmp.h utmpbits.h lastlog.h pty.h
routines := getutent getutent_r getutid getutline getutid_r getutline_r \
utmp_file utmp_db
utmp_file utmp_daemon utmpname
distribute := utmp-private.h
others = utmpd
install-sbin = utmpd
utmpd-routines := connection database error request xtmp
distribute := utmp-private.h utmpd/xtmp.h utmpd/utmpd.h utmpd/utmpd-private.h
vpath %.c utmpd
# Build the -lutil library with these extra functions.
extra-libs := libutil
@ -37,6 +43,8 @@ libutil-routines:= login login_tty logout logwtmp pty
include ../Rules
$(objpfx)utmpd: $(utmpd-routines:%=$(objpfx)%.o)
# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
# This ensures they will load libc.so for needed symbols if loaded by
# a statically-linked program that hasn't already loaded it.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>
and Paul Janzen <pcj@primenet.com>, 1996.
@ -19,49 +19,48 @@
Boston, MA 02111-1307, USA. */
#include <assert.h>
#include <db.h>
#include <fcntl.h>
#if _LIBC
#include <libc-lock.h>
#include <limits.h>
#else
#define __libc_lock_lock(lock) ((void) 0)
#define __libc_lock_unlock(lock) ((void) 0)
#define __libc_lock_define_initialized(CLASS,NAME)
#define weak_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utmp.h>
#include <sys/stat.h>
#include "utmp-private.h"
/* The various backends we have. */
static int __setutent_unknown (int reset);
static int __getutent_r_unknown (struct utmp *buffer, struct utmp **result);
static struct utmp *__pututline_unknown (const struct utmp *data);
static void __endutent_unknown (void);
static int setutent_unknown (int reset);
static int getutent_r_unknown (struct utmp *buffer, struct utmp **result);
static struct utmp *pututline_unknown (const struct utmp *data);
static void endutent_unknown (void);
/* We have three jump tables: unknown, db, or file. */
static struct utfuncs unknown_functions =
/* Initial Jump table. */
struct utfuncs __libc_utmp_unknown_functions =
{
__setutent_unknown,
__getutent_r_unknown,
setutent_unknown,
getutent_r_unknown,
NULL,
NULL,
__pututline_unknown,
__endutent_unknown,
pututline_unknown,
endutent_unknown,
NULL
};
/* Currently selected backend. */
struct utfuncs *__libc_utmp_jump_table = &unknown_functions;
/* The tables from the services. */
extern struct utfuncs __libc_utmp_db_functions;
extern struct utfuncs __libc_utmp_file_functions;
struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
/* We need to protect the opening of the file. */
__libc_lock_define_initialized (, __libc_utmp_lock)
void
__setutent (void)
{
@ -75,22 +74,31 @@ weak_alias (__setutent, setutent)
static int
__setutent_unknown (int reset)
setutent_unknown (int reset)
{
/* We have to test whether it is still not decided which backend to use. */
assert (__libc_utmp_jump_table == &unknown_functions);
assert (__libc_utmp_jump_table == &__libc_utmp_unknown_functions);
/* See whether utmp db file exists. */
if ((*__libc_utmp_db_functions.setutent) (reset))
__libc_utmp_jump_table = &__libc_utmp_db_functions;
/* See whether utmpd is running. */
if ((*__libc_utmp_daemon_functions.setutent) (reset))
__libc_utmp_jump_table = &__libc_utmp_daemon_functions;
else
{
/* Either the db file does not exist or we have other
problems. So use the normal file. */
/* Use the normal file, but if the current file is _PATH_UTMP or
_PATH_WTMP and the corresponding extended file (with an extra
'x' added to the pathname) exists, we use the extended file,
because the original file is in a different format. */
if (strcmp (__libc_utmp_file_name, _PATH_UTMP) == 0
&& __access (_PATH_UTMP "x", F_OK) == 0)
__utmpname (_PATH_UTMP "x");
else if (strcmp (__libc_utmp_file_name, _PATH_WTMP) == 0
&& __access (_PATH_WTMP "x", F_OK) == 0)
__utmpname (_PATH_WTMP "x");
(*__libc_utmp_file_functions.setutent) (reset);
__libc_utmp_jump_table = &__libc_utmp_file_functions;
}
return 0;
}
@ -108,7 +116,7 @@ weak_alias (__endutent, endutent)
static void
__endutent_unknown (void)
endutent_unknown (void)
{
/* Huh, how do we came here? Nothing to do. */
}
@ -131,10 +139,10 @@ weak_alias (__getutent_r, getutent_r)
static int
__getutent_r_unknown (struct utmp *buffer, struct utmp **result)
getutent_r_unknown (struct utmp *buffer, struct utmp **result)
{
/* It is not yet initialized. */
__setutent_unknown (0);
setutent_unknown (0);
return (*__libc_utmp_jump_table->getutent_r) (buffer, result);
}
@ -157,43 +165,10 @@ weak_alias (__pututline, pututline)
static struct utmp *
__pututline_unknown (const struct utmp *data)
pututline_unknown (const struct utmp *data)
{
/* It is not yet initialized. */
__setutent_unknown (0);
setutent_unknown (0);
return (*__libc_utmp_jump_table->pututline) (data);
}
int
__utmpname (const char *file)
{
int result = -1;
__libc_lock_lock (__libc_utmp_lock);
/* Close the old file. */
(*__libc_utmp_jump_table->endutent) ();
/* Store new names. */
if ((*__libc_utmp_file_functions.utmpname) (file) == 0
&& !(*__libc_utmp_db_functions.utmpname) (file) == 0)
{
/* Try to find out whether we are supposed to work with a db
file or not. Do this by looking for the extension ".db". */
const char *ext = strrchr (file, '.');
if (ext != NULL && strcmp (ext, ".db") == 0)
__libc_utmp_jump_table = &__libc_utmp_db_functions;
else
__libc_utmp_jump_table = &unknown_functions;
result = 0;
}
__libc_lock_unlock (__libc_utmp_lock);
return result;
}
weak_alias (__utmpname, utmpname)

View File

@ -23,7 +23,11 @@
#include <unistd.h>
#include <stdlib.h>
#include <utmp.h>
#ifndef _LIBC
#define __set_errno(val) errno = (val)
#endif
/* Return the result of ttyname in the buffer pointed to by TTY, which should
be of length BUF_LEN. If it is too long to fit in this buffer, a
sufficiently long buffer is allocated using malloc, and returned in TTY.
@ -135,20 +139,5 @@ login (const struct utmp *ut)
}
/* Update the WTMP file. Here we have to add a new entry. */
if (utmpname (_PATH_WTMP) != 0)
{
struct utmp *up;
/* Open the WTMP file. */
setutent ();
/* Position at end of file. */
while (! getutent_r (&utbuf, &up));
/* Write the new entry. */
pututline (&copy);
/* Close WTMP file. */
endutent ();
}
updwtmp (_PATH_WTMP, &copy);
}

View File

@ -17,53 +17,12 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
#include <sys/file.h>
#include <sys/stat.h>
void
updwtmp (const char *wtmp_file, const struct utmp *ut)
{
struct stat st;
size_t written;
int fd;
/* Open WTMP file. */
fd = __open (wtmp_file, O_WRONLY | O_APPEND);
if (fd < 0)
return;
/* Try to lock the file. */
if (__flock (fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS)
{
/* Oh, oh. The file is already locked. Wait a bit and try again. */
sleep (1);
/* This time we ignore the error. */
__flock (fd, LOCK_EX | LOCK_NB);
}
/* Remember original size of log file: */
if (__fstat (fd, &st) < 0)
goto done;
/* Write the entry. If we can't write all the bytes, reset the file
size back to the original size. That way, no partial entries
will remain. */
written = __write (fd, ut, sizeof (struct utmp));
if (written > 0 && written != sizeof (struct utmp))
ftruncate (fd, st.st_size);
done:
/* And unlock the file. */
__flock (fd, LOCK_UN);
/* Close WTMP file. */
__close (fd);
}
void
logwtmp (const char *line, const char *name, const char *host)
@ -90,5 +49,5 @@ logwtmp (const char *line, const char *name, const char *host)
time (&ut.ut_time);
#endif
updwtmp(_PATH_WTMP, &ut);
updwtmp (_PATH_WTMP, &ut);
}

View File

@ -1,5 +1,5 @@
/* pty.h - Functions for pseudo TTY handling.
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 1997 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
@ -22,6 +22,7 @@
#define _PTY_H 1
#include <features.h>
#include <ioctl-types.h>
#include <termios.h>

46
login/updwtmp.c Normal file
View File

@ -0,0 +1,46 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <unistd.h>
#include <utmp.h>
#include "utmp-private.h"
void
updwtmp (const char *wtmp_file, const struct utmp *utmp)
{
/* See whether utmpd is running. */
if ((*__libc_utmp_daemon_functions.updwtmp) (wtmp_file, utmp) < 0)
{
/* Use the normal file, but if the current file is _PATH_UTMP or
_PATH_WTMP and the corresponding extended file (with an extra
'x' added to the pathname) exists, we use the extended file,
because the original file is in a different format. */
if (strcmp (wtmp_file, _PATH_UTMP) == 0
&& __access (_PATH_UTMP "x", F_OK) == 0)
(*__libc_utmp_file_functions.updwtmp) (_PATH_UTMP "x", utmp);
else if (strcmp (wtmp_file, _PATH_WTMP) == 0
&& __access (_PATH_WTMP "x", F_OK) == 0)
(*__libc_utmp_file_functions.updwtmp) (_PATH_WTMP "x", utmp);
else
(*__libc_utmp_file_functions.updwtmp) (wtmp_file, utmp);
}
}

View File

@ -34,8 +34,21 @@ struct utfuncs
int (*getutline_r) (const struct utmp *, struct utmp *, struct utmp **);
struct utmp *(*pututline) (const struct utmp *);
void (*endutent) (void);
int (*utmpname) (const char *);
int (*updwtmp) (const char *, const struct utmp *);
};
/* The tables from the services. */
extern struct utfuncs __libc_utmp_file_functions;
extern struct utfuncs __libc_utmp_daemon_functions;
extern struct utfuncs __libc_utmp_unknown_functions;
/* Currently selected backend. */
extern struct utfuncs *__libc_utmp_jump_table;
/* Current file name. */
extern const char *__libc_utmp_file_name;
#endif /* utmp-private.h */

View File

@ -49,21 +49,22 @@ extern void login __P ((__const struct utmp *__entry));
/* Write the utmp entry to say the user on UT_LINE has logged out. */
extern int logout __P ((__const char *__ut_line));
/* Append the given entry to a wtmp file. */
extern void updwtmp __P ((__const char *__wtmp_file,
__const struct utmp *__entry));
/* Append to wtmp an entry for the current time and the given info. */
extern void logwtmp __P ((__const char *__ut_line, __const char *__ut_name,
__const char *__ut_host));
/* Append entry UTMP to the wtmp-like file WTMP_FILE. */
extern void updwtmp __P ((__const char *__wtmp_file,
__const struct utmp *__utmp));
/* Change name of the utmp file to be examined. */
extern int __utmpname __P ((__const char *__file));
extern int utmpname __P ((__const char *__file));
/* Read next entry from a utmp-like file. */
extern struct utmp *getutent __P ((void));
/* Rest the input stream to the beginning of the file. */
/* Reset the input stream to the beginning of the file. */
extern void __setutent __P ((void));
extern void setutent __P ((void));

454
login/utmp_daemon.c Normal file
View File

@ -0,0 +1,454 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <utmp.h>
#include "utmp-private.h"
#include "utmpd/utmpd.h"
#ifndef _LIBC
#define __set_errno(val) errno = (val)
#endif
/* Descriptor for the socket. */
static int daemon_sock = INT_MIN;
/* Functions defined here. */
static int setutent_daemon (int reset);
static int getutent_r_daemon (struct utmp *buffer, struct utmp **result);
static int getutid_r_daemon (const struct utmp *line, struct utmp *buffer,
struct utmp **result);
static int getutline_r_daemon (const struct utmp *id, struct utmp *buffer,
struct utmp **result);
static struct utmp *pututline_daemon (const struct utmp *utmp);
static void endutent_daemon (void);
static int updwtmp_daemon (const char *file, const struct utmp *utmp);
/* Jump table for daemon functions. */
struct utfuncs __libc_utmp_daemon_functions =
{
setutent_daemon,
getutent_r_daemon,
getutid_r_daemon,
getutline_r_daemon,
pututline_daemon,
endutent_daemon,
updwtmp_daemon
};
static int do_setutent (int sock);
static int do_getutent (int sock, struct utmp *buffer);
static int do_endutent (int sock);
static int do_getutline (int sock, const struct utmp *line,
struct utmp *buffer);
static int do_getutid (int sock, const struct utmp *id,
struct utmp *buffer);
static int do_pututline (int sock, const struct utmp *utmp);
static int do_updwtmp (int sock, const char *file,
const struct utmp *utmp);
static int open_socket (const char *name);
static int send_request (int sock, const request_header *request,
reply_header *reply);
static int
setutent_daemon (int reset)
{
if (daemon_sock == INT_MIN)
{
daemon_sock = open_socket (_PATH_UTMPD_RW);
if (daemon_sock < 0)
{
/* Hhm, read-write access did not work. Try read-only. */
daemon_sock = open_socket (_PATH_UTMPD_RO);
if (daemon_sock < 0)
return 0;
}
/* Send request to the daemon. */
if (do_setutent (daemon_sock) < 0)
return 0;
}
else if (reset)
{
/* Send request to the daemon. */
if (do_setutent (daemon_sock) < 0)
return 0;
}
return 1;
}
static void
endutent_daemon (void)
{
if (daemon_sock >= 0)
{
/* Send request to the daemon. */
do_endutent (daemon_sock);
close (daemon_sock);
}
daemon_sock = INT_MIN;
}
static int
getutent_r_daemon (struct utmp *buffer, struct utmp **result)
{
/* Open connection if not already done. */
if (daemon_sock == INT_MIN)
setutent_daemon (1);
if (daemon_sock < 0)
{
/* Not available. */
*result = NULL;
return -1;
}
/* Send request to the daemon. */
if (do_getutent (daemon_sock, buffer) < 0)
{
*result = NULL;
return -1;;
}
*result = buffer;
return 0;
}
static int
getutline_r_daemon (const struct utmp *line, struct utmp *buffer,
struct utmp **result)
{
if (daemon_sock < 0)
{
*result = NULL;
return -1;
}
/* Send request to the daemon. */
if (do_getutline (daemon_sock, line, buffer) < 0)
{
*result = NULL;
return -1;;
}
*result = buffer;
return 0;
}
static int
getutid_r_daemon (const struct utmp *id, struct utmp *buffer,
struct utmp **result)
{
if (daemon_sock < 0)
{
*result = NULL;
return -1;
}
/* Send request to the daemon. */
if (do_getutid (daemon_sock, id, buffer) < 0)
{
*result = NULL;
return -1;
}
*result = buffer;
return 0;
}
static struct utmp *
pututline_daemon (const struct utmp *utmp)
{
if (daemon_sock == INT_MIN)
/* The connection is closed. Open it again. */
setutent_daemon (0);
if (daemon_sock < 0)
/* Something went wrong. */
return NULL;
/* Send request to the daemon. */
if (do_pututline (daemon_sock, utmp) < 0)
return NULL;
return (struct utmp *)utmp;
}
static int
updwtmp_daemon (const char *file, const struct utmp *utmp)
{
int sock;
/* Only try to open for both reading and writing. */
sock = open_socket (_PATH_UTMPD_RW);
if (sock < 0)
return -1;
/* Send request to the daemon. */
if (do_updwtmp (sock, file, utmp) < 0)
return -1;
close (sock);
return 0;
}
static int
do_setutent (int sock)
{
setutent_request request;
setutent_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (setutent_request);
request.header.type = UTMPD_REQ_SETUTENT;
strncpy (request.file, __libc_utmp_file_name, sizeof request.file);
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (setutent_reply);
reply.header.type = UTMPD_REQ_SETUTENT;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
return reply.result;
}
static int
do_getutent (int sock, struct utmp *buffer)
{
getutent_request request;
getutent_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (getutent_request);
request.header.type = UTMPD_REQ_GETUTENT;
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (getutent_reply);
reply.header.type = UTMPD_REQ_GETUTENT;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
else
memcpy (buffer, &reply.entry, sizeof (struct utmp));
return reply.result;
}
static int
do_endutent (int sock)
{
endutent_request request;
endutent_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (endutent_request);
request.header.type = UTMPD_REQ_ENDUTENT;
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (endutent_reply);
reply.header.type = UTMPD_REQ_ENDUTENT;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
return reply.result;
}
static int
do_getutline (int sock, const struct utmp *line, struct utmp *buffer)
{
getutline_request request;
getutline_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (getutline_request);
request.header.type = UTMPD_REQ_GETUTLINE;
memcpy (&request.line, line, sizeof (struct utmp));
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (getutline_reply);
reply.header.type = UTMPD_REQ_GETUTLINE;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
else
memcpy (buffer, &reply.entry, sizeof (struct utmp));
return reply.result;
}
static int
do_getutid (int sock, const struct utmp *id, struct utmp *buffer)
{
getutid_request request;
getutid_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (getutid_request);
request.header.type = UTMPD_REQ_GETUTID;
memcpy (&request.id, id, sizeof (struct utmp));
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (getutid_reply);
reply.header.type = UTMPD_REQ_GETUTID;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
else
memcpy (buffer, &reply.entry, sizeof (struct utmp));
return reply.result;
}
static int
do_pututline (int sock, const struct utmp *utmp)
{
pututline_request request;
pututline_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (pututline_request);
request.header.type = UTMPD_REQ_PUTUTLINE;
memcpy (&request.utmp, utmp, sizeof (struct utmp));
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (pututline_reply);
reply.header.type = UTMPD_REQ_PUTUTLINE;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
return reply.result;
}
static int
do_updwtmp (int sock, const char *file, const struct utmp *utmp)
{
updwtmp_request request;
updwtmp_reply reply;
request.header.version = UTMPD_VERSION;
request.header.size = sizeof (updwtmp_request);
request.header.type = UTMPD_REQ_UPDWTMP;
strncpy (request.file, file, sizeof request.file);
memcpy (&request.utmp, utmp, sizeof (struct utmp));
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (updwtmp_reply);
reply.header.type = UTMPD_REQ_UPDWTMP;
if (send_request (sock, &request.header, &reply.header) < 0)
return -1;
if (reply.result < 0)
__set_errno (reply.errnum);
return reply.result;
}
/* Create a socket connected to NAME. */
static int
open_socket (const char *name)
{
struct sockaddr_un addr;
int sock;
sock = socket (PF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
return -1;
addr.sun_family = AF_UNIX;
strcpy (addr.sun_path, name);
if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0)
{
close (sock);
return -1;
}
return sock;
}
/* Send REQUEST to SOCK, and wait for reply. Returns 0 if successful,
storing the reply in REPLY, and -1 if not. */
static int
send_request (int sock, const request_header *request,
reply_header *reply)
{
reply_header header;
ssize_t nbytes;
nbytes = write (sock, request, request->size);
if (nbytes != (ssize_t) request->size)
return -1;
nbytes = read (sock, &header, sizeof (reply_header));
if (nbytes != sizeof (reply_header))
return -1;
if (reply->version != header.version
|| reply->size != header.size
|| reply->type != header.type)
return -1;
nbytes = read (sock, reply + 1, reply->size - sizeof (reply_header));
if (nbytes != (ssize_t) (reply->size - sizeof (reply_header)))
return -1;
return 0;
}

View File

@ -1,104 +0,0 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>
and Paul Janzen <pcj@primenet.com>, 1996.
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 <assert.h>
#include <db.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utmp.h>
#include <sys/stat.h>
#include "utmp-private.h"
/* This is the default name. */
static const char default_file_name[] = _PATH_UTMP_DB;
/* Current file name. */
static const char *file_name = (const char *) default_file_name;
/* Descriptor for database. */
#if 0
/* XXX One day this will become meaningful again. */
static DB *db_fd;
static char last_date[16];
#endif
/* Our local functions. */
static int setutent_db (int reset);
static void endutent_db (void);
static int utmpname_db (const char *name);
/* The jump table for the local functions. */
struct utfuncs __libc_utmp_db_functions =
{
setutent_db,
NULL,
NULL,
NULL,
NULL,
endutent_db,
utmpname_db
};
static int
setutent_db (int reset)
{
return 0;
}
static void
endutent_db (void)
{
}
static int
utmpname_db (const char *name)
{
if (strcmp (name, file_name) != 0)
{
if (strcmp (name, default_file_name) == 0)
{
if (file_name != default_file_name)
free ((char *) file_name);
file_name = default_file_name;
}
else
{
char *new_name = __strdup (name);
if (new_name == NULL)
/* Out of memory. */
return -1;
if (file_name != default_file_name)
free ((char *) file_name);
file_name = new_name;
}
}
return 0;
}

View File

@ -31,12 +31,11 @@
#include "utmp-private.h"
#ifndef _LIBC
#define _(msg) (msg)
#define __set_errno(val) errno = (val)
#endif
/* This is the default name. */
static const char default_file_name[] = _PATH_UTMP;
/* Current file name. */
static const char *file_name = (const char *) default_file_name;
/* Descriptor for the file and position. */
static int file_fd = INT_MIN;
@ -44,6 +43,7 @@ static off_t file_offset;
static struct utmp last_entry;
/* Functions defined here. */
static int setutent_file (int reset);
static int getutent_r_file (struct utmp *buffer, struct utmp **result);
@ -53,8 +53,7 @@ static int getutline_r_file (const struct utmp *key, struct utmp *buffer,
struct utmp **result);
static struct utmp *pututline_file (const struct utmp *data);
static void endutent_file (void);
static int utmpname_file (const char *name);
static int updwtmp_file (const char *file, const struct utmp *utmp);
/* Jump table for file functions. */
struct utfuncs __libc_utmp_file_functions =
@ -65,7 +64,7 @@ struct utfuncs __libc_utmp_file_functions =
getutline_r_file,
pututline_file,
endutent_file,
utmpname_file
updwtmp_file
};
@ -74,11 +73,11 @@ setutent_file (int reset)
{
if (file_fd == INT_MIN)
{
file_fd = open (file_name, O_RDWR);
file_fd = open (__libc_utmp_file_name, O_RDWR);
if (file_fd == -1)
{
/* Hhm, read-write access did not work. Try read-only. */
file_fd = open (file_name, O_RDONLY);
file_fd = open (__libc_utmp_file_name, O_RDONLY);
if (file_fd == -1)
{
perror (_("while opening UTMP file"));
@ -231,9 +230,7 @@ proc_utmp_eq (const struct utmp *entry, const struct utmp *match)
&&
#endif
#if _HAVE_UT_ID - 0
(entry->ut_id[0] && match->ut_id[0]
? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
: strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0)
strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
#else
strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0
#endif
@ -404,29 +401,50 @@ pututline_file (const struct utmp *data)
static int
utmpname_file (const char *name)
updwtmp_file (const char *file, const struct utmp *utmp)
{
if (strcmp (name, file_name) != 0)
int result = -1;
struct stat st;
ssize_t nbytes;
int fd;
/* Open WTMP file. */
fd = __open (file, O_WRONLY | O_APPEND);
if (fd < 0)
return -1;
/* Try to lock the file. */
if (__flock (fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS)
{
if (strcmp (name, default_file_name) == 0)
{
if (file_name != default_file_name)
free ((char *) file_name);
/* Oh, oh. The file is already locked. Wait a bit and try again. */
sleep (1);
file_name = default_file_name;
}
else
{
char *new_name = __strdup (name);
if (new_name == NULL)
/* Out of memory. */
return -1;
if (file_name != default_file_name)
free ((char *) file_name);
file_name = new_name;
}
/* This time we ignore the error. */
__flock (fd, LOCK_EX | LOCK_NB);
}
return 0;
/* Remember original size of log file. */
if (__fstat (fd, &st) < 0)
goto fail;
/* Write the entry. If we can't write all the bytes, reset the file
size back to the original size. That way, no partial entries
will remain. */
nbytes = __write (fd, utmp, sizeof (struct utmp));
if (nbytes != sizeof (struct utmp))
{
ftruncate (fd, st.st_size);
goto fail;
}
result = 0;
fail:
/* And unlock the file. */
__flock (fd, LOCK_UN);
/* Close WTMP file. */
__close (fd);
return result;
}

180
login/utmpd/connection.c Normal file
View File

@ -0,0 +1,180 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "utmpd-private.h"
/* Prototypes for the local functions. */
static client_connection *alloc_connection (void);
static void free_connection (client_connection *connection);
static int set_nonblock_flag (int desc, int value);
/* The head of the connection list. */
static client_connection *connection_list = NULL;
/* Accept connection on SOCK, with access permissions given by ACCESS.
Returns a pointer to a newly allocated client_connection if
successful, NULL if not. */
client_connection *
accept_connection (int sock, int access)
{
client_connection *connection;
connection = alloc_connection ();
if (connection == NULL)
return NULL;
connection->sock = accept (sock, NULL, NULL);
connection->access = access;
if (connection->sock < 0)
{
free_connection (connection);
return NULL;
}
if (set_nonblock_flag (connection->sock, 1) < 0)
{
close_connection (connection);
return NULL;
}
return connection;
}
/* Close CONNECTION. */
void
close_connection (client_connection *connection)
{
close (connection->sock);
free_connection (connection);
}
/* Return the connection for SOCK. */
client_connection *
find_connection (int sock)
{
client_connection *connection;
for (connection = connection_list; connection;
connection = connection->next)
{
if (connection->sock == sock)
return connection;
}
return NULL;
}
static client_connection *
alloc_connection (void)
{
client_connection *connection;
size_t read_bufsize = 1024;
size_t write_bufsize = 1024;
connection = (client_connection *)malloc (sizeof (client_connection));
if (connection == NULL)
return NULL;
memset (connection, 0, sizeof (client_connection));
/* Allocate read buffer. */
connection->read_base = malloc (read_bufsize);
connection->read_ptr = connection->read_base;
connection->read_end = connection->read_base + read_bufsize;
if (connection->read_base == NULL)
{
free (connection);
return NULL;
}
/* Allocate write buffer. */
connection->write_base = malloc (write_bufsize);
connection->write_ptr = connection->write_base;
connection->write_end = connection->write_base + write_bufsize;
if (connection->write_base == NULL)
{
free (connection->read_base);
free (connection);
return NULL;
}
/* Link connection. */
connection->next = connection_list;
connection_list = connection;
if (connection->next)
connection->next->prev = connection;
return connection;
}
static void
free_connection (client_connection *connection)
{
/* Unlink connection. */
if (connection->next)
connection->next->prev = connection->prev;
if (connection->prev)
connection->prev->next = connection->next;
/* Take care of the head of the list. */
if (connection == connection_list)
connection_list = connection->next;
/* Free buffers. */
if (connection->read_base)
free (connection->read_base);
if (connection->write_base)
free (connection->write_base);
free (connection);
}
/* Set the `O_NONBLOCK' flag of DESC if VALUE is nonzero,
or clear the flag if VALUE is 0.
Return 0 on success, or -1 on error with `errno' set. */
static int
set_nonblock_flag (int desc, int value)
{
int oldflags = fcntl (desc, F_GETFL, 0);
/* If reading the flags failed, return error indication now. */
if (oldflags == -1)
return -1;
/* Set just the flag we want to set. */
if (value != 0)
oldflags |= O_NONBLOCK;
else
oldflags &= ~O_NONBLOCK;
/* Store modified flag word in the descriptor. */
return fcntl (desc, F_SETFL, oldflags);
}

516
login/utmpd/database.c Normal file
View File

@ -0,0 +1,516 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
#include "utmpd-private.h"
#include "xtmp.h"
/* Prototypes for the local functions. */
static int initialize_database (utmp_database *database);
static int store_state_entry (utmp_database *database, int old_position,
const struct utmp *old_entry);
static int store_process_entry (utmp_database *database, int old_position,
const struct utmp *old_entry);
static int replace_entry (utmp_database *database, int old_position,
int new_position, const struct utmp *entry);
static int store_entry (utmp_database *database, int position,
const struct utmp *entry);
static int proc_utmp_eq (const struct utmp *entry, const struct utmp *match);
static int get_mtime (const char *file, time_t *timer);
/* Open the database specified by FILE and merge it with the
contents of the old format file specified by OLD_FILE. Returns a
pointer to a newly allocated structure describing the database, or
NULL on error. */
utmp_database *
open_database (const char *file, const char *old_file)
{
utmp_database *database;
/* Allocate memory. */
database = (utmp_database *) malloc (sizeof (utmp_database));
if (database == NULL)
return NULL;
memset (database, 0, sizeof (utmp_database));
/* Open database. */
database->fd = open (file, O_RDWR);
if (database->fd < 0)
goto fail;
database->old_fd = open (old_file, O_RDWR);
if (database->old_fd < 0)
goto fail;
if ((file && !(database->file = strdup (file)))
|| (old_file && !(database->old_file = strdup (old_file))))
goto fail;
if (initialize_database (database) < 0
|| synchronize_database (database) < 0)
goto fail;
return database;
fail:
close_database (database);
return NULL;
}
/* Synchronize DATABASE. */
int
synchronize_database (utmp_database *database)
{
assert (database);
/* Check if there is a file in the old format, that we have to
synchronize with. */
if (database->old_file)
{
time_t curtime;
time_t mtime;
curtime = time (NULL);
if (get_mtime (database->old_file, &mtime) < 0)
return -1;
if (mtime >= database->mtime)
{
int position = 0;
struct utmp entry;
struct utmp old_entry;
while (1)
{
if (read_old_entry (database, position, &old_entry) < 0)
break;
if (read_entry (database, position, &entry) < 0
|| !compare_entry (&old_entry, &entry))
{
if (write_entry (database, position, &old_entry) < 0)
return -1;
}
position++;
}
database->mtime = curtime;
}
}
return 0;
}
/* Close DATABASE. */
void
close_database (utmp_database *database)
{
assert (database);
if (database->fd >= 0)
close (database->fd);
if (database->old_fd >= 0)
close (database->old_fd);
/* Free allocated memory. */
if (database->file)
free (database->file);
if (database->old_file)
free (database->old_file);
free (database);
}
/* Read the entry at POSITION in DATABASE and store the result in
ENTRY. Returns 0 if successful, -1 if not. */
int
read_entry (utmp_database *database, int position, struct utmp *entry)
{
ssize_t nbytes;
off_t offset;
offset = position * sizeof (struct utmp);
if (lseek (database->fd, offset, SEEK_SET) < 0)
return -1;
nbytes = read (database->fd, entry, sizeof (struct utmp));
if (nbytes != sizeof (struct utmp))
return -1;
return 0;
}
/* Write ENTRY at POSITION in DATABASE. Returns 0 if successful, -1
on error. */
int
write_entry (utmp_database *database, int position,
const struct utmp *entry)
{
int result = -1;
struct flock fl;
ssize_t nbytes;
off_t offset;
/* Try to lock the file. */
memset (&fl, 0, sizeof (struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fcntl (database->fd, F_SETLKW, &fl);
offset = position * sizeof (struct utmp);
if (lseek (database->fd, offset, SEEK_SET) < 0)
goto fail;
nbytes = write (database->fd, entry, sizeof (struct utmp));
if (nbytes != sizeof (struct utmp))
{
ftruncate (database->fd, offset);
goto fail;
}
result = 0;
fail:
/* And unlock the file. */
fl.l_type = F_UNLCK;
fcntl (database->fd, F_SETLKW, &fl);
return result;
}
/* Append ENTRY to DATABASE. Returns the position of the appended
entry if successful, or -1 on error. */
int
append_entry (utmp_database *database, const struct utmp *entry)
{
int result = -1;
struct flock fl;
ssize_t nbytes;
off_t offset;
/* Try to lock the file. */
memset (&fl, 0, sizeof (struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fcntl (database->fd, F_SETLKW, &fl);
offset = lseek (database->fd, 0, SEEK_END);
if (offset % sizeof (struct utmp) != 0)
{
offset -= offset % sizeof (struct utmp);
ftruncate (database->fd, offset);
if (lseek (database->fd, 0, SEEK_END) < 0)
goto fail;
}
nbytes = write (database->fd, entry, sizeof (struct utmp));
if (nbytes != sizeof (struct utmp))
{
ftruncate (database->fd, offset);
goto fail;
}
result = offset / sizeof (struct utmp);
fail:
/* And unlock the file. */
fl.l_type = F_UNLCK;
fcntl (database->fd, F_SETLKW, &fl);
return result;
}
int
read_old_entry (utmp_database *database, int position,
struct utmp *entry)
{
struct xtmp old_entry;
ssize_t nbytes;
off_t offset;
offset = position * sizeof (struct xtmp);
if (lseek (database->old_fd, offset, SEEK_SET) < 0)
return -1;
nbytes = read (database->old_fd, &old_entry, sizeof (struct xtmp));
if (nbytes != sizeof (struct xtmp))
return -1;
xtmp_to_utmp (&old_entry, entry);
return 0;
}
int
write_old_entry (utmp_database *database, int position,
const struct utmp *entry)
{
struct xtmp old_entry;
ssize_t nbytes;
off_t offset;
utmp_to_xtmp (entry, &old_entry);
offset = position * sizeof (struct xtmp);
if (lseek (database->old_fd, offset, SEEK_SET) < 0)
return -1;
nbytes = write (database->old_fd, &old_entry, sizeof (struct xtmp));
if (nbytes != sizeof (struct xtmp))
return -1;
return 0;
}
/* Initialize DATABASE. */
static int
initialize_database (utmp_database *database)
{
struct utmp entry;
int position = 0;
assert (database);
/* Check if there is a file in the old format to read. */
if (database->old_file)
{
while (1)
{
if (read_old_entry (database, position, &entry) < 0)
break;
#if _HAVE_UT_TYPE - 0
/* If the login type is one of RUN_LVL, BOOT_TIME, OLD_TIME or
NEW_TIME, search for an entry of the same type in the
database, and replace it if the entry in the file is newer. */
if (entry.ut_type == RUN_LVL || entry.ut_type == BOOT_TIME
|| entry.ut_type == OLD_TIME || entry.ut_type == NEW_TIME)
{
if (store_state_entry (database, position, &entry) < 0)
return -1;
}
else
#endif
{
if (store_process_entry (database, position, &entry) < 0)
return -1;
}
/* Update position. */
position++;
}
while (1)
{
if (read_entry (database, position, &entry) < 0)
break;
if (write_old_entry (database, position, &entry) < 0)
return -1;
/* Update position. */
position++;
}
}
return 0;
}
static int
store_state_entry (utmp_database *database, int old_position,
const struct utmp *old_entry)
{
struct utmp new_entry;
int new_position = 0;
int found = 0;
assert (old_entry->ut_type == RUN_LVL
|| old_entry->ut_type == BOOT_TIME
|| old_entry->ut_type == OLD_TIME
|| old_entry->ut_type == NEW_TIME);
while (!found)
{
/* Read the next entry. */
if (read_entry (database, new_position, &new_entry) < 0)
break;
if (old_entry->ut_type == new_entry.ut_type)
{
found = 1;
continue;
}
/* Update position. */
new_position++;
}
if (found)
{
const struct utmp *entry;
if (old_entry->ut_time > new_entry.ut_time)
entry = old_entry;
else
entry = &new_entry;
return replace_entry (database, old_position, new_position, entry);
}
return store_entry (database, old_position, old_entry);
}
static int
store_process_entry (utmp_database *database, int old_position,
const struct utmp *old_entry)
{
struct utmp new_entry;
int new_position = 0;
int found = 0;
while (!found)
{
/* Read the next entry. */
if (read_entry (database, new_position, &new_entry) < 0)
break;
if (proc_utmp_eq (old_entry, &new_entry))
{
found = 1;
continue;
}
/* Update position. */
new_position++;
}
if (found)
{
const struct utmp *entry;
if (old_entry->ut_time > new_entry.ut_time)
entry = old_entry;
else
entry = &new_entry;
return replace_entry (database, old_position, new_position, entry);
}
return store_entry (database, old_position, old_entry);
}
static int
replace_entry (utmp_database *database, int old_position, int new_position,
const struct utmp *entry)
{
struct utmp tmp;
if (read_entry (database, old_position, &tmp) < 0
|| write_entry (database, old_position, entry) < 0
|| write_entry (database, new_position, &tmp) < 0)
return -1;
return 0;
}
static int
store_entry (utmp_database *database, int position,
const struct utmp *entry)
{
struct utmp tmp;
if (read_entry (database, position, &tmp) < 0)
return write_entry (database, position, entry);
if (write_entry (database, position, entry) < 0
|| append_entry (database, &tmp) < 0)
return -1;
return 0;
}
/* This function is identical to the one in login/utmp_file.c. */
static int
proc_utmp_eq (const struct utmp *entry, const struct utmp *match)
{
return
(
#if _HAVE_UT_TYPE - 0
(entry->ut_type == INIT_PROCESS
|| entry->ut_type == LOGIN_PROCESS
|| entry->ut_type == USER_PROCESS
|| entry->ut_type == DEAD_PROCESS)
&&
(match->ut_type == INIT_PROCESS
|| match->ut_type == LOGIN_PROCESS
|| match->ut_type == USER_PROCESS
|| match->ut_type == DEAD_PROCESS)
&&
#endif
#if _HAVE_UT_ID - 0
strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
#else
strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0
#endif
);
}
/* Get modification time of FILE and put it in TIMER. returns 0 if
successful, -1 if not. */
static int
get_mtime (const char *file, time_t *timer)
{
struct stat st;
if (stat (file, &st) < 0)
return -1;
*timer = st.st_mtime;
return 0;
}

104
login/utmpd/error.c Normal file
View File

@ -0,0 +1,104 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include "utmpd-private.h"
/* This variable indicates if we have forked. If set, we log messages
via the system logger. Otherwise we simply print the program name
and the message to standard error. */
int forked = 0;
/* Log error message MESSAGE, which is a printf-style format string
with optional args.
If ERRNUM is nonzero, also log its corresponding system error message.
Exit with status STATUS if it is nonzero. */
void
error (int status, int errnum, const char *message, ...)
{
va_list ap;
char *buffer = NULL;
va_start (ap, message);
vasprintf (&buffer, message, ap);
va_end (ap);
if (forked)
{
if (errnum == 0)
syslog (LOG_ERR, "%s", buffer);
else
syslog (LOG_ERR, "%s: %s", buffer, strerror (errnum));
}
else
{
if (errnum == 0)
fprintf (stderr, "%s: %s\n", program_invocation_name, buffer);
else
fprintf (stderr, "%s: %s: %s\n", program_invocation_name, buffer,
strerror (errnum));
}
if (buffer)
free (buffer);
if (status)
exit (status);
}
/* Log warning message MESSAGE, which is a printf-style format string
with optional args.
If ERRNUM is nonzero, also log its corresponding system error message. */
void
warning (int errnum, const char *message, ...)
{
va_list ap;
char *buffer = NULL;
va_start (ap, message);
vasprintf (&buffer, message, ap);
va_end (ap);
if (forked)
{
if (errnum == 0)
syslog (LOG_WARNING, "%s", buffer);
else
syslog (LOG_WARNING, "%s: %s", buffer, strerror (errnum));
}
else
{
if (errnum == 0)
printf ("%s: %s\n", program_invocation_name, buffer);
else
printf ("%s: %s: %s\n", program_invocation_name, buffer,
strerror (errnum));
}
if (buffer)
free (buffer);
}

650
login/utmpd/request.c Normal file
View File

@ -0,0 +1,650 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <utmp.h>
#include "utmpd.h"
#include "utmpd-private.h"
/* Prototypes for the local functions. */
static int process_request (client_connection *connection);
static int send_reply (client_connection *connect, const reply_header *reply);
static int do_setutent (client_connection *connection);
static int do_getutent (client_connection *connection);
static int do_endutent (client_connection *connection);
static int do_getutline (client_connection *connection);
static int do_getutid (client_connection *connection);
static int do_pututline (client_connection *connection);
static int do_updwtmp (client_connection *connection);
static int proc_utmp_eq (const struct utmp *entry, const struct utmp *match);
static int internal_getut_r (client_connection *connection,
const struct utmp *id, struct utmp *buffer);
/* Read data from the client on CONNECTION. */
int
read_data (client_connection *connection)
{
ssize_t nbytes;
assert (connection);
assert ((connection->read_end - connection->read_ptr) > 0);
/* Read data. */
nbytes = read (connection->sock, connection->read_ptr,
connection->read_end - connection->read_ptr);
if (nbytes > 0)
{
size_t total_bytes;
/* Update read pointer. */
connection->read_ptr += nbytes;
/* Check if we have a complete request header. */
total_bytes = connection->read_ptr - connection->read_base;
if (total_bytes >= sizeof (request_header))
{
request_header *header;
/* Check if we have a complete request. */
header = (request_header *)connection->read_base;
if (total_bytes >= header->size)
{
/* Process the request. */
if (process_request (connection) < 0)
return -1;
/* Adjust read pointer, and flush buffer. */
connection->read_ptr -= header->size;
memmove (connection->read_base,
connection->read_base + header->size,
connection->read_ptr - connection->read_base);
}
}
return 0;
}
if (nbytes < 0)
error (0, errno, "cannot read from client");
return -1;
}
/* Write data to the client on CONNECTION. */
int
write_data (client_connection *connection)
{
ssize_t nbytes;
assert (connection);
assert ((connection->write_ptr - connection->write_base) > 0);
/* Write data. */
nbytes = write (connection->sock, connection->write_base,
connection->write_ptr - connection->write_base);
if (nbytes > 0)
{
/* Adjust write pointer and flush buffer. */
connection->write_ptr -= nbytes;
memmove (connection->write_base, connection->write_base + nbytes,
connection->write_ptr - connection->write_base);
return 0;
}
if (nbytes < 0)
error (0, errno, "cannot write to client");
return -1;
}
/* Process the request received on CONNECTION. Returns 0 if
successful, -1 if not. */
static int
process_request (client_connection *connection)
{
request_header *header;
assert (connection);
assert (connection->read_base);
header = (request_header *)connection->read_base;
if (header->version != UTMPD_VERSION)
{
warning (EINVAL, "invalid protocol version");
return -1;
}
switch (header->type)
{
case UTMPD_REQ_SETUTENT: return do_setutent (connection);
case UTMPD_REQ_GETUTENT: return do_getutent (connection);
case UTMPD_REQ_ENDUTENT: return do_endutent (connection);
case UTMPD_REQ_GETUTLINE: return do_getutline (connection);
case UTMPD_REQ_GETUTID: return do_getutid (connection);
case UTMPD_REQ_PUTUTLINE: return do_pututline (connection);
case UTMPD_REQ_UPDWTMP: return do_updwtmp (connection);
default:
warning (EINVAL, "invalid request type");
return -1;
}
}
/* Send the reply specified by HEADER to the client on CONNECTION.
Returns 0 if successful, -1 if not. */
static int
send_reply (client_connection *connection, const reply_header *reply)
{
/* Check if the reply fits in the buffer. */
if ((size_t) (connection->write_end - connection->write_ptr) < reply->size)
{
error (0, 0, "buffer overflow");
return -1;
}
/* Copy reply to buffer, and adjust write pointer. */
memcpy (connection->write_ptr, reply, reply->size);
connection->write_ptr += reply->size;
return 0;
}
static int
do_setutent (client_connection *connection)
{
setutent_request *request;
setutent_reply reply;
request = (setutent_request *)connection->read_base;
if (request->header.size != sizeof (setutent_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Initialize reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (setutent_reply);
reply.header.type = UTMPD_REQ_SETUTENT;
/* Select database. */
if (!strncmp (request->file, _PATH_UTMP, sizeof request->file))
connection->database = utmp_db;
else
{
errno = EINVAL;
goto return_error;
}
/* Initialize position pointer. */
connection->position = 0;
#if _HAVE_UT_TYPE - 0
/* Make sure the entry won't match. */
connection->last_entry.ut_type = -1;
#endif
reply.errnum = 0;
reply.result = 0;
return send_reply (connection, &reply.header);
return_error:
reply.errnum = errno;
reply.result = -1;
return send_reply (connection, &reply.header);
}
static int
do_getutent (client_connection *connection)
{
getutent_request *request;
getutent_reply reply;
request = (getutent_request *)connection->read_base;
if (request->header.size != sizeof (getutent_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Initialize reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (getutent_reply);
reply.header.type = UTMPD_REQ_GETUTENT;
if (connection->database == NULL || connection->position == -1)
{
errno = ESRCH;
goto return_error;
}
/* Make sure we're in synch with the ordinary file. */
if (synchronize_database (connection->database) < 0)
{
errno = ESRCH;
goto return_error;
}
/* Read the next entry from the database. */
if (read_entry (connection->database, connection->position,
&connection->last_entry) < 0)
{
connection->position = -1;
errno = ESRCH;
goto return_error;
}
/* Update position pointer. */
connection->position++;
memcpy (&reply.entry, &connection->last_entry, sizeof (struct utmp));
reply.errnum = 0;
reply.result = 0;
return send_reply (connection, (reply_header *)&reply);
return_error:
memset (&reply.entry, 0, sizeof (struct utmp));
reply.errnum = errno;
reply.result = -1;
return send_reply (connection, &reply.header);
}
static int
do_endutent (client_connection *connection)
{
endutent_request *request;
endutent_reply reply;
request = (endutent_request *)connection->read_base;
if (request->header.size != sizeof (endutent_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Deselect database. */
connection->database = NULL;
/* Formulate reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (endutent_reply);
reply.header.type = UTMPD_REQ_ENDUTENT;
reply.errnum = 0;
reply.result = 0;
return send_reply (connection, &reply.header);
}
static int
do_getutline (client_connection *connection)
{
getutline_request *request;
getutline_reply reply;
request = (getutline_request *)connection->read_base;
if (request->header.size != sizeof (getutline_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Initialize reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (getutline_reply);
reply.header.type = UTMPD_REQ_GETUTLINE;
if (connection->database == NULL || connection->position == -1)
{
errno = ESRCH;
goto return_error;
}
/* Make sure we're in synch with the ordinary file. */
if (synchronize_database (connection->database) < 0)
{
errno = ESRCH;
goto return_error;
}
while (1)
{
/* Read the next entry. */
if (read_entry (connection->database, connection->position,
&connection->last_entry) < 0)
{
connection->position = -1;
errno = ESRCH;
goto return_error;
}
connection->position++;
/* Stop if we found a user or login entry. */
if (
#if _HAVE_UT_TYPE - 0
(connection->last_entry.ut_type == USER_PROCESS
|| connection->last_entry.ut_type == LOGIN_PROCESS)
&&
#endif
!strncmp (request->line.ut_line, connection->last_entry.ut_line,
sizeof request->line.ut_line))
break;
}
memcpy (&reply.entry, &connection->last_entry, sizeof (struct utmp));
reply.errnum = 0;
reply.result = 0;
return send_reply (connection, &reply.header);
return_error:
memset (&reply.entry, 0, sizeof (struct utmp));
reply.errnum = errno;
reply.result = -1;
return send_reply (connection, &reply.header);
}
static int
do_getutid (client_connection *connection)
{
getutid_request *request;
getutid_reply reply;
request = (getutid_request *)connection->read_base;
if (request->header.size != sizeof (getutid_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Initialize reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (getutid_reply);
reply.header.type = UTMPD_REQ_GETUTID;
if (connection->database == NULL || connection->position == -1)
{
errno = ESRCH;
goto return_error;
}
/* Make sure we're in synch with the ordinary file. */
if (synchronize_database (connection->database) < 0)
{
errno = ESRCH;
goto return_error;
}
if (internal_getut_r (connection, &request->id,
&connection->last_entry) < 0)
{
errno = ESRCH;
goto return_error;
}
reply.errnum = 0;
reply.result = 0;
memcpy (&reply.entry, &connection->last_entry, sizeof (struct utmp));
return send_reply (connection, &reply.header);
return_error:
memset (&reply.entry, 0, sizeof (struct utmp));
reply.errnum = errno;
reply.result = -1;
return send_reply (connection, &reply.header);
}
static int
do_pututline (client_connection *connection)
{
pututline_request *request;
pututline_reply reply;
struct utmp buffer;
int found;
request = (pututline_request *)connection->read_base;
if (request->header.size != sizeof (pututline_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Initialize reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (pututline_reply);
reply.header.type = UTMPD_REQ_PUTUTLINE;
if (!(connection->access & W_OK))
{
errno = EPERM;
goto return_error;
}
if (connection->database == NULL || connection->position == -1)
{
errno = ESRCH;
goto return_error;
}
/* Make sure we're in synch with the ordinary file. */
if (synchronize_database (connection->database) < 0)
{
errno = ESRCH;
goto return_error;
}
/* Find the correct place to insert the data. */
if (connection->position > 0
&& (
#if _HAVE_UT_TYPE - 0
(connection->last_entry.ut_type == request->utmp.ut_type
&& (connection->last_entry.ut_type == RUN_LVL
|| connection->last_entry.ut_type == BOOT_TIME
|| connection->last_entry.ut_type == OLD_TIME
|| connection->last_entry.ut_type == NEW_TIME))
||
#endif
proc_utmp_eq (&connection->last_entry, &request->utmp)))
found = 1;
else
found = internal_getut_r (connection, &request->utmp, &buffer);
if (found < 0)
{
/* We append the next entry. */
connection->position =
append_entry (connection->database, &request->utmp);
if (connection->position < 0)
goto return_error;
}
else
{
/* We replace the just read entry. */
connection->position--;
if (write_entry (connection->database, connection->position,
&request->utmp) < 0)
goto return_error;
}
/* Write the entry to the compatibility file. */
write_old_entry (connection->database, connection->position, &request->utmp);
/* Update position pointer. */
connection->position++;
reply.errnum = 0;
reply.result = 0;
return send_reply (connection, &reply.header);
return_error:
reply.errnum = errno;
reply.result = -1;
return send_reply (connection, &reply.header);
}
static int
do_updwtmp (client_connection *connection)
{
updwtmp_request *request;
updwtmp_reply reply;
utmp_database *database;
request = (updwtmp_request *)connection->read_base;
if (request->header.size != sizeof (updwtmp_request))
{
warning (EINVAL, "invalid request size");
return -1;
}
/* Initialize reply. */
reply.header.version = UTMPD_VERSION;
reply.header.size = sizeof (updwtmp_reply);
reply.header.type = UTMPD_REQ_UPDWTMP;
if (!(connection->access & W_OK))
{
errno = EPERM;
goto return_error;
}
/* Select database. */
if (!strncmp (request->file, _PATH_UTMP, sizeof request->file))
database = utmp_db;
else
{
errno = EINVAL;
goto return_error;
}
/* Make sure we're in synch with the ordinary file. */
if (synchronize_database (database) < 0)
{
errno = ESRCH;
goto return_error;
}
/* Append the entry. */
if (append_entry (database, &request->utmp) < 0)
goto return_error;
reply.errnum = 0;
reply.result = 0;
return send_reply (connection, &reply.header);
return_error:
reply.errnum = errno;
reply.result = -1;
return send_reply (connection, &reply.header);
}
/* This function is identical to the one in login/utmp_file.c. */
static int
proc_utmp_eq (const struct utmp *entry, const struct utmp *match)
{
return
(
#if _HAVE_UT_TYPE - 0
(entry->ut_type == INIT_PROCESS
|| entry->ut_type == LOGIN_PROCESS
|| entry->ut_type == USER_PROCESS
|| entry->ut_type == DEAD_PROCESS)
&&
(match->ut_type == INIT_PROCESS
|| match->ut_type == LOGIN_PROCESS
|| match->ut_type == USER_PROCESS
|| match->ut_type == DEAD_PROCESS)
&&
#endif
#if _HAVE_UT_ID - 0
strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
#else
strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0
#endif
);
}
/* This function is derived from the one in login/utmp_file.c. */
static int
internal_getut_r (client_connection *connection,
const struct utmp *id, struct utmp *buffer)
{
#if _HAVE_UT_TYPE - 0
if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
|| id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
{
/* Search for next entry with type RUN_LVL, BOOT_TIME,
OLD_TIME, or NEW_TIME. */
while (1)
{
/* Read the next entry. */
if (read_entry (connection->database, connection->position,
buffer) < 0)
{
connection->position = -1;
return -1;
}
connection->position++;
if (id->ut_type == buffer->ut_type)
break;
}
}
else
#endif /* _HAVE_UT_TYPE */
{
/* Search for the next entry with the specified ID and with type
INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */
while (1)
{
/* Read the next entry. */
if (read_entry (connection->database, connection->position,
buffer) < 0)
{
connection->position = -1;
return -1;
}
connection->position++;
if (proc_utmp_eq (buffer, id))
break;
}
}
return 0;
}

107
login/utmpd/utmpd-private.h Normal file
View File

@ -0,0 +1,107 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _UTMPD_PRIVATE_H
#define _UTMPD_PRIVATE_H 1
#include <time.h>
#include <utmp.h>
/* The number of connections we allow. */
#ifndef MAX_CONNECTIONS
#define MAX_CONNECTIONS 16
#endif
typedef struct utmp_database
{
int fd;
int old_fd;
char *file;
char *old_file;
time_t mtime;
} utmp_database;
/* The databases we handle. */
extern utmp_database *utmp_db;
extern utmp_database *wtmp_db;
typedef struct client_connection
{
int sock;
/* Access permissions. */
int access;
/* Read pointer. */
void *read_base;
void *read_ptr;
void *read_end;
/* Write buffer. */
void *write_base;
void *write_ptr;
void *write_end;
/* Database to use for this connection. */
utmp_database *database;
/* Position pointer. */
int position;
/* Last read entry. */
struct utmp last_entry;
/* Pointers to the next and previous connections in the list. */
struct client_connection *next;
struct client_connection *prev;
} client_connection;
/* This variable indicates if we have forked. If set, we log messages
via the system logger. Otherwise we simply print the program name
and the message to standard error. */
extern int forked;
/* Database functions. */
utmp_database *open_database (const char *file, const char *old_file);
int synchronize_database (utmp_database *database);
void close_database (utmp_database *database);
int read_entry (utmp_database *database, int position, struct utmp *entry);
int write_entry (utmp_database *database, int position,
const struct utmp *entry);
int append_entry (utmp_database *database, const struct utmp *entry);
int read_old_entry (utmp_database *database, int position, struct utmp *entry);
int write_old_entry (utmp_database *database, int position,
const struct utmp *entry);
/* Connection oriented functions. */
client_connection *accept_connection (int sock, int access);
client_connection *find_connection (int sock);
void close_connection (client_connection *connection);
int read_data (client_connection *connection);
int write_data (client_connection *connection);
void error (int status, int errnum, const char *message, ...);
void warning (int errnum, const char *message, ...);
#endif /* utmpd-private.h */

384
login/utmpd/utmpd.c Normal file
View File

@ -0,0 +1,384 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <libintl.h>
#include <pwd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <syslog.h>
#include <unistd.h>
#include "utmpd.h"
#include "utmpd-private.h"
/* Get libc version number. */
#include "../../version.h"
#define PACKAGE "libc"
/* Long options. */
static const struct option long_options[] =
{
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0}
};
/* The UTMP database. */
utmp_database *utmp_db;
/* The socket for read only requests. */
int ro_sock = -1;
/* The socket for read/write requests. */
int rw_sock = -1;
/* Prototypes for the local functions. */
static void usage (int status) __attribute__ ((noreturn));
static void drop_priviliges (void);
static int make_socket (const char *name);
static void handle_requests (void) __attribute__ ((noreturn));
static void termination_handler (int signum);
static int check_pid (const char *file);
static int write_pid (const char *file);
int
main (int argc, char *argv[])
{
mode_t mask;
int debug;
int do_help;
int do_version;
int opt;
/* Initialize local variables. */
debug = 0;
do_help = 0;
do_version = 0;
while ((opt = getopt_long (argc, argv, "dhV", long_options, NULL)) != -1)
switch (opt)
{
case '\0': /* Long option. */
break;
case 'h':
do_help = 1;
break;
case 'd':
debug = 1;
break;
case 'V':
do_version = 1;
break;
default:
usage (EXIT_FAILURE);
}
/* Version information is reequested. */
if (do_version)
{
printf ("utmpd (GNU %s) %s\n", PACKAGE, VERSION);
printf (gettext ("\
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"), "1997");
printf (gettext ("Written by %s.\n"), "Mark Kettenis");
exit (EXIT_SUCCESS);
}
/* Help is requested. */
if (do_help)
usage (EXIT_SUCCESS);
signal (SIGINT, termination_handler);
signal (SIGTERM, termination_handler);
/* Check if we are already running. */
if (check_pid (_PATH_UTMPDPID))
error (EXIT_FAILURE, 0, "already running");
/* Open UTMP database. */
utmp_db = open_database (_PATH_UTMP "x", _PATH_UTMP);
if (utmp_db == NULL)
error (EXIT_FAILURE, errno, "%s", _PATH_UTMP);
/* Create sockets, with the right permissions. */
mask = umask (S_IXUSR | S_IXGRP | S_IXOTH);
ro_sock = make_socket (_PATH_UTMPD_RO);
umask (S_IXUSR | S_IRWXG | S_IRWXO);
rw_sock = make_socket (_PATH_UTMPD_RW);
umask (mask);
/* Set the sockets up to accept connections. */
if (listen (ro_sock, MAX_CONNECTIONS) < 0
|| listen (rw_sock, MAX_CONNECTIONS) < 0)
error (EXIT_FAILURE, errno, "cannot enable socket to accept connections");
/* Behave like a daemon. */
if (!debug)
{
openlog ("utmpd", LOG_CONS | LOG_ODELAY, LOG_DAEMON);
if (daemon (0, 0) < 0)
error (EXIT_FAILURE, errno, "cannot auto-background");
forked = 1;
if (write_pid (_PATH_UTMPDPID) < 0)
warning (errno, "%s", _PATH_UTMPDPID);
}
/* Drop priviliges. */
drop_priviliges ();
/* Handle incoming requests. */
handle_requests ();
}
/* Display usage information and exit. */
static void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, gettext ("Try `%s --help' for more information.\n"),
program_invocation_name);
else
{
printf (gettext ("\
Usage: %s [OPTION]...\n\
-d, --debug do not fork and display messages on the current tty\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n"),
program_invocation_name);
fputs (gettext ("\
Report bugs to <kettenis@phys.uva.nl>.\n"),
stdout);
}
exit (status);
}
/* Drop priviliges. */
static void
drop_priviliges (void)
{
struct passwd *pw;
pw = getpwnam ("daemon");
if (pw)
{
seteuid (pw->pw_uid);
setegid (pw->pw_gid);
}
}
/* Make a socket in the file namespace using the filename NAME as the
socket's address. */
static int
make_socket (const char *name)
{
struct sockaddr_un addr;
size_t size;
int sock;
/* Create the socket. */
sock = socket (PF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
error (EXIT_FAILURE, errno, "cannot create socket");
/* Bind a name to the socket. */
addr.sun_family = AF_UNIX;
strcpy (addr.sun_path, name);
/* The size of the address is the offset of the start
of the filename, plus its length, plus one for the
terminating null byte. */
size = (offsetof (struct sockaddr_un, sun_path)
+ strlen (addr.sun_path));
if (bind (sock, (struct sockaddr *) &addr, size) < 0)
error (EXIT_FAILURE, errno, "%s", name);
return sock;
}
/* Hanlde incoming requests. */
static
void handle_requests (void)
{
client_connection *connection;
fd_set active_read_fd_set;
fd_set active_write_fd_set;
fd_set read_fd_set;
fd_set write_fd_set;
int fd;
/* Initialize the set of active sockets. */
FD_ZERO (&active_read_fd_set);
FD_ZERO (&active_write_fd_set);
FD_SET (rw_sock, &active_read_fd_set);
FD_SET (ro_sock, &active_read_fd_set);
while (1)
{
/* Block until input arrives on one or more active sockets. */
read_fd_set = active_read_fd_set;
write_fd_set = active_write_fd_set;
if (select (FD_SETSIZE, &read_fd_set, &write_fd_set, NULL, NULL) < 0)
error (EXIT_FAILURE, errno, "cannot get input on sockets");
/* Service all the sockets with input pending. */
for (fd = 0; fd < FD_SETSIZE; fd++)
{
if (FD_ISSET (fd, &read_fd_set))
{
if (fd == ro_sock || fd == rw_sock)
{
int access = ((fd == rw_sock) ? (R_OK | W_OK) : R_OK);
connection = accept_connection (fd, access);
if (connection == NULL)
error (0, errno, "cannot accept connection");
FD_SET (connection->sock, &active_read_fd_set);
}
else
{
connection = find_connection (fd);
if (connection == NULL)
error (EXIT_FAILURE, 0, "cannot find connection");
if (read_data (connection) < 0)
{
close_connection (connection);
FD_CLR (fd, &active_read_fd_set);
FD_CLR (fd, &active_write_fd_set);
}
if (connection->write_ptr > connection->write_base)
FD_SET (fd, &active_write_fd_set);
}
}
if (FD_ISSET (fd, &write_fd_set) &&
fd != rw_sock && fd != ro_sock)
{
connection = find_connection (fd);
if (connection == NULL)
error (EXIT_FAILURE, 0, "cannot find connection");
if (write_data (connection) < 0)
{
close_connection (connection);
FD_CLR (fd, &active_read_fd_set);
FD_CLR (fd, &active_write_fd_set);
}
if (connection->write_ptr == connection->write_base)
FD_CLR (fd, &active_write_fd_set);
}
}
}
}
/* Cleanup. */
static void
termination_handler (int signum)
{
/* Close sockets. */
close (ro_sock);
close (rw_sock);
/* Restore user id. */
seteuid (getuid ());
/* Clean up the files created by `bind'. */
unlink (_PATH_UTMPD_RO);
unlink (_PATH_UTMPD_RW);
if (utmp_db)
close_database (utmp_db);
/* Clean up pid file. */
unlink (_PATH_UTMPDPID);
exit (EXIT_SUCCESS);
}
/* Returns 1 if the process in pid file FILE is running, 0 if not. */
static int
check_pid (const char *file)
{
FILE *fp;
fp = fopen (_PATH_UTMPDPID, "r");
if (fp)
{
pid_t pid;
fscanf (fp, "%d", &pid);
fclose (fp);
if (kill (pid, 0) == 0)
return 1;
}
return 0;
}
/* Write the current process id to the file FILE. Returns 0 if
successful, -1 if not. */
static int
write_pid (const char *file)
{
FILE *fp;
fp = fopen (_PATH_UTMPDPID, "w");
if (fp == NULL)
return -1;
fprintf (fp, "%d\n", getpid ());
if (ferror (fp))
return -1;
fclose (fp);
return 0;
}

141
login/utmpd/utmpd.h Normal file
View File

@ -0,0 +1,141 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _UTMPD_H
#define _UTMPD_H 1
/* This is an *internal* header. */
#include <limits.h>
#include <stddef.h>
#include <utmp.h>
/* Paths to daemon sockets. */
#define _PATH_UTMPD_RO "/var/run/utmpd.ro"
#define _PATH_UTMPD_RW "/var/run/utmpd.rw"
/* Path to PID file. */
#define _PATH_UTMPDPID "/var/run/utmpd.pid"
/* Version number of the daemon interface. */
#define UTMPD_VERSION 1
/* Services provided. */
typedef enum
{
UTMPD_REQ_SETUTENT,
UTMPD_REQ_GETUTENT,
UTMPD_REQ_ENDUTENT,
UTMPD_REQ_GETUTLINE,
UTMPD_REQ_GETUTID,
UTMPD_REQ_PUTUTLINE,
UTMPD_REQ_UPDWTMP
} request_type;
/* Header common to all requests. */
typedef struct
{
/* Version number of the daemon interface. */
int version;
/* Number of bytes in this request. */
size_t size;
/* Service requested. */
request_type type;
} request_header;
typedef struct
{
request_header header;
/* File to use. */
char file[_POSIX_PATH_MAX + 1];
} setutent_request;
typedef struct
{
request_header header;
} getutent_request, endutent_request;
typedef struct
{
request_header header;
/* Entry to match. */
struct utmp line;
} getutline_request;
typedef struct
{
request_header header;
/* Entry to match. */
struct utmp id;
} getutid_request;
typedef struct
{
request_header header;
/* Entry to write. */
struct utmp utmp;
} pututline_request;
typedef struct
{
request_header header;
/* File to use. */
char file[_POSIX_PATH_MAX + 1];
/* Entry to write. */
struct utmp utmp;
} updwtmp_request;
/* Header common to all replies. */
typedef struct
{
/* Version number of the daemon interface. */
int version;
/* Number of bytes in this reply. */
size_t size;
/* Answer to the request. */
request_type type;
} reply_header;
typedef struct
{
reply_header header;
/* Error code. */
int errnum;
/* Return value. */
int result;
} setutent_reply, endutent_reply, pututline_reply, updwtmp_reply;
typedef struct
{
reply_header header;
/* Found entry. */
struct utmp entry;
/* Error code. */
int errnum;
/* Return value. */
int result;
} getutent_reply, getutline_reply, getutid_reply;
#endif /* utmpd.h */

102
login/utmpd/xtmp.c Normal file
View File

@ -0,0 +1,102 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <utmp.h>
#include "xtmp.h"
/* Convert the entry XT to the new utmp format and store it in UT.
Fields in UT that were not present in the old utmp format are
initialized to zero. */
void
xtmp_to_utmp (const struct xtmp *xtmp, struct utmp *utmp)
{
memset (utmp, 0, sizeof (struct utmp));
#if _HAVE_XT_TYPE - 0
utmp->ut_type = xtmp->xt_type;
#endif
#if _HAVE_XT_PID - 0
utmp->ut_pid = xtmp->xt_pid;
#endif
strncpy (utmp->ut_line, xtmp->xt_line, XT_LINESIZE);
#if _HAVE_XT_ID - 0
strncpy (utmp->ut_id, xtmp->xt_id, sizeof xtmp->xt_id);
#endif
utmp->ut_time = xtmp->xt_time;
strncpy (utmp->ut_user, xtmp->xt_user, XT_NAMESIZE);
#if _HAVE_XT_HOST - 0
strncpy (utmp->ut_host, xtmp->xt_host, XT_HOSTSIZE);
#endif
utmp->ut_addr = xtmp->xt_addr;
}
/* Convert the entry UTMP to the old utmp format and store it in XTMP. */
void
utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp)
{
memset (xtmp, 0, sizeof (struct xtmp));
#if _HAVE_XT_TYPE - 0
xtmp->xt_type = utmp->ut_type;
#endif
#if _HAVE_XT_PID - 0
xtmp->xt_pid = utmp->ut_pid;
#endif
strncpy (xtmp->xt_line, utmp->ut_line, XT_LINESIZE);
xtmp->xt_line[XT_LINESIZE] = '\0';
#if _HAVE_XT_ID - 0
strncpy (xtmp->xt_id, utmp->ut_id, sizeof xtmp->xt_id);
#endif
xtmp->xt_time = utmp->ut_time;
strncpy (xtmp->xt_user, utmp->ut_user, XT_NAMESIZE);
#if _HAVE_XT_HOST - 0
strncpy (xtmp->xt_host, utmp->ut_host, XT_HOSTSIZE);
xtmp->xt_host[XT_HOSTSIZE] = '\0';
#endif
xtmp->xt_addr = utmp->ut_addr;
}
/* Compare an old style entry XTMP with a new style entry UTMP. The
function returns 1 if the information that is in both old and new
style entries is identical. Otherwise this function returns 0. */
int
compare_entry (const struct utmp *xtmp, const struct utmp *utmp)
{
return
(
#if _HAVE_XT_TYPE - 0
xtmp->ut_type == utmp->ut_type
#endif
#if _HAVE_XT_PID - 0
&& xtmp->ut_pid == utmp->ut_pid
#endif
&& !strncmp (xtmp->ut_line, utmp->ut_line, XT_LINESIZE - 1)
#if _HAVE_XT_ID - 0
&& !strncmp (xtmp->ut_id, utmp->ut_id, sizeof utmp->ut_id)
#endif
&& xtmp->ut_time == utmp->ut_time
&& !strncmp (xtmp->ut_user, utmp->ut_user, XT_NAMESIZE)
#if _HAVE_XT_HOST - 0
&& !strncmp (xtmp->ut_host, utmp->ut_host, XT_HOSTSIZE - 1)
#endif
&& xtmp->ut_addr == utmp->ut_addr);
}

56
login/utmpd/xtmp.h Normal file
View File

@ -0,0 +1,56 @@
/* The `struct xtmp' type, describing the old linux utmp format.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _XTMP_H
#define _XTMP_H 1
#include <features.h>
#include <sys/time.h>
#include <sys/types.h>
#define XT_LINESIZE 12
#define XT_NAMESIZE 8
#define XT_HOSTSIZE 16
struct xtmp
{
short int xt_type; /* Type of login. */
pid_t xt_pid; /* Pid of login process. */
char xt_line[XT_LINESIZE]; /* NUL-terminated devicename of tty. */
char xt_id[4]; /* Inittab id. */
time_t xt_time; /* Time entry was made. */
char xt_user[XT_NAMESIZE]; /* Username (not NUL terminated). */
char xt_host[XT_HOSTSIZE]; /* Hostname for remote login. */
long xt_addr; /* Internet adress of remote host. */
};
#define _HAVE_XT_TYPE 1
#define _HAVE_XT_PID 1
#define _HAVE_XT_ID 1
#define _HAVE_XT_HOST 1
extern void xtmp_to_utmp (const struct xtmp *xtmp, struct utmp *utmp);
extern void utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp);
extern int compare_entry (const struct utmp *xtmp,
const struct utmp *utmp);
#endif /* xtmp.h */

53
login/utmpdump.c Normal file
View File

@ -0,0 +1,53 @@
/* utmpdump - dump utmp-like files.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
void
print_entry (struct utmp *up)
{
printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-15.15s] [%ld]\n",
up->ut_type, up->ut_pid, up->ut_id, up->ut_user,
up->ut_line, 4 + ctime (&up->ut_time), up->ut_tv.tv_usec);
}
int
main (int argc, char *argv[])
{
struct utmp *up;
if (argc > 1)
utmpname (argv[1]);
setutent ();
while ((up = getutent ()))
print_entry (up);
endutent ();
return EXIT_SUCCESS;
}

86
login/utmpname.c Normal file
View File

@ -0,0 +1,86 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#if _LIBC
#include <libc-lock.h>
#else
#define __libc_lock_lock(NAME) ((void) 0)
#define __libc_lock_unlock(NAME) ((void) 0)
#define __libc_lock_define(CLASS,NAME)
#define weak_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
#endif
#include <stdlib.h>
#include <string.h>
#include <utmp.h>
#include "utmp-private.h"
/* This is the default name. */
static const char default_file_name[] = _PATH_UTMP;
/* Current file name. */
const char *__libc_utmp_file_name = (const char *) default_file_name;
/* We have to use the lock in getutent_r.c. */
__libc_lock_define (extern, __libc_utmp_lock)
int
__utmpname (const char *file)
{
int result = -1;
__libc_lock_lock (__libc_utmp_lock);
/* Close the old file. */
(*__libc_utmp_jump_table->endutent) ();
if (strcmp (file, __libc_utmp_file_name) != 0)
{
if (strcmp (file, default_file_name) == 0)
{
if (__libc_utmp_file_name != default_file_name)
free ((char *) __libc_utmp_file_name);
__libc_utmp_file_name = default_file_name;
}
else
{
char *file_name = __strdup (file);
if (file_name == NULL)
/* Out of memory. */
goto done;
if (__libc_utmp_file_name != default_file_name)
free ((char *) __libc_utmp_file_name);
__libc_utmp_file_name = file_name;
}
}
__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
result = 0;
done:
__libc_lock_unlock (__libc_utmp_lock);
return result;
}
weak_alias (__utmpname, utmpname)

View File

@ -74,19 +74,23 @@ long-c-yes = $(calls:=l)
distribute += $(long-c-yes:=.c)
# Rules for the test suite.
tests = test-float test-double $(test-longdouble-$(long-double-fcts))
tests = test-float test-double $(test-longdouble-$(long-double-fcts)) \
test-ifloat test-idouble
# We do the `long double' tests only if this data type is available and
# distrinct from `double'.
#
# XXX This test is disabled for now since the functions are too buggy.
#test-longdouble-yes = test-longdouble
#test-longdouble-yes = test-ldouble test-ildoubl
CFLAGS-test-float.c = -fno-inline
CFLAGS-test-double.c = -fno-inline
CFLAGS-test-longdouble.c = -fno-inline
CFLAGS-test-ldouble.c = -fno-inline
LDLIBS-test-ifloat = libm
LDLIBS-test-idouble = libm
LDLIBS-test-ildoubl = libm
LDLIBS-test-float = libm
LDLIBS-test-double = libm
LDLIBS-test-longdouble = libm
LDLIBS-test-ldouble = libm
distribute += libm-test.c

View File

@ -18,7 +18,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* NOTE: Because of the special way this file is used by <math.h>, this
/* NOTE: Because of the special way this file is used by <complex.h>, this
file must NOT be protected from multiple inclusion as header files
usually are.

View File

@ -1,6 +1,6 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@arthur.pfalz.de>, 1997.
Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@ -39,30 +39,67 @@
*/
/* This program isn't finished yet.
It has tests for acos, acosh, asin, asinh, atan, atan2, atanh,
It has tests for:
acos, acosh, asin, asinh, atan, atan2, atanh,
cbrt, ceil, copysign, cos, cosh, exp, exp2, expm1,
fabs, fdim, floor, fmin, fmax, fpclassify,
frexp, hypot, ilogb, ldexp,
log, log10, log1p, log2, logb, modf, nextafter,
pow, scalb, scalbn, sin, sinh, sqrt, tan, tanh, trunc.
Tests for the other libm-functions will come later.
pow, rint, rinttol, rinttoll, round, roundtol, roundtoll,
scalb, scalbn, sin, sinh, sqrt, tan, tanh, trunc
and for the following complex math functions:
cacos, cacosh, casin, casinh, catan, catanh,
ccos, ccosh, cexp, clog, cpow, csin, csinh, csqrt, ctanh.
At the moment the following functions aren't tested:
cabs, carg, conj, cproj, cimag, creal, drem,
erf, erfc, gamma, lgamma,
j0, j1, jn, y0, y1, yn,
nearbyint, remainder, remquo, signbit, significant, sincos.
The routines using random variables are still under construction. I don't
like it the way it's working now and will change it.
Exception handling has not been implemented so far so don't get fooled
that these tests pass.
Parameter handling is primitive in the moment:
--verbose=[0..3] for different levels of output:
--verbose=[0..4] for different levels of output:
0: only error count
1: basic report on failed tests
1: basic report on failed tests (default)
2: full report on failed tests
3: full report on failed and passed tests (default)
-v for full output (equals --verbose=3)
3: full report on failed and passed tests
4: additional report on exceptions
-v for full output (equals --verbose=4)
-s,--silent outputs only the error count (equals --verbose=0)
*/
/* "Philosophy":
This suite tests the correct implementation of mathematical
functions in libm. Some simple, specific parameters are tested for
correctness. Handling of specific inputs (e.g. infinity,
not-a-number) is also tested. Correct handling of exceptions is
checked against. These implemented tests should check all cases
that are specified in ISO C 9X.
Inline functions: Inlining functions should give an improvement in
speed - but not in precission. The inlined functions return
reasonable values for a reasonable range of input values. The
result is not necessarily correct for all values and exceptions are
not correctly raised in all cases. Problematic input and return
values are infinity, not-a-number and minus zero. This suite
therefore does not check these specific inputs and the exception
handling for inlined mathematical functions - just the "reasonable"
values are checked.
Beware: The tests might fail for any of the following reasons:
- Tests are wrong
- Functions are wrong
- Floating Point Unit not working properly
- Compiler has errors
With e.g. gcc 2.7.2.2 the test for cexp fails because of a compiler error.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
@ -75,11 +112,8 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <getopt.h>
/* TEST_EXCEPTION: tests if an exception as occured */
/* for the moment: does nothing */
/* Possible exceptions */
#define NO_EXCEPTION 0x0
#define INVALID_EXCEPTION 0x1
@ -167,11 +201,39 @@ random_greater (MATHTYPE min_value)
}
/* Get a random value x with x < max_value. */
#ifndef TEST_INLINE
static MATHTYPE
random_less (MATHTYPE max_value)
{
return random_value (-1e6, max_value);
}
#endif
static void
output_new_test (const char *test_name)
{
if (verbose > 2)
printf ("\nTesting: %s\n", test_name);
}
static void
output_pass_value (void)
{
if (verbose > 2)
printf ("Pass: Value Ok.\n");
}
static void
output_fail_value (const char * test_name)
{
if (verbose > 0 && verbose < 3)
printf ("Fail: %s\n", test_name);
if (verbose >= 3)
printf ("Fail:\n");
}
/* Test whether a given exception was raised. */
@ -182,18 +244,22 @@ test_single_exception (const char *test_name,
fexcept_t fe_flag,
const char *flag_name)
{
#ifndef TEST_INLINE
if (exception & exc_flag)
{
if (fetestexcept (fe_flag))
{
if (verbose > 2)
printf ("Pass: %s:\nException \"%s\" set\n", test_name, flag_name);
if (verbose > 3)
printf ("Pass: Exception \"%s\" set\n", flag_name);
}
else
{
if (verbose)
printf ("Fail: %s:\nException \"%s\" not set\n",
if (verbose && verbose < 3)
printf ("Fail: %s: Exception \"%s\" not set\n",
test_name, flag_name);
if (verbose >= 3)
printf ("Fail: Exception \"%s\" not set\n",
flag_name);
++noErrors;
}
}
@ -201,18 +267,22 @@ test_single_exception (const char *test_name,
{
if (fetestexcept (fe_flag))
{
if (verbose)
printf ("Fail: %s:\nException \"%s\" set\n",
if (verbose && verbose < 3)
printf ("Fail: %s: Exception \"%s\" set\n",
test_name, flag_name);
if (verbose >= 3)
printf ("Fail: Exception \"%s\" set\n",
flag_name);
++noErrors;
}
else
{
if (verbose > 2)
printf ("Pass: %s:\nException \"%s\" not set\n",
test_name, flag_name);
if (verbose > 3)
printf ("Pass: Exception \"%s\" not set\n",
flag_name);
}
}
#endif
}
@ -256,6 +326,8 @@ test_exceptions (const char *test_name, short int exception)
static int
check_equal (MATHTYPE computed, MATHTYPE supplied, MATHTYPE eps, MATHTYPE * diff)
{
int ret_value;
/* Both plus Infinity or both minus infinity. */
if (ISINF (computed) && (ISINF (computed) == ISINF (supplied)))
return 1;
@ -265,25 +337,28 @@ check_equal (MATHTYPE computed, MATHTYPE supplied, MATHTYPE eps, MATHTYPE * diff
*diff = FUNC(fabs) (computed - supplied);
if (*diff <= eps && (signbit (computed) == signbit (supplied) || eps != 0.0))
return 1;
return 0;
ret_value = (*diff <= eps &&
(signbit (computed) == signbit (supplied) || eps != 0.0));
/* Make sure the subtraction/comparsion have no influence on the exceptions. */
feclearexcept (FE_ALL_EXCEPT);
return ret_value;
}
static void
output_result_bool (const char *test_name, int result)
{
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
++noErrors;
}
@ -297,13 +372,11 @@ output_isvalue (const char *test_name, int result,
{
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
if (verbose > 1)
printf (" Value: %.20" PRINTF_EXPR "\n", value);
noErrors++;
@ -319,13 +392,11 @@ output_isvalue_ext (const char *test_name, int result,
{
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
if (verbose > 1)
{
printf (" Value: %.20" PRINTF_EXPR "\n", value);
@ -346,13 +417,11 @@ output_result (const char *test_name, int result,
{
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
if (verbose > 1 && print_values)
{
printf ("Result:\n");
@ -377,13 +446,11 @@ output_result_ext (const char *test_name, int result,
{
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
if (verbose > 1 && print_values)
{
printf ("Result:\n");
@ -399,13 +466,16 @@ output_result_ext (const char *test_name, int result,
fpstack_test (test_name);
}
/*
check that computed and expected values are the same
*/
static void
check (const char *test_name, MATHTYPE computed, MATHTYPE expected)
{
MATHTYPE diff;
int result;
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
result = check_equal (computed, expected, 0, &diff);
output_result (test_name, result,
@ -413,6 +483,10 @@ check (const char *test_name, MATHTYPE computed, MATHTYPE expected)
}
/*
check that computed and expected values are the same,
outputs the parameter to the function
*/
static void
check_ext (const char *test_name, MATHTYPE computed, MATHTYPE expected,
MATHTYPE parameter)
@ -420,6 +494,7 @@ check_ext (const char *test_name, MATHTYPE computed, MATHTYPE expected,
MATHTYPE diff;
int result;
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
result = check_equal (computed, expected, 0, &diff);
output_result_ext (test_name, result,
@ -427,6 +502,10 @@ check_ext (const char *test_name, MATHTYPE computed, MATHTYPE expected,
}
/*
check that computed and expected values are the same and
checks also for exception flags
*/
static void
check_exc (const char *test_name, MATHTYPE computed, MATHTYPE expected,
short exception)
@ -434,13 +513,16 @@ check_exc (const char *test_name, MATHTYPE computed, MATHTYPE expected,
MATHTYPE diff;
int result;
output_new_test (test_name);
test_exceptions (test_name, exception);
result = check_equal (computed, expected, 0, &diff);
output_result (test_name, result,
computed, expected, diff, PRINT, PRINT);
}
/*
check that computed and expected values are close enough
*/
static void
check_eps (const char *test_name, MATHTYPE computed, MATHTYPE expected,
MATHTYPE epsilon)
@ -448,38 +530,43 @@ check_eps (const char *test_name, MATHTYPE computed, MATHTYPE expected,
MATHTYPE diff;
int result;
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
result = check_equal (computed, expected, epsilon, &diff);
output_result (test_name, result,
computed, expected, diff, PRINT, PRINT);
}
/*
check a boolean condition
*/
static void
check_bool (const char *test_name, int computed)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_result_bool (test_name, computed);
}
/*
check that computed and expected values are equal (long int values)
*/
static void
check_long (const char *test_name, long int computed, long int expected)
{
long int diff = computed - expected;
int result = diff == 0;
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
if (verbose > 1)
{
printf ("Result:\n");
@ -492,7 +579,9 @@ check_long (const char *test_name, long int computed, long int expected)
fpstack_test (test_name);
}
/*
check that computed and expected values are equal (long long int values)
*/
static void
check_longlong (const char *test_name, long long int computed,
long long int expected)
@ -500,17 +589,16 @@ check_longlong (const char *test_name, long long int computed,
long long int diff = computed - expected;
int result = diff == 0;
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
if (result)
{
if (verbose > 2)
printf ("Pass: %s\n", test_name);
output_pass_value ();
}
else
{
if (verbose)
printf ("Fail: %s\n", test_name);
output_fail_value (test_name);
if (verbose > 1)
{
printf ("Result:\n");
@ -523,46 +611,64 @@ check_longlong (const char *test_name, long long int computed,
fpstack_test (test_name);
}
/*
check that computed value is not-a-number
*/
static void
check_isnan (const char *test_name, MATHTYPE computed)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_isvalue (test_name, isnan (computed), computed);
}
/*
check that computed value is not-a-number and test for exceptions
*/
static void
check_isnan_exc (const char *test_name, MATHTYPE computed,
short exception)
{
output_new_test (test_name);
test_exceptions (test_name, exception);
output_isvalue (test_name, isnan (computed), computed);
}
/*
check that computed value is not-a-number and test for exceptions
*/
static void
check_isnan_maybe_exc (const char *test_name, MATHTYPE computed,
short exception)
{
output_new_test (test_name);
test_not_exception (test_name, exception);
output_isvalue (test_name, isnan (computed), computed);
}
/*
check that computed value is not-a-number and supply parameter
*/
#ifndef TEST_INLINE
static void
check_isnan_ext (const char *test_name, MATHTYPE computed,
MATHTYPE parameter)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_isvalue_ext (test_name, isnan (computed), computed, parameter);
}
#endif
/* Tests if computed is +Inf */
static void
check_isinfp (const char *test_name, MATHTYPE computed)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_isvalue (test_name, (ISINF (computed) == +1), computed);
}
@ -572,6 +678,7 @@ static void
check_isinfp_ext (const char *test_name, MATHTYPE computed,
MATHTYPE parameter)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_isvalue_ext (test_name, (ISINF (computed) == +1), computed, parameter);
}
@ -582,6 +689,7 @@ static void
check_isinfp_exc (const char *test_name, MATHTYPE computed,
int exception)
{
output_new_test (test_name);
test_exceptions (test_name, exception);
output_isvalue (test_name, (ISINF (computed) == +1), computed);
}
@ -590,18 +698,22 @@ check_isinfp_exc (const char *test_name, MATHTYPE computed,
static void
check_isinfn (const char *test_name, MATHTYPE computed)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_isvalue (test_name, (ISINF (computed) == -1), computed);
}
#ifndef TEST_INLINE
static void
check_isinfn_ext (const char *test_name, MATHTYPE computed,
MATHTYPE parameter)
{
output_new_test (test_name);
test_exceptions (test_name, NO_EXCEPTION);
output_isvalue_ext (test_name, (ISINF (computed) == -1), computed, parameter);
}
#endif
/* Tests if computed is -Inf */
@ -609,6 +721,7 @@ static void
check_isinfn_exc (const char *test_name, MATHTYPE computed,
int exception)
{
output_new_test (test_name);
test_exceptions (test_name, exception);
output_isvalue (test_name, (ISINF (computed) == -1), computed);
}
@ -621,48 +734,59 @@ check_isinfn_exc (const char *test_name, MATHTYPE computed,
static void
acos_test (void)
{
#ifndef TEST_INLINE
MATHTYPE x;
check ("acos (1) == 0", FUNC(acos) (1), 0);
x = random_greater (1);
check_isnan_exc ("acos (x) == NaN plus invalid exception for |x| > 1",
FUNC(acos) (x),
INVALID_EXCEPTION);
#endif
check ("acos (1) == 0", FUNC(acos) (1), 0);
}
static void
acosh_test (void)
{
#ifndef TEST_INLINE
MATHTYPE x;
check ("acosh(1) == 0", FUNC(acosh) (1), 0);
check_isinfp ("acosh(+inf) == +inf", FUNC(acosh) (plus_infty));
x = random_less (1);
check_isnan_exc ("acosh(x) == NaN plus invalid exception if x < 1",
FUNC(acosh) (x), INVALID_EXCEPTION);
#endif
check ("acosh(1) == 0", FUNC(acosh) (1), 0);
}
static void
asin_test (void)
{
#ifndef TEST_INLINE
MATHTYPE x;
check ("asin (0) == 0", FUNC(asin) (0), 0);
x = random_greater (1);
check_isnan_exc ("asin x == NaN plus invalid exception for |x| > 1",
FUNC(asin) (x),
INVALID_EXCEPTION);
#endif
check ("asin (0) == 0", FUNC(asin) (0), 0);
}
static void
asinh_test (void)
{
check ("asinh(+0) == +0", FUNC(asinh) (0), 0);
#ifndef TEST_INLINE
check ("asinh(-0) == -0", FUNC(asinh) (minus_zero), minus_zero);
#endif
}
@ -674,7 +798,6 @@ atan_test (void)
check ("atan (+inf) == pi/2", FUNC(atan) (plus_infty), M_PI_2);
check ("atan (-inf) == -pi/2", FUNC(atan) (minus_infty), -M_PI_2);
}
static void
@ -734,11 +857,14 @@ atanh_test (void)
{
check ("atanh(+0) == +0", FUNC(atanh) (0), 0);
#ifndef TEST_INLINE
check ("atanh(-0) == -0", FUNC(atanh) (minus_zero), minus_zero);
check_isinfp_exc ("atanh(+1) == +inf plus divide-by-zero exception",
FUNC(atanh) (1), DIVIDE_BY_ZERO_EXCEPTION);
check_isinfn_exc ("atanh(-1) == -inf plus divide-by-zero exception",
FUNC(atanh) (-1), DIVIDE_BY_ZERO_EXCEPTION);
#endif
}
@ -748,10 +874,11 @@ cbrt_test (void)
check ("cbrt (+0) == +0", FUNC(cbrt) (0.0), 0.0);
check ("cbrt (-0) == -0", FUNC(cbrt) (minus_zero), minus_zero);
#ifndef TEST_INLINE
check_isinfp ("cbrt (+inf) == +inf", FUNC(cbrt) (plus_infty));
check_isinfn ("cbrt (-inf) == -inf", FUNC(cbrt) (minus_infty));
check_isnan ("cbrt (NaN) == NaN", FUNC(cbrt) (nan_value));
#endif
check_eps ("cbrt (8) == 2", FUNC(cbrt) (8), 2, CHOOSE (5e-17L, 0, 0));
check_eps ("cbrt (-27) == -3", FUNC(cbrt) (-27.0), -3.0,
CHOOSE (3e-16L, 0, 0));
@ -797,8 +924,10 @@ cosh_test (void)
check ("cosh (+0) == 1", FUNC(cosh) (0), 1);
check ("cosh (-0) == 1", FUNC(cosh) (minus_zero), 1);
#ifndef TEST_INLINE
check_isinfp ("cosh (+inf) == +inf", FUNC(cosh) (plus_infty));
check_isinfp ("cosh (-inf) == +inf", FUNC(cosh) (minus_infty));
#endif
}
@ -808,9 +937,10 @@ exp_test (void)
check ("exp (+0) == 1", FUNC(exp) (0), 1);
check ("exp (-0) == 1", FUNC(exp) (minus_zero), 1);
#ifndef TEST_INLINE
check_isinfp ("exp (+inf) == +inf", FUNC(exp) (plus_infty));
check ("exp (-inf) == 0", FUNC(exp) (minus_infty), 0);
#endif
check_eps ("exp (1) == e", FUNC(exp) (1), M_E, CHOOSE (4e-18L, 0, 0));
}
@ -1207,10 +1337,13 @@ static void
sinh_test (void)
{
check ("sinh (+0) == +0", FUNC(sinh) (0), 0);
#ifndef TEST_INLINE
check ("sinh (-0) == -0", FUNC(sinh) (minus_zero), minus_zero);
check_isinfp ("sinh (+inf) == +inf", FUNC(sinh) (plus_infty));
check_isinfn ("sinh (-inf) == -inf", FUNC(sinh) (minus_infty));
#endif
}
@ -1233,10 +1366,12 @@ static void
tanh_test (void)
{
check ("tanh (+0) == +0", FUNC(tanh) (0), 0);
#ifndef TEST_INLINE
check ("tanh (-0) == -0", FUNC(tanh) (minus_zero), minus_zero);
check ("tanh (+inf) == +1", FUNC(tanh) (plus_infty), 1);
check ("tanh (-inf) == -1", FUNC(tanh) (minus_infty), -1);
#endif
}
@ -1311,6 +1446,7 @@ pow_test (void)
check ("pow (NaN, +0) == 1", FUNC(pow) (nan_value, 0), 1);
check ("pow (NaN, -0) == 1", FUNC(pow) (nan_value, minus_zero), 1);
#ifndef TEST_INLINE
check_isinfp ("pow (+1.1, +inf) == +inf", FUNC(pow) (1.1, plus_infty));
check_isinfp ("pow (+inf, +inf) == +inf", FUNC(pow) (plus_infty, plus_infty));
check_isinfp ("pow (-1.1, +inf) == +inf", FUNC(pow) (-1.1, plus_infty));
@ -1408,14 +1544,19 @@ pow_test (void)
FUNC(pow) (minus_zero, -2), DIVIDE_BY_ZERO_EXCEPTION);
check_isinfp_exc ("pow (-0, -11.1) == +inf plus divide-by-zero exception",
FUNC(pow) (minus_zero, -11.1), DIVIDE_BY_ZERO_EXCEPTION);
#endif
check ("pow (+0, 1) == +0", FUNC(pow) (0, 1), 0);
check ("pow (+0, 11) == +0", FUNC(pow) (0, 11), 0);
#ifndef TEST_INLINE
check ("pow (-0, 1) == -0", FUNC(pow) (minus_zero, 1), minus_zero);
check ("pow (-0, 11) == -0", FUNC(pow) (minus_zero, 11), minus_zero);
#endif
check ("pow (+0, 2) == +0", FUNC(pow) (0, 2), 0);
check ("pow (+0, 11.1) == +0", FUNC(pow) (0, 11.1), 0);
#ifndef TEST_INLINE
check ("pow (-0, 2) == +0", FUNC(pow) (minus_zero, 2), 0);
check ("pow (-0, 11.1) == +0", FUNC(pow) (minus_zero, 11.1), 0);
@ -1425,11 +1566,11 @@ pow_test (void)
x = random_value (-1.0, 1.0);
check_ext ("pow (x, +inf) == +0 for |x| < 1",
FUNC(pow) (x, plus_infty), 0.0, x);
FUNC(pow) (x, plus_infty), 0.0, x);
x = random_greater (1.0);
check_ext ("pow (x, -inf) == +0 for |x| > 1",
FUNC(pow) (x, minus_infty), 0.0, x);
FUNC(pow) (x, minus_infty), 0.0, x);
x = random_value (-1.0, 1.0);
check_isinfp_ext ("pow (x, -inf) == +inf for |x| < 1",
@ -1458,13 +1599,16 @@ pow_test (void)
x = ((rand () % 1000000) + 1) * -2.0; /* Get random even integer < 0 */
check_ext ("pow (-inf, y) == +0 for y < 0 and not an odd integer",
FUNC(pow) (minus_infty, x), 0.0, x);
#endif
x = (rand () % 1000000) * 2.0 + 1; /* Get random odd integer > 0 */
check_ext ("pow (+0, y) == +0 for y an odd integer > 0",
FUNC(pow) (0.0, x), 0.0, x);
#ifndef TEST_INLINE
x = (rand () % 1000000) * 2.0 + 1; /* Get random odd integer > 0 */
check_ext ("pow (-0, y) == -0 for y an odd integer > 0",
FUNC(pow) (minus_zero, x), minus_zero, x);
#endif
x = ((rand () % 1000000) + 1) * 2.0; /* Get random even integer > 1 */
check_ext ("pow (+0, y) == +0 for y > 0 and not an odd integer",
@ -1682,6 +1826,7 @@ sqrt_test (void)
x = random_value (0, 10000);
check_ext ("sqrt (x*x) == x", FUNC(sqrt) (x*x), x, x);
check ("sqrt (4) == 2", FUNC(sqrt) (4), 2);
}
@ -1741,11 +1886,18 @@ cexp_test (void)
check ("real(cexp(-inf - 0i)) = 0", __real__ result, 0);
check ("imag(cexp(-inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(cexp) (BUILD_COMPLEX (0.0, plus_infty));
check_isnan_exc ("real(cexp(0 + i inf)) = NaN plus invalid exception",
__real__ result, INVALID_EXCEPTION);
check_isnan ("imag(cexp(0 + i inf)) = NaN plus invalid exception",
__imag__ result);
#if defined __GNUC__ && __GNUC__ <= 2 && __GNUC_MINOR <= 7
if (verbose)
printf ("The following test for cexp might fail due to a gcc compiler error!\n");
#endif
result = FUNC(cexp) (BUILD_COMPLEX (minus_zero, plus_infty));
check_isnan_exc ("real(cexp(-0 + i inf)) = NaN plus invalid exception",
__real__ result, INVALID_EXCEPTION);
@ -3757,6 +3909,15 @@ static void
cpow_test (void)
{
__complex__ MATHTYPE result;
result = FUNC (cpow) (BUILD_COMPLEX (1, 0), BUILD_COMPLEX (0, 0));
check ("real(cpow (1 + i0), (0 + i0)) = 0", __real__ result, 1);
check ("imag(cpow (1 + i0), (0 + i0)) = 0", __imag__ result, 0);
result = FUNC (cpow) (BUILD_COMPLEX (2, 0), BUILD_COMPLEX (10, 0));
check ("real(cpow (2 + i0), (10 + i0)) = 1024", __real__ result, 1024);
check ("imag(cpow (2 + i0), (10 + i0)) = 0", __imag__ result, 0);
}
@ -3887,6 +4048,7 @@ inverse_func_pair_test (const char *test_name,
b = inverse (a);
(void) &b;
output_new_test (test_name);
result = check_equal (b, x, epsilon, &difference);
output_result (test_name, result,
b, x, difference, PRINT, PRINT);
@ -3941,6 +4103,7 @@ identities1_test (MATHTYPE x, MATHTYPE epsilon)
res3 = res1 * res1 + res2 * res2;
(void) &res3;
output_new_test ("sin^2 + cos^2 == 1");
result = check_equal (res3, 1.0, epsilon, &diff);
output_result_ext ("sin^2 + cos^2 == 1", result,
res3, 1.0, diff, x, PRINT, PRINT);
@ -3963,6 +4126,7 @@ identities2_test (MATHTYPE x, MATHTYPE epsilon)
res4 = res1 / res2;
(void) &res4;
output_new_test ("sin/cos == tan");
result = check_equal (res4, res3, epsilon, &diff);
output_result_ext ("sin/cos == tan", result,
res4, res3, diff, x, PRINT, PRINT);
@ -3983,6 +4147,7 @@ identities3_test (MATHTYPE x, MATHTYPE epsilon)
res3 = res2 * res2 - res1 * res1;
(void) &res3;
output_new_test ("cosh^2 - sinh^2 == 1");
result = check_equal (res3, 1.0, epsilon, &diff);
output_result_ext ("cosh^2 - sinh^2 == 1", result,
res3, 1.0, diff, x, PRINT, PRINT);
@ -4142,7 +4307,7 @@ parse_options (int argc, char *argv[])
if (optarg)
verbose = (unsigned int) strtoul (optarg, NULL, 0);
else
verbose = 3;
verbose = 4;
break;
case 's':
verbose = 0;
@ -4156,10 +4321,12 @@ parse_options (int argc, char *argv[])
int
main (int argc, char *argv[])
{
parse_options (argc, argv);
initialize ();
printf (TEST_MSG);
basic_tests ();
acos_test ();

33
math/test-idouble.c Normal file
View File

@ -0,0 +1,33 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define FUNC(function) function
#define MATHTYPE double
#define TEST_MSG "testing double (inline functions)\n"
#define MATHCONST(x) x
#define CHOOSE(Clongdouble,Cdouble,Cfloat) Cdouble
#define PRINTF_EXPR "e"
#define TEST_INLINE
#ifdef __NO_MATH_INLINES
# undef __NO_MATH_INLINES
#endif
#include "libm-test.c"

32
math/test-ifloat.c Normal file
View File

@ -0,0 +1,32 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define FUNC(function) function ## f
#define MATHTYPE float
#define TEST_MSG "testing float (inline functions)\n"
#define MATHCONST(x) x
#define CHOOSE(Clongdouble,Cdouble,Cfloat) Cfloat
#define PRINTF_EXPR "e"
#define TEST_INLINE
#ifdef __NO_MATH_INLINES
# undef __NO_MATH_INLINES
#endif
#include "libm-test.c"

33
math/test-ildoubl.c Normal file
View File

@ -0,0 +1,33 @@
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define FUNC(function) function##l
#define MATHTYPE long double
#define TEST_MSG "testing long double (inline functions)\n"
#define MATHCONST(x) x##L
#define CHOOSE(Clongdouble,Cdouble,Cfloat) Clongdouble
#define PRINTF_EXPR "Le"
#define TEST_INLINE
#ifdef __NO_MATH_INLINES
# undef __NO_MATH_INLINES
#endif
#include "libm-test.c"

View File

@ -191,7 +191,7 @@ compile (char *__instring, char *__expbuf, __const char *__endbuf, int __eof)
}
/* Everything is ok. */
RETURN ((char *) (__expr_ptr->buffer + __expr->used));
RETURN ((char *) (__expr_ptr->buffer + __expr_ptr->used));
}
#endif

View File

@ -19,6 +19,7 @@
#include <errno.h>
#include <syslog.h>
#include <string.h>
#include <rpcsvc/nis.h>
#include <rpcsvc/nislib.h>

View File

@ -18,6 +18,8 @@
Boston, MA 02111-1307, USA. */
#include <time.h>
#include <string.h>
#include <rpcsvc/nis.h>
#include <rpcsvc/nislib.h>

View File

@ -101,8 +101,9 @@ LINE_PARSER
/* If we need the host entry in IPv6 form change it now. */
if (_res.options & RES_USE_INET6)
{
char *bufptr = data->linebuffer;
size_t buflen = (char *) data + datalen - bufptr;
char *bufptr = data->linebuffer;
/* This should be size_t */
int buflen = (char *) data + datalen - bufptr;
map_v4v6_hostent (result, &bufptr, &buflen);
}

View File

@ -159,7 +159,8 @@
}
}
if (isxdigit (name[0]) || name[0] == ':')
if ((isxdigit (name[0]) && strchr (name, ':') != NULL)
|| name[0] == ':')
{
const char *cp;
char *hostname;
@ -238,8 +239,6 @@
{
if (*--cp == '.')
break;
if (!strchr (name, ':'))
break;
/* All-IPv6-legal, no dot at the end. Fake up a
hostent as if we'd actually done a lookup. */

View File

@ -51,8 +51,7 @@ LINE_PARSER
STRING_FIELD (addr, isspace, 1);
/* Parse address. */
if ((_res.options & RES_USE_INET6)
&& inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
if (inet_pton (AF_INET6, p, entdata->host_addr) > 0)
{
result->h_addrtype = AF_INET6;
result->h_length = IN6ADDRSZ;
@ -81,14 +80,6 @@ LINE_PARSER
entdata->h_addr_ptrs[1] = NULL;
result->h_addr_list = entdata->h_addr_ptrs;
/* If we need the host entry in IPv6 form change it now. */
if (_res.options & RES_USE_INET6)
{
char *bufptr = data->linebuffer;
int buflen = (char *) data + datalen - bufptr;
map_v4v6_hostent (result, &bufptr, &buflen);
}
STRING_FIELD (result->h_name, isspace, 1);
})

View File

@ -16,6 +16,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <alloca.h>
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>

View File

@ -1 +1 @@
BIND-4.9.5-P1
BIND-4.9.6-T1A

View File

@ -281,7 +281,12 @@ b64_pton(src, target, targsize)
case 2: /* Valid, means one byte of info */
/* Skip any number of spaces. */
#ifdef _LIBC
/* To avoid warnings. */
for ( ; ch != '\0'; ch = *src++)
#else
for (NULL; ch != '\0'; ch = *src++)
#endif
if (!isspace(ch))
break;
/* Make sure there is another trailing = sign. */
@ -296,7 +301,12 @@ b64_pton(src, target, targsize)
* We know this char is an =. Is there anything but
* whitespace after it?
*/
#ifdef _LIBC
/* To avoid warnings. */
for ( ; ch != '\0'; ch = *src++)
#else
for (NULL; ch != '\0'; ch = *src++)
#endif
if (!isspace(ch))
return (-1);

View File

@ -212,6 +212,10 @@ getanswer(answer, anslen, qname, qtype)
* (i.e., with the succeeding search-domain tacked on).
*/
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
__set_h_errno (NO_RECOVERY);
return (NULL);
}
host.h_name = bp;
bp += n;
buflen -= n;
@ -256,11 +260,15 @@ getanswer(answer, anslen, qname, qtype)
/* Store alias. */
*ap++ = bp;
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
had_error++;
continue;
}
bp += n;
buflen -= n;
/* Get canonical name. */
n = strlen(tbuf) + 1; /* for the \0 */
if (n > buflen) {
if (n > buflen || n >= MAXHOSTNAMELEN) {
had_error++;
continue;
}
@ -272,14 +280,14 @@ getanswer(answer, anslen, qname, qtype)
}
if (qtype == T_PTR && type == T_CNAME) {
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
if ((n < 0) || !res_hnok(tbuf)) {
if (n < 0 || !res_hnok(tbuf)) {
had_error++;
continue;
}
cp += n;
/* Get canonical name. */
n = strlen(tbuf) + 1; /* for the \0 */
if (n > buflen) {
if (n > buflen || n >= MAXHOSTNAMELEN) {
had_error++;
continue;
}
@ -320,6 +328,10 @@ getanswer(answer, anslen, qname, qtype)
n = -1;
if (n != -1) {
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
had_error++;
break;
}
bp += n;
buflen -= n;
}
@ -328,6 +340,10 @@ getanswer(answer, anslen, qname, qtype)
host.h_name = bp;
if (_res.options & RES_USE_INET6) {
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
had_error++;
break;
}
bp += n;
buflen -= n;
map_v4v6_hostent(&host, &bp, &buflen);
@ -395,8 +411,8 @@ getanswer(answer, anslen, qname, qtype)
# endif /*RESOLVSORT*/
if (!host.h_name) {
n = strlen(qname) + 1; /* for the \0 */
if (n > buflen)
goto try_again;
if (n > buflen || n >= MAXHOSTNAMELEN)
goto no_recovery;
strcpy(bp, qname);
host.h_name = bp;
bp += n;
@ -407,8 +423,8 @@ getanswer(answer, anslen, qname, qtype)
__set_h_errno (NETDB_SUCCESS);
return (&host);
}
try_again:
__set_h_errno (TRY_AGAIN);
no_recovery:
__set_h_errno (NO_RECOVERY);
return (NULL);
}
@ -508,13 +524,12 @@ gethostbyname2(name, af)
if (!isdigit(*cp) && *cp != '.')
break;
}
if (isxdigit(name[0]) || name[0] == ':')
if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
name[0] == ':')
for (cp = name;; ++cp) {
if (!*cp) {
if (*--cp == '.')
break;
if (!strchr(name, ':'))
break;
/*
* All-IPv6-legal, no dot at the end.
* Fake up a hostent as if we'd actually
@ -719,8 +734,7 @@ _gethtent()
if (!(cp = strpbrk(p, " \t")))
goto again;
*cp++ = '\0';
if ((_res.options & RES_USE_INET6) &&
inet_pton(AF_INET6, p, host_addr) > 0) {
if (inet_pton(AF_INET6, p, host_addr) > 0) {
af = AF_INET6;
len = IN6ADDRSZ;
} else if (inet_pton(AF_INET, p, host_addr) > 0) {
@ -757,12 +771,6 @@ _gethtent()
*cp++ = '\0';
}
*q = NULL;
if (_res.options & RES_USE_INET6) {
char *bp = hostbuf;
int buflen = sizeof hostbuf;
map_v4v6_hostent(&host, &bp, &buflen);
}
__set_h_errno (NETDB_SUCCESS);
return (&host);
}

View File

@ -166,7 +166,7 @@ inet_net_pton_ipv4(src, dst, size)
goto emsgsize;
}
/* Fiery death and destruction unless we prefetched EOS. */
/* Firey death and destruction unless we prefetched EOS. */
if (ch != '\0')
goto enoent;

View File

@ -342,6 +342,11 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
* (i.e., with the succeeding search-domain tacked on).
*/
n = strlen (bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN)
{
__set_h_errno (NO_RECOVERY);
return NSS_STATUS_TRYAGAIN;
}
result->h_name = bp;
bp += n;
linebuflen -= n;
@ -396,11 +401,16 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
/* Store alias. */
*ap++ = bp;
n = strlen (bp) + 1; /* For the \0. */
if (n >= MAXHOSTNAMELEN)
{
++had_error;
continue;
}
bp += n;
linebuflen -= n;
/* Get canonical name. */
n = strlen (tbuf) + 1; /* For the \0. */
if ((size_t) n > buflen)
if ((size_t) n > buflen || n >= MAXHOSTNAMELEN)
{
++had_error;
continue;
@ -423,7 +433,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
cp += n;
/* Get canonical name. */
n = strlen (tbuf) + 1; /* For the \0. */
if ((size_t) n > buflen)
if ((size_t) n > buflen || n >= MAXHOSTNAMELEN)
{
++had_error;
continue;
@ -469,6 +479,11 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (n != -1)
{
n = strlen (bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN)
{
++had_error;
break;
}
bp += n;
linebuflen -= n;
}
@ -478,6 +493,11 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (_res.options & RES_USE_INET6)
{
n = strlen (bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN)
{
++had_error;
break;
}
bp += n;
linebuflen -= n;
map_v4v6_hostent (result, &bp, &linebuflen);
@ -549,8 +569,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (result->h_name == NULL)
{
n = strlen (qname) + 1; /* For the \0. */
if (n > linebuflen)
goto try_again;
if (n > linebuflen || n >= MAXHOSTNAMELEN)
goto no_recovery;
strcpy (bp, qname); /* Cannot overflow. */
result->h_name = bp;
bp += n;
@ -562,7 +582,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
try_again:
*h_errnop = TRY_AGAIN;
no_recovery:
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
}

View File

@ -94,7 +94,7 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
register char *dn;
register int n, c;
char *eom;
int len = -1, checked = 0;
int len = -1, checked = 0, octets = 0;
dn = exp_dn;
cp = comp_dn;
@ -108,6 +108,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
*/
switch (n & INDIR_MASK) {
case 0:
octets += (n + 1);
if (octets > MAXCDNAME)
return (-1);
if (dn != exp_dn) {
if (dn >= eom)
return (-1);
@ -179,6 +182,8 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
dn = (u_char *)exp_dn;
cp = comp_dn;
if (length > MAXCDNAME)
length = MAXCDNAME;
eob = cp + length;
lpp = cpp = NULL;
if (dnptrs != NULL) {

View File

@ -1146,40 +1146,47 @@ static u_int8_t
precsize_aton(strptr)
char **strptr;
{
unsigned int mval = 0, cmval = 0;
u_int8_t retval = 0;
register char *cp;
register int exponent;
register int mantissa;
char *cp;
int exponent = 0;
int mantissa = 0;
cp = *strptr;
while (isdigit(*cp)) {
if (mantissa == 0)
mantissa = *cp - '0';
else
exponent++;
cp++;
}
while (isdigit(*cp))
mval = mval * 10 + (*cp++ - '0');
if (*cp == '.') { /* centimeters */
if (*cp == '.') {
cp++;
if (isdigit(*cp)) {
cmval = (*cp++ - '0') * 10;
if (mantissa == 0)
mantissa = *cp - '0';
else
exponent++;
cp++;
if (isdigit(*cp)) {
cmval += (*cp++ - '0');
if (mantissa == 0)
mantissa = *cp - '0';
else
exponent++;
cp++;
}
else
exponent++;
}
}
cmval = (mval * 100) + cmval;
for (exponent = 0; exponent < 9; exponent++)
if (cmval < poweroften[exponent+1])
break;
mantissa = cmval / poweroften[exponent];
if (mantissa > 9)
mantissa = 9;
else
exponent += 2;
if (mantissa == 0)
exponent = 0;
retval = (mantissa << 4) | exponent;
*strptr = cp;
return (retval);
}

View File

@ -159,7 +159,7 @@ res_init()
register FILE *fp;
register char *cp, **pp;
register int n;
char buf[BUFSIZ];
char buf[MAXDNAME];
int nserv = 0; /* number of nameserver records read from file */
int haveenv = 0;
int havesearch = 0;

View File

@ -601,6 +601,11 @@ read_len:
if ((long) timeout.tv_sec <= 0)
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (s+1 > FD_SETSIZE) {
Perror(stderr, "s+1 > FD_SETSIZE", EMFILE);
res_close();
goto next_ns;
}
wait:
FD_ZERO(&dsmask);
FD_SET(s, &dsmask);

View File

@ -6,8 +6,7 @@
int win = 0;
void
handler (sig)
int sig;
handler (int sig)
{
printf ("Received signal %d (%s).\n", sig, strsignal(sig));
win = 1;

View File

@ -3,8 +3,7 @@
#include <stdio.h>
int
compare (a, b)
const char *a, *b;
compare (const char *a, const char *b)
{
return strcmp (*(char **) a, *(char **) b);
}

View File

@ -20,8 +20,7 @@ size_t errors = 0;
/* Complain if condition is not true. */
void
check (thing, number)
int thing, number;
check (int thing, int number)
{
if (!thing)
{
@ -40,9 +39,7 @@ char one[50];
char two[50];
int
main (argc, argv)
int argc;
char **argv;
main (void)
{
char *cp;

View File

@ -155,6 +155,10 @@ struct svc_req {
SVCXPRT *rq_xprt; /* associated transport */
};
#ifndef __DISPATCH_FN_T
#define __DISPATCH_FN_T
typedef void (*__dispatch_fn_t) __P((struct svc_req*, SVCXPRT*));
#endif
/*
* Service registration
@ -167,8 +171,7 @@ struct svc_req {
* u_long protocol; like TCP or UDP, zero means do not register
*/
extern bool_t svc_register __P ((SVCXPRT *__xprt, u_long __prog,
u_long __vers, void (*__dispatch)
__P ((struct svc_req *, SVCXPRT *)),
u_long __vers, __dispatch_fn_t __dispatch,
u_long __protocol));
/*

View File

@ -22,7 +22,7 @@
/* Set N bytes of S to 0. */
void
bzero (s, n)
bzero (s, len)
void *s;
size_t len;
{

View File

@ -17,6 +17,7 @@
Boston, MA 02111-1307, USA. */
#include <stddef.h> /* For size_t and NULL. */
#include <string.h>
/*
* Copy no more than N bytes of SRC to DEST, stopping when C is found.

View File

@ -29,9 +29,7 @@
/* If VT is not NULL, write statistics for WHO into *VT.
Return 0 for success, -1 for failure. */
static int
vtimes_one (vt, who)
struct vtimes *vt;
enum __rusage_who who;
vtimes_one (struct vtimes *vt, enum __rusage_who who)
{
if (vt != NULL)
{

View File

@ -35,55 +35,42 @@ float_type
s(__ieee754_atan2) (float_type y, float_type x)
{
float_type pi, pi_2, z;
unsigned long y_cond, x_cond;
__asm ("fmovecr%.x %#0, %0" : "=f" (pi));
__asm ("fscale%.w %#-1, %0" : "=f" (pi_2) : "0" (pi));
if (x != x || y != y)
y_cond = __m81_test (y);
x_cond = __m81_test (x);
if ((x_cond | y_cond) & __M81_COND_NAN)
z = x + y;
else if (y == 0)
else if (y_cond & __M81_COND_ZERO)
{
if (m81(__signbit) (x))
z = m81(__signbit) (y) ? -pi : pi;
if (x_cond & __M81_COND_NEG)
z = y_cond & __M81_COND_NEG ? -pi : pi;
else
z = y;
}
else if (m81(__isinf) (x))
else if (x_cond & __M81_COND_INF)
{
if (m81(__isinf) (y))
if (y_cond & __M81_COND_INF)
{
float_type pi_4;
__asm ("fscale%.w %#-2, %0" : "=f" (pi_4) : "0" (pi));
z = x > 0 ? pi_4 : 3 * pi_4;
z = x_cond & __M81_COND_NEG ? 3 * pi_4 : pi_4;
}
else
z = x > 0 ? 0 : pi;
if (m81(__signbit) (y))
z = x_cond & __M81_COND_NEG ? pi : 0;
if (y_cond & __M81_COND_NEG)
z = -z;
}
else if (m81(__isinf) (y))
z = y > 0 ? pi_2 : -pi_2;
else if (x > 0)
else if (y_cond & __M81_COND_INF)
z = y_cond & __M81_COND_NEG ? -pi_2 : pi_2;
else if (x_cond & __M81_COND_NEG)
{
if (y > 0)
if (y_cond & __M81_COND_NEG)
{
if (x > y)
z = m81(__atan) (y / x);
else
z = pi_2 - m81(__atan) (x / y);
}
else
{
if (x > -y)
z = m81(__atan) (y / x);
else
z = -pi_2 - m81(__atan) (x / y);
}
}
else
{
if (y < 0)
{
if (-x > y)
if (-x > -y)
z = -pi + m81(__atan) (y / x);
else
z = -pi_2 - m81(__atan) (x / y);
@ -96,5 +83,22 @@ s(__ieee754_atan2) (float_type y, float_type x)
z = pi_2 - m81(__atan) (x / y);
}
}
else
{
if (y_cond & __M81_COND_NEG)
{
if (x > -y)
z = m81(__atan) (y / x);
else
z = -pi_2 - m81(__atan) (x / y);
}
else
{
if (x > y)
z = m81(__atan) (y / x);
else
z = pi_2 - m81(__atan) (x / y);
}
}
return z;
}

View File

@ -199,7 +199,7 @@ $(common-objpfx)ioctls: $(sysdep_dir)/unix/snarf-ioctls \
$(sysincludedir)/sys/ioctl.h $(ioctl-includes)
$(dir $<)$(notdir $<) $(filter-out $<,$^) \
| fgrep -xv "`($(dir $<)$(notdir $<) $(termbits.h) \
$(..)termios/sys/ttydefaults.h; \
$(..)sysdeps/generic/sys/ttydefaults.h; \
echo NULL) \
| sort | uniq`" \
| sort | uniq | tr '\012' ' ' > $@-tmp

View File

@ -17,6 +17,7 @@
Boston, MA 02111-1307, USA. */
#include <sys/time.h>
#include <unistd.h>
/* Set an alarm to go off (generating a SIGALRM signal) in VALUE microseconds.
If INTERVAL is nonzero, when the alarm goes off, the timer is reset to go

View File

@ -1,6 +1,9 @@
#ifndef _NET_PPP_DEFS_H
#define _NET_PPP_DEFS_H 1
#define __need_time_t
#include <time.h>
#include <asm/types.h>
#include <linux/ppp_defs.h>

View File

@ -53,6 +53,7 @@
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <net/if.h>
__BEGIN_DECLS

View File

@ -62,10 +62,10 @@ typedef int int_least32_t;
typedef long long int int_least64_t;
/* Unsigned. */
typedef unsigned char int_least8_t;
typedef unsigned short int int_least16_t;
typedef unsigned int int_least32_t;
typedef unsigned long long int int_least64_t;
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
typedef unsigned long long int uint_least64_t;
/* Fast types. */
@ -77,10 +77,10 @@ typedef int int_fast32_t;
typedef long long int int_fast64_t;
/* Unsigned. */
typedef unsigned char int_fast8_t;
typedef unsigned int int_fast16_t;
typedef unsigned int int_fast32_t;
typedef unsigned long long int int_fast64_t;
typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
typedef unsigned long long int uint_fast64_t;
/* Limits of integral types. */
@ -122,21 +122,21 @@ typedef unsigned long long int int_fast64_t;
/* Minimum of fast signed integral types having a minimum size. */
#define INT_LEAST8_MIN (-128)
#define INT_LEAST16_MIN (-2147483647-1)
#define INT_LEAST32_MIN (-2147483647-1)
#define INT_LEAST64_MIN (-9223372036854775807LL-1)
#define INT_FAST8_MIN (-128)
#define INT_FAST16_MIN (-2147483647-1)
#define INT_FAST32_MIN (-2147483647-1)
#define INT_FAST64_MIN (-9223372036854775807LL-1)
/* Maximum of fast signed integral types having a minimum size. */
#define INT_LEAST8_MAX (127)
#define INT_LEAST16_MAX (2147483647)
#define INT_LEAST32_MAX (2147483647)
#define INT_LEAST64_MAX (9223372036854775807LL)
#define INT_FAST8_MAX (127)
#define INT_FAST16_MAX (2147483647)
#define INT_FAST32_MAX (2147483647)
#define INT_FAST64_MAX (9223372036854775807LL)
/* Maximum of fast unsigned integral types having a minimum size. */
#define UINT_LEAST8_MAX (255U)
#define UINT_LEAST16_MAX (4294967295U)
#define UINT_LEAST32_MAX (4294967295U)
#define UINT_LEAST64_MAX (18446744073709551615uLL)
#define UINT_FAST8_MAX (255U)
#define UINT_FAST16_MAX (4294967295U)
#define UINT_FAST32_MAX (4294967295U)
#define UINT_FAST64_MAX (18446744073709551615uLL)
/* Minimum for most efficient signed integral types. */

View File

@ -62,10 +62,10 @@ typedef int int_least32_t;
typedef long int int_least64_t;
/* Unsigned. */
typedef unsigned char int_least8_t;
typedef unsigned short int int_least16_t;
typedef unsigned int int_least32_t;
typedef unsigned long int int_least64_t;
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
typedef unsigned long int uint_least64_t;
/* Fast types. */
@ -77,10 +77,10 @@ typedef int int_fast32_t;
typedef long int int_fast64_t;
/* Unsigned. */
typedef unsigned char int_fast8_t;
typedef unsigned int int_fast16_t;
typedef unsigned int int_fast32_t;
typedef unsigned long int int_fast64_t;
typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
typedef unsigned long int uint_fast64_t;
/* Limits of integral types. */
@ -122,21 +122,21 @@ typedef unsigned long int int_fast64_t;
/* Minimum of fast signed integral types having a minimum size. */
#define INT_LEAST8_MIN (-128)
#define INT_LEAST16_MIN (-2147483647-1)
#define INT_LEAST32_MIN (-2147483647-1)
#define INT_LEAST64_MIN (-9223372036854775807L-1)
#define INT_FAST8_MIN (-128)
#define INT_FAST16_MIN (-2147483647-1)
#define INT_FAST32_MIN (-2147483647-1)
#define INT_FAST64_MIN (-9223372036854775807L-1)
/* Maximum of fast signed integral types having a minimum size. */
#define INT_LEAST8_MAX (127)
#define INT_LEAST16_MAX (2147483647)
#define INT_LEAST32_MAX (2147483647)
#define INT_LEAST64_MAX (9223372036854775807L)
#define INT_FAST8_MAX (127)
#define INT_FAST16_MAX (2147483647)
#define INT_FAST32_MAX (2147483647)
#define INT_FAST64_MAX (9223372036854775807L)
/* Maximum of fast unsigned integral types having a minimum size. */
#define UINT_LEAST8_MAX (255U)
#define UINT_LEAST16_MAX (4294967295U)
#define UINT_LEAST32_MAX (4294967295U)
#define UINT_LEAST64_MAX (18446744073709551615uL)
#define UINT_FAST8_MAX (255U)
#define UINT_FAST16_MAX (4294967295U)
#define UINT_FAST32_MAX (4294967295U)
#define UINT_FAST64_MAX (18446744073709551615uL)
/* Minimum for most efficient signed integral types. */

View File

@ -137,7 +137,7 @@ extern int __tz_compute __P ((time_t timer, const struct tm *tm));
# if ! HAVE_LOCALTIME_R
# if ! HAVE_TM_GMTOFF
/* Approximate gmtime_r as best we can in its absence. */
# define gmtime_r my_gmtime_r
# define gmtime_r my_gmtime_r
static struct tm *gmtime_r __P ((const time_t *, struct tm *));
static struct tm *
gmtime_r (t, tp)
@ -208,7 +208,7 @@ static const char zeroes[16] = "0000000000000000";
# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
#endif
#define add(n, f) \
#define add(n, f) \
do \
{ \
int _n = (n); \
@ -231,7 +231,7 @@ static const char zeroes[16] = "0000000000000000";
i += _incr; \
} while (0)
#define cpy(n, s) \
#define cpy(n, s) \
add ((n), \
if (to_lowcase) \
memcpy_lowcase (p, (s), _n); \

View File

@ -541,7 +541,10 @@ strptime_internal (buf, format, tm, decided)
break;
case 'Y':
/* Match year including century number. */
get_number (0, INT_MAX);
if (sizeof (time_t) > 4)
get_number (0, 9999);
else
get_number (0, 2036);
tm->tm_year = val - 1900;
break;
case 'Z':