newlib-cygwin/winsup/cygwin/libc/bsdlib.cc

342 lines
7.6 KiB
C++
Raw Normal View History

/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* CV 2003-09-10: Cygwin specific changes applied. Code simplified just
* for Cygwin alone.
*/
#include "winsup.h"
#include <stdio.h>
#include <stdlib.h>
#include <utmp.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
2011-02-02 23:17:14 +08:00
#include <err.h>
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
* exceptions.cc (set_signal_mask): Redefine to not pass by address. Report calculated mask in debugging output. * sigproc.h (set_signal_mask): Reflect above change in declaration. * path.cc (mount_item::build_win32): Take path apart before feeding it to fnmunge. Throughout, change use of _reent_winsup()-> to _my_tls.locals. instead. Throughout, remove obsolete MT_SAFE/_CYG_THREAD_FAILSAFE considerations. Througout, add cygtls.h include. * Makefile.in (DLL_OFILES): Add cygtls.o. Add some more objects to the -fomit-frame-pointer list. * acconfig.h: Remove obsolete settings. * config.h.in: Ditto. * bsdlib.cc: Add cygtls.h include. * configure.in: Remove --enable-extra-threadsafe-checking. * configure: Regenerate. * cygtls.h (_local_storage): New struct renamed from _winsup_t (sic). (_threadinfo:local_clib): Add new field. (_threadinfo::locals): Ditto. (_threadinfo::init_thread): Accept second _reent * argument. (_threadinfo::call): Define as regparm. (CYGTLS_PADSIZE): Remove unnecessary slop. (_getreent): Define as a macro. * thread.h: Remove _CYG_THREAD_FAILSAFE and MT_SAFE stuff. (_winsup_t): Move to cygtls.h. (ResourceLocks::ResourceLocks): Eliminate empty constructor. (MTinterface::reents): Eliminate. (MTinterface::thread_self_key): Eliminate. (MTinterface::MTinterface): Eliminate. * dcrt0.cc: Include stdio.h for _impure_ptr initialization. (do_global_ctors): Remove run_ctors_p (sic) considerations. Don't call atexit here. (__main): Initialize destructors for user here. (dll_crt0_1): Accept a dummy argument. Don't call init_thread here. Don't set _impure_ptr here. Call do_global_ctors after more things have been initialized. (_dll_crt0): Define zeros buffer as max of needed size of CYGTLS_PADSIZE so that it can be used for two purposes while minimizing stack usage. Initialize _impure_ptr specifically, for speed. Call dll_crt0_1 with buffer argument. (cygwin_dll_init): Call dll_crt0_1 with dummy argument. * dtable.cc (dtable::find_unused_handle): Remove call to AssertResourceOwner. * exceptions.cc: Move _threadinfo stuff to new file. * cygtls.cc: New file. * gentls_offsets: Accommodate increasing complexity of cygtls.h. * hires.h (hires_base::~hires_base): Remove. * init.cc (dll_entry): Remove setting of reents. * thread.cc: Remove syslog.h include. (__getreent): Simplify to use _my_tls. (_reent_winsup): Delete. (AssertResourceOwner): Delete. (MTinterface::Init): Remove setting of _clib and _winsup, with all that entails. (MTinterface::fixup_after_fork): Ditto. (pthread::thread_init_wrapper): Ditto. Also remove call to set_tls_self_pointer. (pthread::set_tls_self_pointer): Eliminate. (pthread::get_tls_self_pointer): Just return _my_tls.tid; (__reent_t::init_clib): Eliminate. * tlsoffsets.h: Regenerate.
2003-12-24 00:26:31 +08:00
#include "cygtls.h"
extern "C" int
daemon (int nochdir, int noclose)
{
int fd;
switch (fork ())
{
case -1:
return -1;
case 0:
break;
default:
/* This sleep avoids a race condition which kills the
2013-04-23 17:44:36 +08:00
child process if parent is started by a service process.
FIXME: Is that still true? */
Sleep (1000L);
_exit (0);
}
if (setsid () == -1)
return -1;
if (!nochdir)
chdir ("/");
if (!noclose && (fd = open (_PATH_DEVNULL, O_RDWR, 0)) >= 0)
{
dup2 (fd, STDIN_FILENO);
dup2 (fd, STDOUT_FILENO);
dup2 (fd, STDERR_FILENO);
if (fd > 2)
close (fd);
}
return 0;
}
extern "C" int
login_tty (int fd)
{
/* If setsid fails, FreeBSD uses the current sid returned by getsid(0),
then calls tcsetsid, which we don't provide (just as Linux doesn't).
tcsetsid only uses the sid to check against the value returned by
getsid(0). So, either way, that check will not fail and we can
simply ignore the return value from setsid and just perform the
ioctl call tcsetsid does. */
setsid ();
if (ioctl (fd, TIOCSCTTY, NULL) == -1)
return -1;
dup2 (fd, STDIN_FILENO);
dup2 (fd, STDOUT_FILENO);
dup2 (fd, STDERR_FILENO);
if (fd > 2)
close (fd);
return 0;
}
extern "C" int
openpty (int *amaster, int *aslave, char *name, const struct termios *termp,
const struct winsize *winp)
{
int master, slave;
char pts[TTY_NAME_MAX];
if ((master = open ("/dev/ptmx", O_RDWR | O_NOCTTY)) >= 0)
{
grantpt (master);
unlockpt (master);
2013-04-23 17:44:36 +08:00
__ptsname (pts, cygheap->fdtab[master]->get_minor ());
revoke (pts);
if ((slave = open (pts, O_RDWR | O_NOCTTY)) >= 0)
{
if (amaster)
*amaster = master;
if (name)
strcpy (name, pts);
if (termp)
tcsetattr (slave, TCSAFLUSH, termp);
if (winp)
ioctl (slave, TIOCSWINSZ, (char *) winp);
/* The man page doesn't say that aslave can be NULL but we have
allowed it for years. As of 2011-11-08 we now avoid a handle
leak in this case. */
if (aslave)
*aslave = slave;
else
close (slave);
return 0;
}
close (master);
}
set_errno (ENOENT);
return -1;
}
extern "C" int
forkpty (int *amaster, char *name, const struct termios *termp,
const struct winsize *winp)
{
int master, slave, pid;
if (openpty (&master, &slave, name, termp, winp) == -1)
return -1;
switch (pid = fork ())
{
case -1:
close (master);
close (slave);
return -1;
case 0:
close (master);
login_tty (slave);
return 0;
}
if (amaster)
*amaster = master;
close (slave);
return pid;
}
extern "C" char *__progname;
static void
_vwarnx (const char *fmt, va_list ap)
{
fprintf (stderr, "%s: ", __progname);
vfprintf (stderr, fmt, ap);
}
extern "C" void
vwarn (const char *fmt, va_list ap)
{
_vwarnx (fmt, ap);
fprintf (stderr, ": %s", strerror (get_errno ()));
fputc ('\n', stderr);
}
extern "C" void
vwarnx (const char *fmt, va_list ap)
{
_vwarnx (fmt, ap);
fputc ('\n', stderr);
}
extern "C" void
warn (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vwarn (fmt, ap);
va_end (ap);
}
extern "C" void
warnx (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vwarnx (fmt, ap);
va_end (ap);
}
extern "C" void
verr (int eval, const char *fmt, va_list ap)
{
vwarn (fmt, ap);
exit (eval);
}
extern "C" void
verrx (int eval, const char *fmt, va_list ap)
{
vwarnx (fmt, ap);
exit (eval);
}
extern "C" void
err (int eval, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vwarn (fmt, ap);
va_end (ap);
exit (eval);
}
extern "C" void
errx (int eval, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
vwarnx (fmt, ap);
va_end (ap);
exit (eval);
}
extern "C" const char *
getprogname (void)
{
return __progname;
}
extern "C" void
setprogname (const char *newprogname)
{
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
__try
{
/* Per BSD man page, setprogname keeps a pointer to the last
path component of the argument. It does *not* copy the
argument before. */
__progname = strrchr (newprogname, '/');
if (__progname)
++__progname;
else
__progname = (char *)newprogname;
}
* Throughout, use __try/__except/__endtry blocks, rather than myfault handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
2014-08-22 17:21:33 +08:00
__except (EFAULT) {}
__endtry
}
extern "C" void
setproctitle (const char *fmt, ...)
{
char buf[MAX_PATH]; /* Max len of a new proc title */
va_list ap;
int len;
char *tmp;
if (__argv0_orig)
{
tmp = __argv[0];
__argv[0] = __argv0_orig;
__argv0_orig = NULL;
cfree (tmp);
}
if (fmt)
{
if (fmt[0] == '-') /* Skip program name prefix. */
{
fmt++;
len = 0;
}
else /* Print program name heading for grep. */
len = snprintf (buf, sizeof buf, "%s: ", getprogname ());
va_start (ap, fmt);
vsnprintf (buf + len, sizeof buf - len, fmt, ap);
va_end (ap);
tmp = (char *) cstrdup1 (buf);
__argv0_orig = __argv[0];
__argv[0] = tmp;
}
}
extern "C" void
logwtmp (const char *line, const char *user, const char *host)
{
struct utmp ut;
memset (&ut, 0, sizeof ut);
ut.ut_type = USER_PROCESS;
ut.ut_pid = getpid ();
if (line)
strncpy (ut.ut_line, line, sizeof ut.ut_line);
time (&ut.ut_time);
if (user)
strncpy (ut.ut_user, user, sizeof ut.ut_user);
if (host)
strncpy (ut.ut_host, host, sizeof ut.ut_host);
updwtmp (_PATH_WTMP, &ut);
}
extern "C" void
login (const struct utmp *ut)
{
pututline (ut);
endutent ();
updwtmp (_PATH_WTMP, ut);
}
extern "C" int
logout (const char *line)
{
struct utmp ut_buf, *ut;
memset (&ut_buf, 0, sizeof ut_buf);
strncpy (ut_buf.ut_line, line, sizeof ut_buf.ut_line);
setutent ();
ut = getutline (&ut_buf);
if (ut)
{
ut->ut_type = DEAD_PROCESS;
memset (ut->ut_user, 0, sizeof ut->ut_user);
memset (ut->ut_host, 0, sizeof ut->ut_host);
time (&ut->ut_time);
debug_printf ("set logout time for %s", line);
pututline (ut);
endutent ();
return 1;
}
return 0;
}