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

312 lines
6.7 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)
{
char *fdname;
int newfd;
if (setsid () == -1)
return -1;
if ((fdname = ttyname (fd)))
{
if (fd != STDIN_FILENO)
close (STDIN_FILENO);
if (fd != STDOUT_FILENO)
close (STDOUT_FILENO);
if (fd != STDERR_FILENO)
close (STDERR_FILENO);
newfd = open (fdname, O_RDWR);
close (newfd);
}
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:
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)
{
myfault efault;
if (!efault.faulted (EFAULT))
{
/* 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;
}
}
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;
}