mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
handle password file locking.
This commit is contained in:
8
NEWS
8
NEWS
@ -1,4 +1,4 @@
|
|||||||
GNU C Library NEWS -- history of user-visible changes. 24 June 1996
|
GNU C Library NEWS -- history of user-visible changes. 25 August 1996
|
||||||
|
|
||||||
Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
|
Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
|
||||||
See the end for copying conditions.
|
See the end for copying conditions.
|
||||||
@ -20,8 +20,8 @@ Version 2.0
|
|||||||
of many files which contained only symbol aliases, reducing the size of
|
of many files which contained only symbol aliases, reducing the size of
|
||||||
the source and the compiled library; many other files were renamed to
|
the source and the compiled library; many other files were renamed to
|
||||||
less cryptic names previously occupied by the symbol alias files.
|
less cryptic names previously occupied by the symbol alias files.
|
||||||
There is a new header file <elf.h> and new library `-lelf' for
|
There is a new header file <elf.h> for programs which operate on
|
||||||
programs which operate on files in the ELF format.
|
files in the ELF format.
|
||||||
|
|
||||||
* Converted to Autoconf version 2, so `configure' has more options.
|
* Converted to Autoconf version 2, so `configure' has more options.
|
||||||
Run `configure --help' to see the details.
|
Run `configure --help' to see the details.
|
||||||
@ -104,7 +104,7 @@ Version 2.0
|
|||||||
* The new header file <fts.h> and suite of functions simplify programs that
|
* The new header file <fts.h> and suite of functions simplify programs that
|
||||||
operate on directory trees. This code comes from 4.4 BSD.
|
operate on directory trees. This code comes from 4.4 BSD.
|
||||||
|
|
||||||
* The resolver code has been updated from the BIND 4.9.4-T3B release.
|
* The resolver code has been updated from the BIND 4.9.5-T1A release.
|
||||||
|
|
||||||
* The new function `malloc_find_object_address' finds the starting address
|
* The new function `malloc_find_object_address' finds the starting address
|
||||||
of a malloc'd block, given any address within the block;
|
of a malloc'd block, given any address within the block;
|
||||||
|
@ -483,6 +483,8 @@ fi
|
|||||||
AC_CACHE_CHECK(for ld --no-whole-archive, libc_cv_ld_no_whole_archive, [dnl
|
AC_CACHE_CHECK(for ld --no-whole-archive, libc_cv_ld_no_whole_archive, [dnl
|
||||||
cat > conftest.c <<\EOF
|
cat > conftest.c <<\EOF
|
||||||
_start () {}
|
_start () {}
|
||||||
|
int __eh_pc;
|
||||||
|
__throw () {}
|
||||||
EOF
|
EOF
|
||||||
dnl No \ in command here because it ends up inside ''.
|
dnl No \ in command here because it ends up inside ''.
|
||||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS
|
if AC_TRY_COMMAND([${CC-cc} $CFLAGS
|
||||||
|
@ -46,8 +46,13 @@ _dl_signal_error (int errcode,
|
|||||||
|
|
||||||
if (catch)
|
if (catch)
|
||||||
{
|
{
|
||||||
/* We are inside _dl_catch_error. Return to it. */
|
/* We are inside _dl_catch_error. Return to it. We have to
|
||||||
catch->errstring = errstring;
|
duplicate the error string since it might be allocated on the
|
||||||
|
stack. */
|
||||||
|
size_t len = strlen (errstring) + 1;
|
||||||
|
catch->errstring = malloc (len);
|
||||||
|
if (catch->errstring != NULL)
|
||||||
|
memcpy (catch->errstring, errstring, len);
|
||||||
catch->objname = objname;
|
catch->objname = objname;
|
||||||
longjmp (catch->env, errcode ?: -1);
|
longjmp (catch->env, errcode ?: -1);
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,11 @@ extern void _dl_start (void); weak_extern (_dl_start)
|
|||||||
|
|
||||||
extern int __libc_multiple_libcs; /* Defined in init-first.c. */
|
extern int __libc_multiple_libcs; /* Defined in init-first.c. */
|
||||||
|
|
||||||
|
extern int __libc_argc;
|
||||||
|
extern char **__libc_argv;
|
||||||
|
extern char **__libc_envp;
|
||||||
|
|
||||||
|
|
||||||
size_t _dl_global_scope_alloc;
|
size_t _dl_global_scope_alloc;
|
||||||
|
|
||||||
struct link_map *
|
struct link_map *
|
||||||
@ -136,7 +141,8 @@ _dl_open (const char *file, int mode)
|
|||||||
|
|
||||||
/* Run the initializer functions of new objects. */
|
/* Run the initializer functions of new objects. */
|
||||||
while (init = _dl_init_next (new))
|
while (init = _dl_init_next (new))
|
||||||
(*(void (*) (void)) init) ();
|
(*(void (*) (int, char **, char **)) init) (__libc_argc, __libc_argv,
|
||||||
|
__libc_envp);
|
||||||
|
|
||||||
if (dl_start_ptr == NULL)
|
if (dl_start_ptr == NULL)
|
||||||
/* We must be the static _dl_open in libc.a because ld.so.1 is not
|
/* We must be the static _dl_open in libc.a because ld.so.1 is not
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* dlerror -- Return error detail for failing <dlfcn.h> functions.
|
/* dlerror -- Return error detail for failing <dlfcn.h> functions.
|
||||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -58,6 +58,7 @@ dlerror (void)
|
|||||||
? NULL : buf);
|
? NULL : buf);
|
||||||
|
|
||||||
/* Reset the error indicator. */
|
/* Reset the error indicator. */
|
||||||
|
free (last_errstring);
|
||||||
last_errstring = NULL;
|
last_errstring = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -65,6 +66,11 @@ dlerror (void)
|
|||||||
int
|
int
|
||||||
_dlerror_run (void (*operate) (void))
|
_dlerror_run (void (*operate) (void))
|
||||||
{
|
{
|
||||||
|
if (last_errstring != NULL)
|
||||||
|
/* Free the error string from the last failed command. This can
|
||||||
|
happen if `dlerror' was not run after an error was found. */
|
||||||
|
free (last_errstring);
|
||||||
|
|
||||||
last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
|
last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
|
||||||
operate);
|
operate);
|
||||||
return last_errstring != NULL;
|
return last_errstring != NULL;
|
||||||
|
15
elf/rtld.c
15
elf/rtld.c
@ -204,12 +204,15 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
{
|
{
|
||||||
l = _dl_map_object (NULL, _dl_argv[0], lt_library);
|
l = _dl_map_object (NULL, _dl_argv[0], lt_library);
|
||||||
}
|
}
|
||||||
const char *err_str = NULL;
|
char *err_str = NULL;
|
||||||
const char *obj_name __attribute__ ((unused));
|
const char *obj_name __attribute__ ((unused));
|
||||||
|
|
||||||
(void) _dl_catch_error (&err_str, &obj_name, doit);
|
(void) _dl_catch_error (&err_str, &obj_name, doit);
|
||||||
if (err_str != NULL)
|
if (err_str != NULL)
|
||||||
_exit (EXIT_FAILURE);
|
{
|
||||||
|
free (err_str);
|
||||||
|
_exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
l = _dl_map_object (NULL, _dl_argv[0], lt_library);
|
l = _dl_map_object (NULL, _dl_argv[0], lt_library);
|
||||||
@ -395,7 +398,8 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||||
&_dl_default_scope[2],
|
&_dl_default_scope[2],
|
||||||
"argument", 0);
|
"argument",
|
||||||
|
DL_LOOKUP_NOPLT);
|
||||||
char buf[20], *bp;
|
char buf[20], *bp;
|
||||||
buf[sizeof buf - 1] = '\0';
|
buf[sizeof buf - 1] = '\0';
|
||||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||||
@ -488,8 +492,9 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
dynamic linker. There is no additional initialization
|
dynamic linker. There is no additional initialization
|
||||||
required for the ABI-compliant dynamic linker. */
|
required for the ABI-compliant dynamic linker. */
|
||||||
|
|
||||||
(*(void (*) (void)) (_dl_rtld_map.l_addr +
|
(*(void (*) (int, char **, char**))
|
||||||
_dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
|
(_dl_rtld_map.l_addr + _dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr))
|
||||||
|
(0, NULL, NULL);
|
||||||
|
|
||||||
/* Clear the field so a future dlopen won't run it again. */
|
/* Clear the field so a future dlopen won't run it again. */
|
||||||
_dl_rtld_map.l_info[DT_INIT] = NULL;
|
_dl_rtld_map.l_info[DT_INIT] = NULL;
|
||||||
|
@ -96,6 +96,7 @@ vsyslog(pri, fmt, ap)
|
|||||||
register const char *fmt;
|
register const char *fmt;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
{
|
{
|
||||||
|
struct tm now_tm;
|
||||||
time_t now;
|
time_t now;
|
||||||
int fd;
|
int fd;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
@ -126,10 +127,11 @@ vsyslog(pri, fmt, ap)
|
|||||||
#ifdef USE_IN_LIBIO
|
#ifdef USE_IN_LIBIO
|
||||||
f->_IO_write_ptr += strftime (f->_IO_write_ptr,
|
f->_IO_write_ptr += strftime (f->_IO_write_ptr,
|
||||||
f->_IO_write_end - f->_IO_write_ptr,
|
f->_IO_write_end - f->_IO_write_ptr,
|
||||||
"%h %e %T ", localtime (&now));
|
"%h %e %T ",
|
||||||
|
__localtime_r (&now, &now_tm));
|
||||||
#else
|
#else
|
||||||
f->__bufp += strftime (f->__bufp, f->__put_limit - f->__bufp,
|
f->__bufp += strftime (f->__bufp, f->__put_limit - f->__bufp,
|
||||||
"%h %e %T ", localtime (&now));
|
"%h %e %T ", __localtime_r (&now, &mow_tm));
|
||||||
#endif
|
#endif
|
||||||
msgoff = ftell (f);
|
msgoff = ftell (f);
|
||||||
if (LogTag == NULL)
|
if (LogTag == NULL)
|
||||||
|
@ -1491,13 +1491,13 @@ __p_secstodate (secs)
|
|||||||
{
|
{
|
||||||
static char output[15]; /* YYYYMMDDHHMMSS and null */
|
static char output[15]; /* YYYYMMDDHHMMSS and null */
|
||||||
time_t clock = secs;
|
time_t clock = secs;
|
||||||
struct tm *time;
|
struct tm time;
|
||||||
|
|
||||||
time = gmtime(&clock);
|
__gmtime_r(&clock, &time);
|
||||||
time->tm_year += 1900;
|
time.tm_year += 1900;
|
||||||
time->tm_mon += 1;
|
time.tm_mon += 1;
|
||||||
sprintf(output, "%04d%02d%02d%02d%02d%02d",
|
sprintf(output, "%04d%02d%02d%02d%02d%02d",
|
||||||
time->tm_year, time->tm_mon, time->tm_mday,
|
time.tm_year, time.tm_mon, time.tm_mday,
|
||||||
time->tm_hour, time->tm_min, time->tm_sec);
|
time.tm_hour, time.tm_min, time.tm_sec);
|
||||||
return (output);
|
return (output);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ subdir := shadow
|
|||||||
|
|
||||||
headers = shadow.h
|
headers = shadow.h
|
||||||
routines = getspent getspnam sgetspent fgetspent putspent \
|
routines = getspent getspnam sgetspent fgetspent putspent \
|
||||||
getspent_r getspnam_r sgetspent_r fgetspent_r
|
getspent_r getspnam_r sgetspent_r fgetspent_r \
|
||||||
|
lckpwdf
|
||||||
|
|
||||||
|
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
181
shadow/lckpwdf.c
Normal file
181
shadow/lckpwdf.c
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/* lckpwdf - handle locking of password file.
|
||||||
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
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
|
||||||
|
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 <libc-lock.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Name of the lock file. */
|
||||||
|
#define PWD_LOCKFILE "/var/lock/lock.pwd"
|
||||||
|
|
||||||
|
/* How long to wait for getting the lock before returning with an
|
||||||
|
error. */
|
||||||
|
#define TIMEOUT 15 /* sec */
|
||||||
|
|
||||||
|
|
||||||
|
/* File descriptor for lock file. */
|
||||||
|
static int lock_fd = -1;
|
||||||
|
|
||||||
|
/* Prevent problems in multithreaded program by using mutex. */
|
||||||
|
__libc_lock_define_initialized (static, lock)
|
||||||
|
|
||||||
|
|
||||||
|
/* Prototypes for local functions. */
|
||||||
|
static void noop_handler __P ((int __sig));
|
||||||
|
|
||||||
|
|
||||||
|
/* We cannot simply return in error cases. We have to close the file
|
||||||
|
and perhaps restore the signal handler. */
|
||||||
|
#define RETURN_CLOSE_FD(code) \
|
||||||
|
do { \
|
||||||
|
if ((code) < 0 && lock_fd >= 0) \
|
||||||
|
{ \
|
||||||
|
close (lock_fd); \
|
||||||
|
lock_fd = -1; \
|
||||||
|
} \
|
||||||
|
__libc_lock_unlock (lock); \
|
||||||
|
return (code); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RETURN_RESTORE_HANDLER(code) \
|
||||||
|
do { \
|
||||||
|
/* Restore old action handler for alarm. We don't need to know \
|
||||||
|
about the current one. */ \
|
||||||
|
sigaction (SIGALRM, &saved_act, NULL); \
|
||||||
|
RETURN_CLOSE_FD (code); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RETURN_CLEAR_ALARM(code) \
|
||||||
|
do { \
|
||||||
|
/* Clear alarm. */ \
|
||||||
|
alarm (0); \
|
||||||
|
/* Restore old set of handled signals. We don't need to know \
|
||||||
|
about the current one.*/ \
|
||||||
|
sigprocmask (SIG_SETMASK, &saved_set, NULL); \
|
||||||
|
RETURN_RESTORE_HANDLER (code); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
__lckpwdf ()
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
sigset_t saved_set; /* Saved set of caught signals. */
|
||||||
|
struct sigaction saved_act; /* Saved signal action. */
|
||||||
|
sigset_t new_set; /* New set of caught signals. */
|
||||||
|
struct sigaction new_act; /* New signal action. */
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (lock_fd != -1)
|
||||||
|
/* Still locked by own process. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Prevent problems caused by multiple threads. */
|
||||||
|
__libc_lock_lock (lock);
|
||||||
|
|
||||||
|
lock_fd = open (PWD_LOCKFILE, O_WRONLY | O_CREAT, 0600);
|
||||||
|
if (lock_fd == -1)
|
||||||
|
/* Cannot create lock file. */
|
||||||
|
RETURN_CLOSE_FD (-1);
|
||||||
|
|
||||||
|
/* Make sure file gets correctly closed when process finished. */
|
||||||
|
flags = fcntl (lock_fd, F_GETFD, 0);
|
||||||
|
if (flags == -1)
|
||||||
|
/* Cannot get file flags. */
|
||||||
|
RETURN_CLOSE_FD (-1);
|
||||||
|
flags |= FD_CLOEXEC; /* Close on exit. */
|
||||||
|
if (fcntl (lock_fd, F_SETFD, flags) < 0)
|
||||||
|
/* Cannot set new flags. */
|
||||||
|
RETURN_CLOSE_FD (-1);
|
||||||
|
|
||||||
|
/* Now we have to get exclusive write access. Since multiple
|
||||||
|
process could try this we won't stop when it first fails.
|
||||||
|
Instead we set a timeout for the system call. Once the timer
|
||||||
|
expires it is likely that there are some problems which cannot be
|
||||||
|
resolved by waiting.
|
||||||
|
|
||||||
|
It is important that we don't change the signal state. We must
|
||||||
|
restore the old signal behaviour. */
|
||||||
|
memset (&new_act, '\0', sizeof (struct sigaction));
|
||||||
|
new_act.sa_handler = noop_handler;
|
||||||
|
sigfillset (&new_act.sa_mask);
|
||||||
|
new_act.sa_flags = 0ul;
|
||||||
|
|
||||||
|
/* Install new action handler for alarm and save old. */
|
||||||
|
if (sigaction (SIGALRM, &new_act, &saved_act) < 0)
|
||||||
|
/* Cannot install signal handler. */
|
||||||
|
RETURN_CLOSE_FD (-1);
|
||||||
|
|
||||||
|
/* Now make sure the alarm signal is not blocked. */
|
||||||
|
sigemptyset (&new_set);
|
||||||
|
sigaddset (&new_set, SIGALRM);
|
||||||
|
if (sigprocmask (SIG_UNBLOCK, &new_set, &saved_set) < 0)
|
||||||
|
RETURN_RESTORE_HANDLER (-1);
|
||||||
|
|
||||||
|
/* Start timer. If we cannot get the lock in the specified time we
|
||||||
|
get a signal. */
|
||||||
|
alarm (TIMEOUT);
|
||||||
|
|
||||||
|
/* Try to get the lock. */
|
||||||
|
result = flock (lock_fd, LOCK_EX);
|
||||||
|
|
||||||
|
RETURN_CLEAR_ALARM (result);
|
||||||
|
}
|
||||||
|
weak_alias (__lckpwdf, lckpwdf)
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
__ulckpwdf ()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (lock_fd == -1)
|
||||||
|
/* There is no lock set. */
|
||||||
|
result = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Prevent problems caused by multiple threads. */
|
||||||
|
__libc_lock_lock (&lock);
|
||||||
|
|
||||||
|
result = close (lock_fd);
|
||||||
|
|
||||||
|
/* Mark descriptor as unused. */
|
||||||
|
lock_fd = -1;
|
||||||
|
|
||||||
|
/* Clear mutex. */
|
||||||
|
__libc_lock_unlock (lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
weak_alias (__ulckpwdf, ulckpwdf)
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
noop_handler (sig)
|
||||||
|
int sig;
|
||||||
|
{
|
||||||
|
/* We simply return which makes the `flock' call return with an error. */
|
||||||
|
}
|
@ -46,8 +46,8 @@ struct spwd
|
|||||||
the password. */
|
the password. */
|
||||||
__time_t sp_inact; /* Number of days the account may be
|
__time_t sp_inact; /* Number of days the account may be
|
||||||
inactive. */
|
inactive. */
|
||||||
__time_t sp_expire; /* Number of days since 700101 until account
|
__time_t sp_expire; /* Number of days since 1970-01-01 until
|
||||||
expires. */
|
account expires. */
|
||||||
unsigned long int sp_flag; /* Reserved. */
|
unsigned long int sp_flag; /* Reserved. */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,6 +103,15 @@ extern struct spwd *fgetspent_r __P ((FILE *__stream,
|
|||||||
char *__buffer, int __buflen));
|
char *__buffer, int __buflen));
|
||||||
#endif /* reentrant */
|
#endif /* reentrant */
|
||||||
|
|
||||||
|
|
||||||
|
/* Protect password file against multi writers. */
|
||||||
|
extern int __lckpwdf __P ((void));
|
||||||
|
extern int lckpwdf __P ((void));
|
||||||
|
|
||||||
|
/* Unlock password file. */
|
||||||
|
extern int __ulckpwdf __P ((void));
|
||||||
|
extern int ulckpwdf __P ((void));
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* shadow.h */
|
#endif /* shadow.h */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1994 Free Software Foundation, Inc.
|
/* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -25,19 +25,18 @@ ftime (timebuf)
|
|||||||
struct timeb *timebuf;
|
struct timeb *timebuf;
|
||||||
{
|
{
|
||||||
int save = errno;
|
int save = errno;
|
||||||
struct tm *tp;
|
struct tm tp;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (time (&timebuf->time) == (time_t) -1 && errno != 0)
|
if (time (&timebuf->time) == (time_t) -1 && errno != 0)
|
||||||
return -1;
|
return -1;
|
||||||
timebuf->millitm = 0;
|
timebuf->millitm = 0;
|
||||||
|
|
||||||
tp = localtime (&timebuf->time);
|
if (__localtime_r (&timebuf->time, &tp) == NULL)
|
||||||
if (tp == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
timebuf->timezone = tp->tm_gmtoff / 60;
|
timebuf->timezone = tp.tm_gmtoff / 60;
|
||||||
timebuf->dstflag = tp->tm_isdst;
|
timebuf->dstflag = tp.tm_isdst;
|
||||||
|
|
||||||
errno = save;
|
errno = save;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -29,5 +29,8 @@ __setfpucw (fpu_control_t set)
|
|||||||
|
|
||||||
/* Preserve the reserved bits, and set the rest as the user
|
/* Preserve the reserved bits, and set the rest as the user
|
||||||
specified (or the default, if the user gave zero). */
|
specified (or the default, if the user gave zero). */
|
||||||
_FPU_SETCW ((cw & _FPU_RESERVED) | (set & ~_FPU_RESERVED));
|
cw &= _FPU_RESERVED;
|
||||||
|
cw |= set & ~_FPU_RESERVED;
|
||||||
|
|
||||||
|
_FPU_SETCW (cw);
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,8 @@ Boston, MA 02111-1307, USA. */
|
|||||||
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
|
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
|
||||||
|
|
||||||
/* Macros for accessing the hardware control word. */
|
/* Macros for accessing the hardware control word. */
|
||||||
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (cw))
|
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
|
||||||
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (cw))
|
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
|
||||||
|
|
||||||
/* Default control word set at startup. */
|
/* Default control word set at startup. */
|
||||||
extern fpu_control_t __fpu_control;
|
extern fpu_control_t __fpu_control;
|
||||||
|
@ -175,7 +175,7 @@ _dl_start_user:
|
|||||||
| Loop to call _dl_init_next for the next initializer.
|
| Loop to call _dl_init_next for the next initializer.
|
||||||
jra 0b
|
jra 0b
|
||||||
1: | Clear the startup flag.
|
1: | Clear the startup flag.
|
||||||
move.l #0, _dl_starting_up@GOT(%a5)
|
clr.l _dl_starting_up@GOT(%a5)
|
||||||
| Pass our finalizer function to the user in %a1.
|
| Pass our finalizer function to the user in %a1.
|
||||||
move.l _dl_fini@GOT(%a5), %a1
|
move.l _dl_fini@GOT(%a5), %a1
|
||||||
| Initialize %fp with the stack pointer.
|
| Initialize %fp with the stack pointer.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
|
/* Copyright (C) 1991, 92, 94, 95, 96 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
|
|||||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||||
Cambridge, MA 02139, USA. */
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include <ansidecl.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -32,8 +31,9 @@ Cambridge, MA 02139, USA. */
|
|||||||
putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled.
|
putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled.
|
||||||
Returns 0 on success, -1 on errors. */
|
Returns 0 on success, -1 on errors. */
|
||||||
int
|
int
|
||||||
DEFUN(__gettimeofday, (tv, tz),
|
__gettimeofday (tv, tz)
|
||||||
struct timeval *tv AND struct timezone *tz)
|
struct timeval *tv;
|
||||||
|
struct timezone *tz;
|
||||||
{
|
{
|
||||||
if (tv == NULL)
|
if (tv == NULL)
|
||||||
{
|
{
|
||||||
@ -46,16 +46,17 @@ DEFUN(__gettimeofday, (tv, tz),
|
|||||||
|
|
||||||
if (tz != NULL)
|
if (tz != NULL)
|
||||||
{
|
{
|
||||||
CONST time_t timer = tv->tv_sec;
|
const time_t timer = tv->tv_sec;
|
||||||
CONST struct tm *tm;
|
struct tm tm;
|
||||||
|
const struct tm *tmp;
|
||||||
|
|
||||||
CONST long int save_timezone = __timezone;
|
const long int save_timezone = __timezone;
|
||||||
CONST long int save_daylight = __daylight;
|
const long int save_daylight = __daylight;
|
||||||
char *save_tzname[2];
|
char *save_tzname[2];
|
||||||
save_tzname[0] = __tzname[0];
|
save_tzname[0] = __tzname[0];
|
||||||
save_tzname[1] = __tzname[1];
|
save_tzname[1] = __tzname[1];
|
||||||
|
|
||||||
tm = localtime (&timer);
|
tmp = localtime (&timer, &tm);
|
||||||
|
|
||||||
tz->tz_minuteswest = __timezone / 60;
|
tz->tz_minuteswest = __timezone / 60;
|
||||||
tz->tz_dsttime = __daylight;
|
tz->tz_dsttime = __daylight;
|
||||||
@ -65,7 +66,7 @@ DEFUN(__gettimeofday, (tv, tz),
|
|||||||
__tzname[0] = save_tzname[0];
|
__tzname[0] = save_tzname[0];
|
||||||
__tzname[1] = save_tzname[1];
|
__tzname[1] = save_tzname[1];
|
||||||
|
|
||||||
if (tm == NULL)
|
if (tmp == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,21 +36,30 @@ weak_extern (_dl_starting_up)
|
|||||||
used in the process. Safe assumption if initializer never runs. */
|
used in the process. Safe assumption if initializer never runs. */
|
||||||
int __libc_multiple_libcs = 1;
|
int __libc_multiple_libcs = 1;
|
||||||
|
|
||||||
|
/* Remember the command line argument and enviroment contents for
|
||||||
|
later calls of initializers for dynamic libraries. */
|
||||||
|
int __libc_argc;
|
||||||
|
char **__libc_argv;
|
||||||
|
char **__libc_envp;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init (void *data)
|
init (void *data)
|
||||||
{
|
{
|
||||||
extern int __personality (int);
|
extern int __personality (int);
|
||||||
|
|
||||||
int argc = *(long *)data;
|
|
||||||
char **argv = (char **)data + 1;
|
|
||||||
char **envp = &argv[argc + 1];
|
|
||||||
|
|
||||||
|
|
||||||
__libc_multiple_libcs = &_dl_starting_up && ! _dl_starting_up;
|
__libc_multiple_libcs = &_dl_starting_up && ! _dl_starting_up;
|
||||||
|
|
||||||
|
|
||||||
/* We must not call `personality' twice. */
|
/* We must not call `personality' twice. */
|
||||||
if (!__libc_multiple_libcs)
|
if (!__libc_multiple_libcs)
|
||||||
{
|
{
|
||||||
|
/* The argument we got points to the values describing the
|
||||||
|
command line argument etc. */
|
||||||
|
__libc_argc = *(int *)data;
|
||||||
|
__libc_argv = (char **)data + 1;
|
||||||
|
__libc_envp = &__libc_argv[__libc_argc + 1];
|
||||||
|
|
||||||
/* The `personality' system call takes one argument that chooses
|
/* The `personality' system call takes one argument that chooses
|
||||||
the "personality", i.e. the set of system calls and such. We
|
the "personality", i.e. the set of system calls and such. We
|
||||||
must make this call first thing to disable emulation of some
|
must make this call first thing to disable emulation of some
|
||||||
@ -61,9 +70,17 @@ init (void *data)
|
|||||||
/* Set the FPU control word to the proper default value. */
|
/* Set the FPU control word to the proper default value. */
|
||||||
__setfpucw (__fpu_control);
|
__setfpucw (__fpu_control);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The argument we got points to the values describing the
|
||||||
|
command line argument etc. */
|
||||||
|
__libc_argc = *((int *)data)++;
|
||||||
|
__libc_argv = *((char ***)data)++;
|
||||||
|
__libc_envp = *(char ***)data;
|
||||||
|
}
|
||||||
|
|
||||||
__environ = envp;
|
__environ = __libc_envp;
|
||||||
__libc_init (argc, argv, envp);
|
__libc_init (__libc_argc, __libc_argv, __libc_envp);
|
||||||
|
|
||||||
#ifdef PIC
|
#ifdef PIC
|
||||||
__libc_global_ctors ();
|
__libc_global_ctors ();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
|
/* Copyright (C) 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
|
|||||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||||
Cambridge, MA 02139, USA. */
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include <ansidecl.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -25,16 +24,19 @@ extern struct tm _tmbuf;
|
|||||||
|
|
||||||
/* Return the `struct tm' representation of *T in UTC. */
|
/* Return the `struct tm' representation of *T in UTC. */
|
||||||
struct tm *
|
struct tm *
|
||||||
DEFUN(gmtime, (t), CONST time_t *t)
|
gmtime (t)
|
||||||
|
const time_t *t;
|
||||||
{
|
{
|
||||||
return __gmtime_r (t, &_tmbuf);
|
return __gmtime_r (t, &_tmbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return the `struct tm' representation of *T in UTC,
|
/* Return the `struct tm' representation of *T in UTC,
|
||||||
using *TP to store the result. */
|
using *TP to store the result. */
|
||||||
struct tm *
|
struct tm *
|
||||||
DEFUN(__gmtime_r, (t, tp),
|
__gmtime_r (t, tp)
|
||||||
CONST time_t *t AND struct tm *tp)
|
const time_t *t;
|
||||||
|
struct tm *tp;
|
||||||
{
|
{
|
||||||
__offtime (t, 0L, tp);
|
__offtime (t, 0L, tp);
|
||||||
|
|
||||||
|
@ -470,27 +470,37 @@ strftime (s, maxsize, format, tp)
|
|||||||
case 'z':
|
case 'z':
|
||||||
{
|
{
|
||||||
struct tm tml = *tp;
|
struct tm tml = *tp;
|
||||||
time_t t = mktime (&tml);
|
|
||||||
struct tm tmg;
|
struct tm tmg;
|
||||||
|
time_t t;
|
||||||
|
time_t offset = 0;
|
||||||
int diff;
|
int diff;
|
||||||
|
|
||||||
tml = *localtime (&t); /* Canonicalize the local time. */
|
t = __mktime_internal (&tml, __localtime_r, &offset);
|
||||||
tmg = *gmtime (&t);
|
|
||||||
|
|
||||||
/* Compute the difference. */
|
/* Canonicalize the local time. */
|
||||||
diff = tml.tm_min - tmg.tm_min;
|
if (t == (time_t) -1 || __localtime_r (&t, &tml) == NULL)
|
||||||
diff += 60 * (tml.tm_hour - tmg.tm_hour);
|
/* We didn't managed to get the local time. Assume it
|
||||||
|
GMT as a reasonable default value. */
|
||||||
if (tml.tm_mon != tmg.tm_mon)
|
diff = 0;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* We assume no timezone differs from UTC by more than
|
__gmtime_r (&t, &tmg);
|
||||||
+- 23 hours. This should be safe. */
|
|
||||||
if (tmg.tm_mday == 1)
|
/* Compute the difference. */
|
||||||
tml.tm_mday = 0;
|
diff = tml.tm_min - tmg.tm_min;
|
||||||
else /* tml.tm_mday == 1 */
|
diff += 60 * (tml.tm_hour - tmg.tm_hour);
|
||||||
tmg.tm_mday = 0;
|
|
||||||
|
if (tml.tm_mon != tmg.tm_mon)
|
||||||
|
{
|
||||||
|
/* We assume no timezone differs from UTC by more
|
||||||
|
than +- 23 hours. This should be safe. */
|
||||||
|
if (tmg.tm_mday == 1)
|
||||||
|
tml.tm_mday = 0;
|
||||||
|
else /* tml.tm_mday == 1 */
|
||||||
|
tmg.tm_mday = 0;
|
||||||
|
}
|
||||||
|
diff += 1440 * (tml.tm_mday - tmg.tm_mday);
|
||||||
}
|
}
|
||||||
diff += 1440 * (tml.tm_mday - tmg.tm_mday);
|
|
||||||
|
|
||||||
if (diff < 0)
|
if (diff < 0)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user