mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 14:50:05 +00:00
handle password file locking.
This commit is contained in:
parent
4884d0f03c
commit
dcf0671d90
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.
|
||||
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
|
||||
the source and the compiled library; many other files were renamed to
|
||||
less cryptic names previously occupied by the symbol alias files.
|
||||
There is a new header file <elf.h> and new library `-lelf' for
|
||||
programs which operate on files in the ELF format.
|
||||
There is a new header file <elf.h> for programs which operate on
|
||||
files in the ELF format.
|
||||
|
||||
* Converted to Autoconf version 2, so `configure' has more options.
|
||||
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
|
||||
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
|
||||
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
|
||||
cat > conftest.c <<\EOF
|
||||
_start () {}
|
||||
int __eh_pc;
|
||||
__throw () {}
|
||||
EOF
|
||||
dnl No \ in command here because it ends up inside ''.
|
||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS
|
||||
|
@ -46,8 +46,13 @@ _dl_signal_error (int errcode,
|
||||
|
||||
if (catch)
|
||||
{
|
||||
/* We are inside _dl_catch_error. Return to it. */
|
||||
catch->errstring = errstring;
|
||||
/* We are inside _dl_catch_error. Return to it. We have to
|
||||
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;
|
||||
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_argc;
|
||||
extern char **__libc_argv;
|
||||
extern char **__libc_envp;
|
||||
|
||||
|
||||
size_t _dl_global_scope_alloc;
|
||||
|
||||
struct link_map *
|
||||
@ -136,7 +141,8 @@ _dl_open (const char *file, int mode)
|
||||
|
||||
/* Run the initializer functions of new objects. */
|
||||
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)
|
||||
/* 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.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -58,6 +58,7 @@ dlerror (void)
|
||||
? NULL : buf);
|
||||
|
||||
/* Reset the error indicator. */
|
||||
free (last_errstring);
|
||||
last_errstring = NULL;
|
||||
return ret;
|
||||
}
|
||||
@ -65,6 +66,11 @@ dlerror (void)
|
||||
int
|
||||
_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,
|
||||
operate);
|
||||
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);
|
||||
}
|
||||
const char *err_str = NULL;
|
||||
char *err_str = NULL;
|
||||
const char *obj_name __attribute__ ((unused));
|
||||
|
||||
(void) _dl_catch_error (&err_str, &obj_name, doit);
|
||||
if (err_str != NULL)
|
||||
_exit (EXIT_FAILURE);
|
||||
{
|
||||
free (err_str);
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
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;
|
||||
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||
&_dl_default_scope[2],
|
||||
"argument", 0);
|
||||
"argument",
|
||||
DL_LOOKUP_NOPLT);
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\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
|
||||
required for the ABI-compliant dynamic linker. */
|
||||
|
||||
(*(void (*) (void)) (_dl_rtld_map.l_addr +
|
||||
_dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
|
||||
(*(void (*) (int, char **, char**))
|
||||
(_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. */
|
||||
_dl_rtld_map.l_info[DT_INIT] = NULL;
|
||||
|
@ -96,6 +96,7 @@ vsyslog(pri, fmt, ap)
|
||||
register const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
struct tm now_tm;
|
||||
time_t now;
|
||||
int fd;
|
||||
FILE *f;
|
||||
@ -126,10 +127,11 @@ vsyslog(pri, fmt, ap)
|
||||
#ifdef USE_IN_LIBIO
|
||||
f->_IO_write_ptr += strftime (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
|
||||
f->__bufp += strftime (f->__bufp, f->__put_limit - f->__bufp,
|
||||
"%h %e %T ", localtime (&now));
|
||||
"%h %e %T ", __localtime_r (&now, &mow_tm));
|
||||
#endif
|
||||
msgoff = ftell (f);
|
||||
if (LogTag == NULL)
|
||||
|
@ -1491,13 +1491,13 @@ __p_secstodate (secs)
|
||||
{
|
||||
static char output[15]; /* YYYYMMDDHHMMSS and null */
|
||||
time_t clock = secs;
|
||||
struct tm *time;
|
||||
struct tm time;
|
||||
|
||||
time = gmtime(&clock);
|
||||
time->tm_year += 1900;
|
||||
time->tm_mon += 1;
|
||||
__gmtime_r(&clock, &time);
|
||||
time.tm_year += 1900;
|
||||
time.tm_mon += 1;
|
||||
sprintf(output, "%04d%02d%02d%02d%02d%02d",
|
||||
time->tm_year, time->tm_mon, time->tm_mday,
|
||||
time->tm_hour, time->tm_min, time->tm_sec);
|
||||
time.tm_year, time.tm_mon, time.tm_mday,
|
||||
time.tm_hour, time.tm_min, time.tm_sec);
|
||||
return (output);
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ subdir := shadow
|
||||
|
||||
headers = shadow.h
|
||||
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
|
||||
|
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. */
|
||||
__time_t sp_inact; /* Number of days the account may be
|
||||
inactive. */
|
||||
__time_t sp_expire; /* Number of days since 700101 until account
|
||||
expires. */
|
||||
__time_t sp_expire; /* Number of days since 1970-01-01 until
|
||||
account expires. */
|
||||
unsigned long int sp_flag; /* Reserved. */
|
||||
};
|
||||
|
||||
@ -103,6 +103,15 @@ extern struct spwd *fgetspent_r __P ((FILE *__stream,
|
||||
char *__buffer, int __buflen));
|
||||
#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
|
||||
|
||||
#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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -25,19 +25,18 @@ ftime (timebuf)
|
||||
struct timeb *timebuf;
|
||||
{
|
||||
int save = errno;
|
||||
struct tm *tp;
|
||||
struct tm tp;
|
||||
|
||||
errno = 0;
|
||||
if (time (&timebuf->time) == (time_t) -1 && errno != 0)
|
||||
return -1;
|
||||
timebuf->millitm = 0;
|
||||
|
||||
tp = localtime (&timebuf->time);
|
||||
if (tp == NULL)
|
||||
|
||||
if (__localtime_r (&timebuf->time, &tp) == NULL)
|
||||
return -1;
|
||||
|
||||
timebuf->timezone = tp->tm_gmtoff / 60;
|
||||
timebuf->dstflag = tp->tm_isdst;
|
||||
timebuf->timezone = tp.tm_gmtoff / 60;
|
||||
timebuf->dstflag = tp.tm_isdst;
|
||||
|
||||
errno = save;
|
||||
return 0;
|
||||
|
@ -29,5 +29,8 @@ __setfpucw (fpu_control_t set)
|
||||
|
||||
/* Preserve the reserved bits, and set the rest as the user
|
||||
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__)));
|
||||
|
||||
/* Macros for accessing the hardware control word. */
|
||||
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (cw))
|
||||
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (cw))
|
||||
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
|
||||
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
|
||||
|
||||
/* Default control word set at startup. */
|
||||
extern fpu_control_t __fpu_control;
|
||||
|
@ -175,7 +175,7 @@ _dl_start_user:
|
||||
| Loop to call _dl_init_next for the next initializer.
|
||||
jra 0b
|
||||
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.
|
||||
move.l _dl_fini@GOT(%a5), %a1
|
||||
| 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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <ansidecl.h>
|
||||
#include <errno.h>
|
||||
#include <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.
|
||||
Returns 0 on success, -1 on errors. */
|
||||
int
|
||||
DEFUN(__gettimeofday, (tv, tz),
|
||||
struct timeval *tv AND struct timezone *tz)
|
||||
__gettimeofday (tv, tz)
|
||||
struct timeval *tv;
|
||||
struct timezone *tz;
|
||||
{
|
||||
if (tv == NULL)
|
||||
{
|
||||
@ -46,16 +46,17 @@ DEFUN(__gettimeofday, (tv, tz),
|
||||
|
||||
if (tz != NULL)
|
||||
{
|
||||
CONST time_t timer = tv->tv_sec;
|
||||
CONST struct tm *tm;
|
||||
const time_t timer = tv->tv_sec;
|
||||
struct tm tm;
|
||||
const struct tm *tmp;
|
||||
|
||||
CONST long int save_timezone = __timezone;
|
||||
CONST long int save_daylight = __daylight;
|
||||
const long int save_timezone = __timezone;
|
||||
const long int save_daylight = __daylight;
|
||||
char *save_tzname[2];
|
||||
save_tzname[0] = __tzname[0];
|
||||
save_tzname[1] = __tzname[1];
|
||||
|
||||
tm = localtime (&timer);
|
||||
tmp = localtime (&timer, &tm);
|
||||
|
||||
tz->tz_minuteswest = __timezone / 60;
|
||||
tz->tz_dsttime = __daylight;
|
||||
@ -65,7 +66,7 @@ DEFUN(__gettimeofday, (tv, tz),
|
||||
__tzname[0] = save_tzname[0];
|
||||
__tzname[1] = save_tzname[1];
|
||||
|
||||
if (tm == NULL)
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -36,21 +36,30 @@ weak_extern (_dl_starting_up)
|
||||
used in the process. Safe assumption if initializer never runs. */
|
||||
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
|
||||
init (void *data)
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
/* We must not call `personality' twice. */
|
||||
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", i.e. the set of system calls and such. We
|
||||
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. */
|
||||
__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;
|
||||
__libc_init (argc, argv, envp);
|
||||
__environ = __libc_envp;
|
||||
__libc_init (__libc_argc, __libc_argv, __libc_envp);
|
||||
|
||||
#ifdef PIC
|
||||
__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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <ansidecl.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
|
||||
@ -25,16 +24,19 @@ extern struct tm _tmbuf;
|
||||
|
||||
/* Return the `struct tm' representation of *T in UTC. */
|
||||
struct tm *
|
||||
DEFUN(gmtime, (t), CONST time_t *t)
|
||||
gmtime (t)
|
||||
const time_t *t;
|
||||
{
|
||||
return __gmtime_r (t, &_tmbuf);
|
||||
}
|
||||
|
||||
|
||||
/* Return the `struct tm' representation of *T in UTC,
|
||||
using *TP to store the result. */
|
||||
struct tm *
|
||||
DEFUN(__gmtime_r, (t, tp),
|
||||
CONST time_t *t AND struct tm *tp)
|
||||
__gmtime_r (t, tp)
|
||||
const time_t *t;
|
||||
struct tm *tp;
|
||||
{
|
||||
__offtime (t, 0L, tp);
|
||||
|
||||
|
@ -470,27 +470,37 @@ strftime (s, maxsize, format, tp)
|
||||
case 'z':
|
||||
{
|
||||
struct tm tml = *tp;
|
||||
time_t t = mktime (&tml);
|
||||
struct tm tmg;
|
||||
time_t t;
|
||||
time_t offset = 0;
|
||||
int diff;
|
||||
|
||||
tml = *localtime (&t); /* Canonicalize the local time. */
|
||||
tmg = *gmtime (&t);
|
||||
t = __mktime_internal (&tml, __localtime_r, &offset);
|
||||
|
||||
/* Compute the difference. */
|
||||
diff = tml.tm_min - tmg.tm_min;
|
||||
diff += 60 * (tml.tm_hour - tmg.tm_hour);
|
||||
|
||||
if (tml.tm_mon != tmg.tm_mon)
|
||||
/* Canonicalize the local time. */
|
||||
if (t == (time_t) -1 || __localtime_r (&t, &tml) == NULL)
|
||||
/* We didn't managed to get the local time. Assume it
|
||||
GMT as a reasonable default value. */
|
||||
diff = 0;
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
__gmtime_r (&t, &tmg);
|
||||
|
||||
/* Compute the difference. */
|
||||
diff = tml.tm_min - tmg.tm_min;
|
||||
diff += 60 * (tml.tm_hour - tmg.tm_hour);
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user