aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1996-08-26 10:28:45 +0000
committerUlrich Drepper <drepper@redhat.com>1996-08-26 10:28:45 +0000
commitdcf0671d905200c449f92ead6cf43c184637a0d5 (patch)
tree91dc217311db41e89545d487b991865a6433205e
parentUpdate. (diff)
downloadglibc-dcf0671d905200c449f92ead6cf43c184637a0d5.tar.gz
glibc-dcf0671d905200c449f92ead6cf43c184637a0d5.tar.bz2
glibc-dcf0671d905200c449f92ead6cf43c184637a0d5.zip
handle password file locking.cvs/libc-960826
-rw-r--r--NEWS8
-rw-r--r--configure.in2
-rw-r--r--elf/dl-error.c9
-rw-r--r--elf/dl-open.c8
-rw-r--r--elf/dlerror.c8
-rw-r--r--elf/rtld.c15
-rw-r--r--misc/syslog.c6
-rw-r--r--resolv/res_debug.c12
-rw-r--r--shadow/Makefile3
-rw-r--r--shadow/lckpwdf.c181
-rw-r--r--shadow/shadow.h13
-rw-r--r--sysdeps/generic/ftime.c13
-rw-r--r--sysdeps/generic/setfpucw.c5
-rw-r--r--sysdeps/i386/fpu_control.h4
-rw-r--r--sysdeps/m68k/dl-machine.h2
-rw-r--r--sysdeps/posix/gettimeofday.c21
-rw-r--r--sysdeps/unix/sysv/linux/init-first.c31
-rw-r--r--time/gmtime.c12
-rw-r--r--time/strftime.c40
19 files changed, 321 insertions, 72 deletions
diff --git a/NEWS b/NEWS
index edb07b8330..76a4272569 100644
--- a/NEWS
+++ b/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;
diff --git a/configure.in b/configure.in
index 631a035e92..a2668b9ff9 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/elf/dl-error.c b/elf/dl-error.c
index 737bba7421..2eaa7e03d1 100644
--- a/elf/dl-error.c
+++ b/elf/dl-error.c
@@ -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);
}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 40b5224725..76f6329762 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -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
diff --git a/elf/dlerror.c b/elf/dlerror.c
index 4ec5037de4..663207d708 100644
--- a/elf/dlerror.c
+++ b/elf/dlerror.c
@@ -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;
diff --git a/elf/rtld.c b/elf/rtld.c
index 9f13124207..be71e88c3c 100644
--- a/elf/rtld.c
+++ b/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;
diff --git a/misc/syslog.c b/misc/syslog.c
index 3a39c4317a..de159da9ee 100644
--- a/misc/syslog.c
+++ b/misc/syslog.c
@@ -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)
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index dfb3b4706f..bb314bcaa0 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -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);
}
diff --git a/shadow/Makefile b/shadow/Makefile
index 943881f1f1..614f7afdd4 100644
--- a/shadow/Makefile
+++ b/shadow/Makefile
@@ -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
diff --git a/shadow/lckpwdf.c b/shadow/lckpwdf.c
new file mode 100644
index 0000000000..fb1c4b2e5e
--- /dev/null
+++ b/shadow/lckpwdf.c
@@ -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. */
+}
diff --git a/shadow/shadow.h b/shadow/shadow.h
index 88199a9856..b1a4c82b4e 100644
--- a/shadow/shadow.h
+++ b/shadow/shadow.h
@@ -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 */
diff --git a/sysdeps/generic/ftime.c b/sysdeps/generic/ftime.c
index 76e9276483..600e959245 100644
--- a/sysdeps/generic/ftime.c
+++ b/sysdeps/generic/ftime.c
@@ -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;
diff --git a/sysdeps/generic/setfpucw.c b/sysdeps/generic/setfpucw.c
index 7b09a68b55..5654c942b0 100644
--- a/sysdeps/generic/setfpucw.c
+++ b/sysdeps/generic/setfpucw.c
@@ -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);
}
diff --git a/sysdeps/i386/fpu_control.h b/sysdeps/i386/fpu_control.h
index 706dea3d6d..7944b1a5ee 100644
--- a/sysdeps/i386/fpu_control.h
+++ b/sysdeps/i386/fpu_control.h
@@ -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;
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index f36b9ce2f4..8b9872c15a 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -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.
diff --git a/sysdeps/posix/gettimeofday.c b/sysdeps/posix/gettimeofday.c
index a4bb38a41c..c3b8108258 100644
--- a/sysdeps/posix/gettimeofday.c
+++ b/sysdeps/posix/gettimeofday.c
@@ -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;
}
diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c
index feff028a28..ae163bcd49 100644
--- a/sysdeps/unix/sysv/linux/init-first.c
+++ b/sysdeps/unix/sysv/linux/init-first.c
@@ -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 ();
diff --git a/time/gmtime.c b/time/gmtime.c
index 93fba659be..364b4c9262 100644
--- a/time/gmtime.c
+++ b/time/gmtime.c
@@ -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);
diff --git a/time/strftime.c b/time/strftime.c
index 214f82f488..129fd1412c 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -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)
{