e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
cb22561995-10-11Fredrik Hübinette (Hubbe) #include "global.h"
85f59e1998-01-08Fredrik Hübinette (Hubbe) #include "fdlib.h"
6e27c91998-02-19Fredrik Hübinette (Hubbe) #include "fd_control.h"
cb22561995-10-11Fredrik Hübinette (Hubbe) #include "svalue.h" #include "interpret.h" #include "stralloc.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "constants.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
cb22561995-10-11Fredrik Hübinette (Hubbe) #include "backend.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
a29e021996-10-15Fredrik Hübinette (Hubbe) #include "callback.h"
85f59e1998-01-08Fredrik Hübinette (Hubbe) #include "mapping.h" #include "threads.h" #include "signal_handler.h" #include "module_support.h"
0d52dd1998-01-16Fredrik Hübinette (Hubbe) #include "operators.h" #include "builtin_functions.h"
5f06241999-04-11Fredrik Hübinette (Hubbe) #include "main.h"
f010202011-11-16Tobias S. Josefowitz #include "time_stuff.h"
7112872015-10-18Martin Nilsson 
cb22561995-10-11Fredrik Hübinette (Hubbe) #include <signal.h>
7112872015-10-18Martin Nilsson #include <errno.h>
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
f087c41998-02-04Fredrik Hübinette (Hubbe) #ifdef HAVE_PASSWD_H # include <passwd.h> #endif #ifdef HAVE_GROUP_H # include <group.h> #endif #ifdef HAVE_PWD_H # include <pwd.h> #endif #ifdef HAVE_GRP_H # include <grp.h> #endif
857ea72000-08-17Henrik Grubbström (Grubba) #ifdef HAVE_SYS_ID_H # include <sys/id.h> #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) #ifdef HAVE_WINBASE_H #include <winbase.h> #endif
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_WAIT_H
15a4361995-11-15Fredrik Hübinette (Hubbe) #include <sys/wait.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
cb22561995-10-11Fredrik Hübinette (Hubbe) 
cf2a151996-04-13Fredrik Hübinette (Hubbe) #ifdef HAVE_UNISTD_H #include <unistd.h> #endif
d4debf1997-05-19Henrik Grubbström (Grubba) #ifdef HAVE_STRINGS_H #include <strings.h> #endif
51e8842015-10-18Martin Nilsson 
52ad0d1998-11-23Marcus Comstedt #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif
27205b2003-11-25Jonas Wallden #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif
bfd94e2000-10-18Henrik Grubbström (Grubba) #ifdef HAVE_POLL #ifdef HAVE_POLL_H #include <poll.h> #endif /* HAVE_POLL_H */ #ifdef HAVE_SYS_POLL_H #include <sys/poll.h> #endif /* HAVE_SYS_POLL_H */ #endif /* HAVE_POLL */
62e3f52000-12-06Marcus Comstedt #ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> #endif
06dda52002-08-21Marcus Comstedt #ifdef HAVE_SYS_TERMIO_H # include <sys/termio.h> #endif
6abd862017-08-27Henrik Grubbström (Grubba) #ifdef HAVE_TERMIOS_H # include <termios.h> #elif defined(HAVE_SYS_TERMIOS_H) /* NB: Deprecated by <termios.h> above. */
06dda52002-08-21Marcus Comstedt # include <sys/termios.h> #endif
b143542003-02-28Henrik Grubbström (Grubba) #ifdef HAVE_SYS_PTRACE_H #include <sys/ptrace.h> #endif
d0d7962005-12-02Henrik Grubbström (Grubba) #ifdef HAVE_SYS_PARAM_H /* Needed for <sys/user.h> on OpenBSD. */ #include <sys/param.h> #endif
4499d52003-03-06Henrik Grubbström (Grubba) #ifdef HAVE_SYS_USER_H
fe2c202003-04-14Henrik Grubbström (Grubba) /* NOTE: On AIX 4.x with COFF32 format, this file * includes <syms.h>, which has incompatible * definitions of T_INT and T_FLOAT. * Use PIKE_T_INT and PIKE_T_FLOAT in this file! * /grubba 2003-04-14. */
4499d52003-03-06Henrik Grubbström (Grubba) #include <sys/user.h> #endif
0c95942018-01-12Stephen R. van den Berg #ifdef __amigaos__ #define timeval amigaos_timeval #include <exec/types.h> #include <dos/dos.h> #include <dos/dostags.h> #include <dos/exall.h> #ifdef __amigaos4__ #include <interfaces/dos.h> #include <inline4/dos.h> #else #include <clib/dos_protos.h> #include <inline/dos.h> #endif #undef timeval #endif
531c172002-05-11Martin Nilsson #define fp Pike_fp
52ad0d1998-11-23Marcus Comstedt 
cb22561995-10-11Fredrik Hübinette (Hubbe) #ifdef NSIG #define MAX_SIGNALS NSIG #else #define MAX_SIGNALS 256
15fafe1999-11-16Henrik Grubbström (Grubba) #define NSIG 256
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif #define SIGNAL_BUFFER 16384
85f59e1998-01-08Fredrik Hübinette (Hubbe) #define WAIT_BUFFER 4096
cb22561995-10-11Fredrik Hübinette (Hubbe) 
ae2cc61998-05-19Fredrik Hübinette (Hubbe) #ifdef HAVE_UNION_WAIT #define WAITSTATUSTYPE union wait #else #define WAITSTATUSTYPE int #endif
5096d71998-05-17Henrik Grubbström (Grubba) #ifndef WEXITSTATUS #ifdef HAVE_UNION_WAIT #define WEXITSTATUS(x) ((x).w_retcode) #else /* !HAVE_UNION_WAIT */ #define WEXITSTATUS(x) (((x)>>8)&0xff) #endif /* HAVE_UNION_WAIT */ #endif /* !WEXITSTATUS */
b143542003-02-28Henrik Grubbström (Grubba) #ifndef WUNTRACED #define WUNTRACED 0 #endif /* !WUNTRACED */
75c9d52003-03-01Henrik Grubbström (Grubba) #ifdef HAVE_PTRACE /* BSDs have different names for these constants...
dad69b2003-03-01Henrik Grubbström (Grubba)  *
4499d52003-03-06Henrik Grubbström (Grubba)  * ... and so does HPUX... * * And Solaris 2.9 and later don't name them at all... * * Requests 0 - 9 are standardized by AT&T/SVID as follows: * * PTRACE_TRACEME 0 Enter trace mode. Stop at exec() and signals. * PTRACE_PEEKTEXT 1 Read a word from the text area. * PTRACE_PEEKDATA 2 Read a word from the data area. * PTRACE_PEEKUSER 3 Read a word from the user area. * PTRACE_POKETEXT 4 Set a word in the text area. * PTRACE_POKEDATA 5 Set a word in the data area. * PTRACE_POKEUSER 6 Set a word in the user area. * PTRACE_CONT 7 Continue process with specified signal. * PTRACE_KILL 8 Exit process. * PTRACE_SINGLESTEP 9 Execute a single instruction. * * NB: In Solaris 2.x ptrace() is simulated by libc.
75c9d52003-03-01Henrik Grubbström (Grubba)  */
dad69b2003-03-01Henrik Grubbström (Grubba) #ifndef PTRACE_TRACEME #ifdef PT_TRACE_ME
4499d52003-03-06Henrik Grubbström (Grubba) /* BSD */
dad69b2003-03-01Henrik Grubbström (Grubba) #define PTRACE_TRACEME PT_TRACE_ME
4499d52003-03-06Henrik Grubbström (Grubba) #elif defined(PT_SETTRC) /* HPUX */ #define PTRACE_TRACEME PT_SETTRC
dad69b2003-03-01Henrik Grubbström (Grubba) #else #define PTRACE_TRACEME 0 #endif #endif
4499d52003-03-06Henrik Grubbström (Grubba) #ifndef PTRACE_PEEKUSER #ifdef PT_READ_U /* BSD */ #define PTRACE_PEEKUSER PT_READ_U #elif defined(PT_RUAREA) /* HPUX */ #define PTRACE_PEEKUSER PT_RUAREA #else #define PTRACE_PEEKUSER 3 #endif #endif
75c9d52003-03-01Henrik Grubbström (Grubba) #ifndef PTRACE_CONT #ifdef PT_CONTINUE
4499d52003-03-06Henrik Grubbström (Grubba) /* BSD */
75c9d52003-03-01Henrik Grubbström (Grubba) #define PTRACE_CONT PT_CONTINUE
4499d52003-03-06Henrik Grubbström (Grubba) #elif defined(PT_CONTIN) /* HPUX */ #define PTRACE_CONT PT_CONTIN
75c9d52003-03-01Henrik Grubbström (Grubba) #else #define PTRACE_CONT 7 #endif #endif
dad69b2003-03-01Henrik Grubbström (Grubba) #ifndef PTRACE_KILL #ifdef PT_KILL
4499d52003-03-06Henrik Grubbström (Grubba) /* BSD */
dad69b2003-03-01Henrik Grubbström (Grubba) #define PTRACE_KILL PT_KILL
4499d52003-03-06Henrik Grubbström (Grubba) #elif defined(PT_EXIT) #define PTRACE_KILL PT_EXIT
75c9d52003-03-01Henrik Grubbström (Grubba) #else
dad69b2003-03-01Henrik Grubbström (Grubba) #define PTRACE_KILL 8
75c9d52003-03-01Henrik Grubbström (Grubba) #endif #endif
4499d52003-03-06Henrik Grubbström (Grubba) #ifndef PTRACE_TAKES_FOUR_ARGS /* HPUX and SunOS 4 have a fifth argument "addr2". */ #define ptrace(R,P,A,D) ptrace(R,P,A,D,NULL) #endif
d574b82003-03-27Henrik Grubbström (Grubba) #ifdef PTRACE_ADDR_TYPE_IS_POINTER #define CAST_TO_PTRACE_ADDR(X) ((void *)(ptrdiff_t)(X)) #else /* !PTRACE_ADDR_TYPE_IS_POINTER */ #define CAST_TO_PTRACE_ADDR(X) ((ptrdiff_t)(X)) #endif /* PTRACE_ADDR_TYPE_IS_POINTER */
75c9d52003-03-01Henrik Grubbström (Grubba) #endif /* HAVE_PTRACE */
6465ab2002-04-26Henrik Grubbström (Grubba) /* Number of EBADF's before the set_close_on_exec() loop terminates. */ #ifndef PIKE_BADF_LIMIT #define PIKE_BADF_LIMIT 1024 #endif /* !PIKE_BADF_LIMIT */
b73c452003-03-25Martin Nilsson /* #define PROC_DEBUG */
a9590d1998-04-21Henrik Grubbström (Grubba) 
392e4b2004-04-01Henrik Grubbström (Grubba) #ifdef PROC_DEBUG
a91d9a2016-01-11Martin Nilsson #define PROC_FPRINTF(...) fprintf(stderr, __VA_ARGS__)
392e4b2004-04-01Henrik Grubbström (Grubba) #else
a91d9a2016-01-11Martin Nilsson #define PROC_FPRINTF(...)
392e4b2004-04-01Henrik Grubbström (Grubba) #endif /* PROC_DEBUG */
0c95942018-01-12Stephen R. van den Berg #if !defined(__NT__) && !defined(__amigaos__)
70e9781999-03-06Fredrik Hübinette (Hubbe) #define USE_PID_MAPPING #else
d561d61999-03-07Fredrik Hübinette (Hubbe) #undef USE_WAIT_THREAD #undef USE_SIGCHILD
70e9781999-03-06Fredrik Hübinette (Hubbe) #endif
3be5501999-06-08Fredrik Hübinette (Hubbe) #if defined(USE_SIGCHILD) && defined(__linux__) && defined(_REENTRANT)
4743f81999-06-02Fredrik Hübinette (Hubbe) #define NEED_SIGNAL_SAFE_FIFO #endif #ifndef NEED_SIGNAL_SAFE_FIFO #ifdef DEBUG #define SAFE_FIFO_DEBUG_BEGIN() do {\ static volatile int inside=0; \ if(inside) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("You need to define NEED_SIGNAL_SAFE_FIFO in signal_handler.c!\n"); \
4743f81999-06-02Fredrik Hübinette (Hubbe)  inside=1; #define SAFE_FIFO_DEBUG_END() inside=0; }while(0)
45f2a22002-09-10Martin Nilsson #endif /* DEBUG */
4743f81999-06-02Fredrik Hübinette (Hubbe) 
fae26d2013-01-26Henrik Grubbström (Grubba) #define DECLARE_FIFO(pre,TYPE) \ static volatile TYPE PIKE_CONCAT(pre,buf) [SIGNAL_BUFFER]; \ static volatile int PIKE_CONCAT(pre,_first)=0,PIKE_CONCAT(pre,_last)=0; \
1486162013-01-29Henrik Grubbström (Grubba)  static inline int PIKE_CONCAT(pre,_pop)(TYPE *val) { \
fae26d2013-01-26Henrik Grubbström (Grubba)  int tmp2 = PIKE_CONCAT(pre,_first); \
1486162013-01-29Henrik Grubbström (Grubba)  if(PIKE_CONCAT(pre,_last) != tmp2) { \
fae26d2013-01-26Henrik Grubbström (Grubba)  int tmp; \ if( ++ PIKE_CONCAT(pre,_last) == SIGNAL_BUFFER) \ PIKE_CONCAT(pre,_last)=0; \ tmp = PIKE_CONCAT(pre,_last); \
1486162013-01-29Henrik Grubbström (Grubba)  *val = PIKE_CONCAT(pre,buf)[tmp]; \ return 1; \
fae26d2013-01-26Henrik Grubbström (Grubba)  } \
1486162013-01-29Henrik Grubbström (Grubba)  return 0; \
fae26d2013-01-26Henrik Grubbström (Grubba)  } \ \ static inline void PIKE_CONCAT(pre,_push)(TYPE val) { \ int tmp = PIKE_CONCAT(pre, _first) + 1; \ if (tmp >= SIGNAL_BUFFER) tmp = 0; \ PIKE_CONCAT(pre, buf)[tmp] = val; \ PIKE_CONCAT(pre, _first) = tmp; \ }
4743f81999-06-02Fredrik Hübinette (Hubbe)  #define QUICK_CHECK_FIFO(pre,TYPE) ( PIKE_CONCAT(pre,_first) != PIKE_CONCAT(pre,_last) ) #define INIT_FIFO(pre,TYPE)
23c5132017-10-03Per Cederqvist #define REINIT_FIFO(pre,TYPE)
4743f81999-06-02Fredrik Hübinette (Hubbe) 
45f2a22002-09-10Martin Nilsson #else /* NEED_SIGNAL_SAFE_FIFO */
4743f81999-06-02Fredrik Hübinette (Hubbe) 
fae26d2013-01-26Henrik Grubbström (Grubba) #define DECLARE_FIFO(pre,TYPE) \ static int PIKE_CONCAT(pre,_fd)[2]; \ static volatile sig_atomic_t PIKE_CONCAT(pre,_data_available); \ static inline int PIKE_CONCAT(pre, _pop)(TYPE *val) { \ PIKE_CONCAT(pre,_data_available) = 0; \ if (read(PIKE_CONCAT(pre,_fd)[0], val, sizeof(*val)) \ == sizeof(*val)) { \ /* NB: We must reset and set data_available here \ * to avoid races. */ \ PIKE_CONCAT(pre,_data_available) = 1; \ return 1; \ } \ return 0; \ } \ \ static inline void PIKE_CONCAT(pre, _push)(TYPE val) { \ int sz; \ int errno_save = errno; \ while( (sz = write(PIKE_CONCAT(pre,_fd)[1], (char *)&val, \ sizeof(val))) < 0 && \ errno==EINTR) \ ; \ DO_IF_DEBUG(if (sz != sizeof(val)) \ Pike_fatal("Atomic pipe write failed!!\n"); ) \ errno = errno_save; \ PIKE_CONCAT(pre,_data_available)=1; \ }
4743f81999-06-02Fredrik Hübinette (Hubbe)  #define QUICK_CHECK_FIFO(pre,TYPE) PIKE_CONCAT(pre,_data_available) #define INIT_FIFO(pre,TYPE) do { \ if(pike_make_pipe(PIKE_CONCAT(pre,_fd)) <0) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Couldn't create buffer " #pre ".\n"); \
4743f81999-06-02Fredrik Hübinette (Hubbe)  \ set_nonblocking(PIKE_CONCAT(pre,_fd)[0],1); \ set_nonblocking(PIKE_CONCAT(pre,_fd)[1],1); \ set_close_on_exec(PIKE_CONCAT(pre,_fd)[0], 1); \ set_close_on_exec(PIKE_CONCAT(pre,_fd)[1], 1); \ }while(0)
13670c2015-05-25Martin Nilsson 
23c5132017-10-03Per Cederqvist #define REINIT_FIFO(pre,TYPE) do { \ close(PIKE_CONCAT(pre,_fd)[0]); \ close(PIKE_CONCAT(pre,_fd)[1]); \ INIT_FIFO(pre,TYPE); \ } while(0)
45f2a22002-09-10Martin Nilsson #endif /* else NEED_SIGNAL_SAFE_FIFO */
4743f81999-06-02Fredrik Hübinette (Hubbe)  #ifndef SAFE_FIFO_DEBUG_END #define SAFE_FIFO_DEBUG_BEGIN() do { #define SAFE_FIFO_DEBUG_END() }while(0) #endif
70e9781999-03-06Fredrik Hübinette (Hubbe) 
0d7c542014-05-20Per Hedbor  /* There is really no need at all to optimize this for speed. The issue is that the loops checking EINTR etc are unrolled 32 times or so, which is very very pointless and makes the code size explode for no good reason. An alternative solution would be helper functions for all systemcalls that can be interrupted (in reality, usually none when using modern OS:es and setting the signal flags correctly, but...) */ #ifdef __GNUC__ #pragma GCC optimize "-Os" #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) extern int fd_from_object(struct object *o);
70e9781999-03-06Fredrik Hübinette (Hubbe) static int set_priority( int pid, char *to );
965cb11998-04-06Fredrik Hübinette (Hubbe) 
cb22561995-10-11Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe) static struct svalue signal_callbacks[MAX_SIGNALS];
b887362013-01-27Henrik Grubbström (Grubba) static sig_atomic_t signal_masks[MAX_SIGNALS];
5f06241999-04-11Fredrik Hübinette (Hubbe) static void (*default_signals[MAX_SIGNALS])(INT32);
a29e021996-10-15Fredrik Hübinette (Hubbe) static struct callback *signal_evaluator_callback =0;
aec9021999-06-12Henrik Grubbström (Grubba) DECLARE_FIFO(sig, unsigned char);
4743f81999-06-02Fredrik Hübinette (Hubbe) 
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #ifdef USE_PID_MAPPING static void report_child(int pid,
b143542003-02-28Henrik Grubbström (Grubba)  WAITSTATUSTYPE status, const char *called_from);
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #endif #ifdef USE_SIGCHILD static RETSIGTYPE receive_sigchild(int signum);
4743f81999-06-02Fredrik Hübinette (Hubbe) typedef struct wait_data_s {
e51c9b1999-05-03Fredrik Hübinette (Hubbe)  pid_t pid; WAITSTATUSTYPE status;
4743f81999-06-02Fredrik Hübinette (Hubbe) } wait_data;
aec9021999-06-12Henrik Grubbström (Grubba) DECLARE_FIFO(wait, wait_data);
e51c9b1999-05-03Fredrik Hübinette (Hubbe) 
45f2a22002-09-10Martin Nilsson #endif /* USE_SIGCHILD */
cb22561995-10-11Fredrik Hübinette (Hubbe)  /* * All known signals */
c33e761998-02-27Fredrik Hübinette (Hubbe) #ifdef __NT__ #ifndef SIGKILL #define SIGKILL 9 #endif #endif /* __NT__ */
70e9781999-03-06Fredrik Hübinette (Hubbe) struct sigdesc { int signum; char *signame; };
eb54102004-06-23Martin Nilsson static const struct sigdesc signal_desc []={
cb22561995-10-11Fredrik Hübinette (Hubbe) #ifdef SIGHUP { SIGHUP, "SIGHUP" }, #endif #ifdef SIGINT { SIGINT, "SIGINT" }, #endif #ifdef SIGQUIT { SIGQUIT, "SIGQUIT" }, #endif #ifdef SIGILL { SIGILL, "SIGILL" }, #endif #ifdef SIGTRAP { SIGTRAP, "SIGTRAP" }, #endif #ifdef SIGABRT { SIGABRT, "SIGABRT" }, #endif #ifdef SIGIOT { SIGIOT, "SIGIOT" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGEMT { SIGEMT, "SIGEMT" },
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif #ifdef SIGFPE { SIGFPE, "SIGFPE" }, #endif #ifdef SIGKILL { SIGKILL, "SIGKILL" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGBUS { SIGBUS, "SIGBUS" },
0e2fd01997-06-17Fredrik Hübinette (Hubbe) #endif #ifdef SIGSEGV { SIGSEGV, "SIGSEGV" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGSYS { SIGSYS, "SIGSYS" }, #endif
cb22561995-10-11Fredrik Hübinette (Hubbe) #ifdef SIGPIPE { SIGPIPE, "SIGPIPE" }, #endif #ifdef SIGALRM { SIGALRM, "SIGALRM" }, #endif #ifdef SIGTERM { SIGTERM, "SIGTERM" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGUSR1 { SIGUSR1, "SIGUSR1" }, #endif #ifdef SIGUSR2 { SIGUSR2, "SIGUSR2" },
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif #ifdef SIGCHLD { SIGCHLD, "SIGCHLD" }, #endif #ifdef SIGCLD { SIGCLD, "SIGCLD" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGPWR { SIGPWR, "SIGPWR" }, #endif #ifdef SIGWINCH { SIGWINCH, "SIGWINCH" }, #endif #ifdef SIGURG { SIGURG, "SIGURG" }, #endif #ifdef SIGIO { SIGIO, "SIGIO" },
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif #ifdef SIGSTOP { SIGSTOP, "SIGSTOP" }, #endif #ifdef SIGTSTP { SIGTSTP, "SIGTSTP" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGCONT { SIGCONT, "SIGCONT" }, #endif
cb22561995-10-11Fredrik Hübinette (Hubbe) #ifdef SIGTSTP { SIGTSTP, "SIGTSTP" }, #endif #ifdef SIGTTIN { SIGTTIN, "SIGTTIN" }, #endif #ifdef SIGTTIO { SIGTTIO, "SIGTTIO" }, #endif #ifdef SIGVTALRM { SIGVTALRM, "SIGVTALRM" }, #endif #ifdef SIGPROF { SIGPROF, "SIGPROF" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGXCPU { SIGXCPU, "SIGXCPU" },
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGXFSZ { SIGXFSZ, "SIGXFSZ" }, #endif #ifdef SIGSTKFLT { SIGSTKFLT, "SIGSTKFLT" },
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif #ifdef SIGPOLL { SIGPOLL, "SIGPOLL" }, #endif #ifdef SIGLOST { SIGLOST, "SIGLOST" }, #endif #ifdef SIGUNUSED { SIGUNUSED, "SIGUNUSED" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGINFO { SIGINFO, "SIGINFO" }, #endif #ifdef SIGMSG { SIGMSG, "SIGMSG" }, #endif #ifdef SIGDANGER { SIGDANGER, "SIGDANGER" }, #endif #ifdef SIGMIGRATE { SIGMIGRATE, "SIGMIGRATE" }, #endif #ifdef SIGPRE { SIGPRE, "SIGPRE" }, #endif #ifdef SIGVIRT { SIGVIRT, "SIGVIRT" }, #endif #ifdef SIGALRM1 { SIGALRM1, "SIGALRM1" }, #endif #ifdef SIGWAITING { SIGWAITING, "SIGWAITING" }, #endif #ifdef SIGKAP { SIGKAP, "SIGKAP" }, #endif #ifdef SIGGRANT { SIGGRANT, "SIGGRANT" }, #endif #ifdef SIGRETRACT { SIGRETRACT, "SIGRETRACT" }, #endif #ifdef SIGSOUND { SIGSOUND, "SIGSOUND" }, #endif #ifdef SIGSAK { SIGSAK, "SIGSAK" }, #endif #ifdef SIGDIL { SIGDIL, "SIGDIL" }, #endif #ifdef SIG32 { SIG32, "SIG32" }, #endif #ifdef SIGCKPT { SIGCKPT, "SIGCKPT" }, #endif #ifdef SIGPTRESCHED { SIGPTRESCHED, "SIGPTRESCHED" }, #endif
17fde51998-05-09Henrik Grubbström (Grubba)  #ifndef _REENTRANT
775f491998-01-18Henrik Grubbström (Grubba) #ifdef SIGWAITING { SIGWAITING, "SIGWAITING" }, #endif #ifdef SIGLWP { SIGLWP, "SIGLWP" }, #endif #ifdef SIGCANCEL { SIGCANCEL, "SIGCANCEL" }, #endif #endif /* !_REENTRANT */ #ifdef SIGFREEZE { SIGFREEZE, "SIGFREEZE" }, #endif #ifdef SIGTHAW { SIGTHAW, "SIGTHAW" }, #endif
fac1132001-09-28Tomas Nilsson #ifdef SIGBREAK { SIGBREAK, "SIGBREAK" }, #endif
775f491998-01-18Henrik Grubbström (Grubba) 
cb22561995-10-11Fredrik Hübinette (Hubbe)  { -1, "END" } /* Notused */ };
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
df78071999-06-10Fredrik Hübinette (Hubbe) /* Process stuff */
f62ab81999-06-25Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
df78071999-06-10Fredrik Hübinette (Hubbe) 
955f5c1999-08-27Fredrik Hübinette (Hubbe) #define MY_MAX_PID 65536 char process_info[MY_MAX_PID];
df78071999-06-10Fredrik Hübinette (Hubbe) int last_pid_p; int last_pids[4096]; #define P_NOT_STARTED 0 #define P_RUNNING 1 #define P_DONE 2 #define P_RUNNING_AGAIN 3 #define P_DONE_AGAIN 4 void dump_process_history(pid_t pid) { int e;
955f5c1999-08-27Fredrik Hübinette (Hubbe)  if(pid < 1)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pid out of range: %ld\n",(long)pid);
df78071999-06-10Fredrik Hübinette (Hubbe)  fprintf(stderr,"Process history:"); for(e=MAXIMUM(-4095,-last_pid_p);e<0;e++) { fprintf(stderr," %d",last_pids[ (last_pid_p + e) & 4095]); }
955f5c1999-08-27Fredrik Hübinette (Hubbe)  if(pid<MY_MAX_PID) fprintf(stderr,"\nProblem pid = %d, status = %d\n", (int)pid, process_info[pid]);
df78071999-06-10Fredrik Hübinette (Hubbe) } void process_started(pid_t pid) {
955f5c1999-08-27Fredrik Hübinette (Hubbe)  if(pid < 1)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pid out of range: %ld\n",(long)pid);
df78071999-06-10Fredrik Hübinette (Hubbe)  last_pids[last_pid_p++ & 4095]=pid;
48bfd11999-08-30Fredrik Hübinette (Hubbe)  if(pid>=MY_MAX_PID)
955f5c1999-08-27Fredrik Hübinette (Hubbe)  return;
df78071999-06-10Fredrik Hübinette (Hubbe)  switch(process_info[pid]) { case P_NOT_STARTED: case P_DONE: process_info[pid]++; break; case P_DONE_AGAIN: process_info[pid]=P_RUNNING_AGAIN; break; default: dump_process_history(pid);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Process debug: Pid %ld started without stopping! (status=%d)\n",(long)pid,process_info[pid]);
df78071999-06-10Fredrik Hübinette (Hubbe)  } }
b143542003-02-28Henrik Grubbström (Grubba) void process_done(pid_t pid, const char *from)
df78071999-06-10Fredrik Hübinette (Hubbe) {
955f5c1999-08-27Fredrik Hübinette (Hubbe)  if(pid < 1)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pid out of range in %s: %ld\n",from,(long)pid);
955f5c1999-08-27Fredrik Hübinette (Hubbe) 
48bfd11999-08-30Fredrik Hübinette (Hubbe)  if(pid>=MY_MAX_PID)
955f5c1999-08-27Fredrik Hübinette (Hubbe)  return;
df78071999-06-10Fredrik Hübinette (Hubbe)  switch(process_info[pid]) { case P_RUNNING: case P_RUNNING_AGAIN: process_info[pid]++; break; default:
948afd1999-07-16Fredrik Hübinette (Hubbe) #ifdef PROC_DEBUG
df78071999-06-10Fredrik Hübinette (Hubbe)  dump_process_history(pid);
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Process debug: Unknown child %ld in %s! (status=%d)\n", getpid(), (long)pid,from,process_info[pid]);
948afd1999-07-16Fredrik Hübinette (Hubbe) #endif
2fafca1999-07-20Fredrik Hübinette (Hubbe)  break;
df78071999-06-10Fredrik Hübinette (Hubbe)  } } #else
74dfe82012-12-30Jonas Walldén void process_started(pid_t UNUSED(pid)) { } void process_done(pid_t UNUSED(pid), const char *UNUSED(from)) { }
df78071999-06-10Fredrik Hübinette (Hubbe) 
45f2a22002-09-10Martin Nilsson #endif /* PIKE_DEBUG */
df78071999-06-10Fredrik Hübinette (Hubbe) 
e51c9b1999-05-03Fredrik Hübinette (Hubbe) static void register_signal(int signum)
70e9781999-03-06Fredrik Hübinette (Hubbe) {
fae26d2013-01-26Henrik Grubbström (Grubba)  sig_push(signum);
e51c9b1999-05-03Fredrik Hübinette (Hubbe)  wake_up_backend(); } static RETSIGTYPE receive_signal(int signum) {
4743f81999-06-02Fredrik Hübinette (Hubbe)  SAFE_FIFO_DEBUG_BEGIN();
70e9781999-03-06Fredrik Hübinette (Hubbe)  if ((signum < 0) || (signum >= MAX_SIGNALS)) { /* Some OSs (Solaris 2.6) send a bad signum sometimes. * SIGCHLD is the safest signal to substitute. * /grubba 1998-05-19 */ #ifdef SIGCHLD signum = SIGCHLD; #else signum = 0; #endif }
e51c9b1999-05-03Fredrik Hübinette (Hubbe)  register_signal(signum);
4743f81999-06-02Fredrik Hübinette (Hubbe)  SAFE_FIFO_DEBUG_END();
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #ifdef SIGNAL_ONESHOT
70e9781999-03-06Fredrik Hübinette (Hubbe)  my_signal(signum, receive_signal); #endif } /* This function is intended to work like signal(), but better :) */
cd83521998-02-02Fredrik Hübinette (Hubbe) void my_signal(int sig, sigfunctype fun)
8dd2371995-11-02Fredrik Hübinette (Hubbe) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] my_signal(%d, 0x%p)\n", getpid(), sig, (void *)fun);
8dd2371995-11-02Fredrik Hübinette (Hubbe) #ifdef HAVE_SIGACTION { struct sigaction action;
17fde51998-05-09Henrik Grubbström (Grubba)  /* NOTE: * sa_handler is really _funcptr._handler, and * sa_sigaction is really _funcptr._sigaction, * where _funcptr is a union. ie sa_handler and * sa_sigaction overlap. */
21b12a2014-09-03Martin Nilsson  memset(&action, 0, sizeof(action));
17fde51998-05-09Henrik Grubbström (Grubba)  action.sa_handler = fun;
8dd2371995-11-02Fredrik Hübinette (Hubbe)  sigfillset(&action.sa_mask);
17fde51998-05-09Henrik Grubbström (Grubba)  action.sa_flags = 0;
8dd2371995-11-02Fredrik Hübinette (Hubbe) #ifdef SA_INTERRUPT
6307e01995-11-02Fredrik Hübinette (Hubbe)  if(fun != SIG_IGN)
17fde51998-05-09Henrik Grubbström (Grubba)  action.sa_flags |= SA_INTERRUPT;
8dd2371995-11-02Fredrik Hübinette (Hubbe) #endif
17fde51998-05-09Henrik Grubbström (Grubba)  sigaction(sig, &action, NULL);
8dd2371995-11-02Fredrik Hübinette (Hubbe)  } #else #ifdef HAVE_SIGVEC { struct sigvec action;
21b12a2014-09-03Martin Nilsson  memset(&action, 0, sizeof(action));
6307e01995-11-02Fredrik Hübinette (Hubbe)  action.sv_handler= fun;
8dd2371995-11-02Fredrik Hübinette (Hubbe)  action.sv_mask=-1;
17fde51998-05-09Henrik Grubbström (Grubba) #ifdef SV_INTERRUPT
6307e01995-11-02Fredrik Hübinette (Hubbe)  if(fun != SIG_IGN) action.sv_flags=SV_INTERRUPT;
8dd2371995-11-02Fredrik Hübinette (Hubbe) #endif sigvec(sig,&action,0); } #else
04554a1997-04-10Fredrik Hübinette (Hubbe)  signal(sig, fun);
8dd2371995-11-02Fredrik Hübinette (Hubbe) #endif #endif }
70e9781999-03-06Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén PMOD_EXPORT void check_signals(struct callback *UNUSED(foo), void *UNUSED(bar), void *UNUSED(gazonk))
8dd2371995-11-02Fredrik Hübinette (Hubbe) {
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(d_flag>5) do_debug(); #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
b887362013-01-27Henrik Grubbström (Grubba)  if (QUICK_CHECK_FIFO(sig, unsigned char))
70e9781999-03-06Fredrik Hübinette (Hubbe)  {
fae26d2013-01-26Henrik Grubbström (Grubba)  unsigned char sig = ~0;
70e9781999-03-06Fredrik Hübinette (Hubbe) 
fae26d2013-01-26Henrik Grubbström (Grubba)  while (sig_pop(&sig)) {
70e9781999-03-06Fredrik Hübinette (Hubbe) 
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #ifdef USE_SIGCHILD
fae26d2013-01-26Henrik Grubbström (Grubba)  if(sig == SIGCHLD) { wait_data wd;
4743f81999-06-02Fredrik Hübinette (Hubbe) 
fae26d2013-01-26Henrik Grubbström (Grubba)  while (wait_pop(&wd)) { if(!wd.pid) Pike_fatal("wd.pid=0 NEED_SIGNAL_SAFE_FIFO is "
4743f81999-06-02Fredrik Hübinette (Hubbe) #ifndef NEED_SIGNAL_SAFE_FIFO
fae26d2013-01-26Henrik Grubbström (Grubba)  "not "
4743f81999-06-02Fredrik Hübinette (Hubbe) #endif
fae26d2013-01-26Henrik Grubbström (Grubba)  "defined.\n"); report_child(wd.pid, wd.status, "check_signals"); } }
eaf8b91998-07-15Fredrik Hübinette (Hubbe) #endif
70e9781999-03-06Fredrik Hübinette (Hubbe) 
a03cc42013-02-06Henrik Grubbström (Grubba) #if MAX_SIGNALS < 256 if (sig >= MAX_SIGNALS) continue; #endif
b887362013-01-27Henrik Grubbström (Grubba)  if (!signal_masks[sig]) { signal_masks[sig] = 1; do { /* NB: We check this every loop in case the * Pike-level signal handler has been * disabled during the call. */ if(SAFE_IS_ZERO(signal_callbacks + sig)) { if(default_signals[sig]) default_signals[sig](sig); } else { JMP_BUF recovery; free_svalue(&throw_value); mark_free_svalue(&throw_value); if (SETJMP_SP(recovery, 0)) { call_handle_error(); } else { push_svalue(signal_callbacks + sig); push_int(sig); f_call_function(2); pop_stack(); } UNSETJMP(recovery); } } while (--signal_masks[sig]);
18c1c02013-01-20Henrik Grubbström (Grubba)  } else {
b887362013-01-27Henrik Grubbström (Grubba)  /* Signal handler is being called somewhere else. * Make it repeat when finished. */ signal_masks[sig] = 2;
18c1c02013-01-20Henrik Grubbström (Grubba)  } }
7faf3c1998-06-17Fredrik Noring  }
70e9781999-03-06Fredrik Hübinette (Hubbe) }
ba89b71998-05-05Marcus Comstedt 
70e9781999-03-06Fredrik Hübinette (Hubbe) /* Get the name of a signal given the number */ static char *signame(int sig) { int e; for(e=0;e<(int)NELEM(signal_desc)-1;e++)
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
70e9781999-03-06Fredrik Hübinette (Hubbe)  if(sig==signal_desc[e].signum) return signal_desc[e].signame;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }
70e9781999-03-06Fredrik Hübinette (Hubbe)  return 0; }
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe) /* Get the signal's number given the name */ static int signum(char *name) { int e; for(e=0;e<(int)NELEM(signal_desc)-1;e++)
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
70e9781999-03-06Fredrik Hübinette (Hubbe)  if(!STRCASECMP(name,signal_desc[e].signame) || !STRCASECMP(name,signal_desc[e].signame+3) ) return signal_desc[e].signum; } return -1; }
1bb6612012-07-30Chris Angelico /*! @decl function(int|void:void) signal(int sig, function(int|void:void) callback) *! @decl function(int|void:void) signal(int sig)
685fb62001-01-31Henrik Grubbström (Grubba)  *! *! Trap signals. *! *! This function allows you to trap a signal and have a function called *! when the process receives a signal. Although it IS possible to trap
1bb6612012-07-30Chris Angelico  *! SIGBUS, SIGSEGV etc, I advise you not to; Pike should not receive any *! such signals, and if it does, it is because of bugs in the Pike
685fb62001-01-31Henrik Grubbström (Grubba)  *! interpreter. And all bugs should be reported, no matter how trifle. *! *! The callback will receive the signal number as its only argument. *! *! See the documentation for @[kill()] for a list of signals. *! *! If no second argument is given, the signal handler for that signal *! is restored to the default handler. *! *! If the second argument is zero, the signal will be completely ignored. *!
1bb6612012-07-30Chris Angelico  *! @returns *! Returns the previous signal function, or 0 if none had been registered. *!
685fb62001-01-31Henrik Grubbström (Grubba)  *! @seealso *! @[kill()], @[signame()], @[signum()] */
70e9781999-03-06Fredrik Hübinette (Hubbe) static void f_signal(int args) { int signum; sigfunctype func;
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] f_signal(%d)\n", getpid(), args);
c0110f2003-08-20Henrik Grubbström (Grubba) 
70e9781999-03-06Fredrik Hübinette (Hubbe)  check_signals(0,0,0); if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("signal", 1);
70e9781999-03-06Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("signal", 1, "int");
70e9781999-03-06Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  signum=Pike_sp[-args].u.integer;
70e9781999-03-06Fredrik Hübinette (Hubbe)  if(signum <0 || signum >=MAX_SIGNALS ) {
7db3392017-03-07Martin Nilsson  Pike_error("Signal %d out of range.\n", signum);
70e9781999-03-06Fredrik Hübinette (Hubbe)  } if(!signal_evaluator_callback) { signal_evaluator_callback=add_to_callback(&evaluator_callbacks, check_signals, 0,0);
424d9c1999-05-02Fredrik Hübinette (Hubbe)  dmalloc_accept_leak(signal_evaluator_callback);
70e9781999-03-06Fredrik Hübinette (Hubbe)  } if(args == 1) { push_int(0); args++; switch(signum) {
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #ifdef USE_SIGCHILD
5f06241999-04-11Fredrik Hübinette (Hubbe)  case SIGCHLD: func=receive_sigchild; break;
70e9781999-03-06Fredrik Hübinette (Hubbe) #endif
13670c2015-05-25Martin Nilsson 
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef SIGPIPE
5f06241999-04-11Fredrik Hübinette (Hubbe)  case SIGPIPE: func=(sigfunctype) SIG_IGN; break;
061ca91999-04-01Fredrik Hübinette (Hubbe) #endif
13670c2015-05-25Martin Nilsson 
5f06241999-04-11Fredrik Hübinette (Hubbe)  default: if(default_signals[signum]) func=receive_signal; else func=(sigfunctype) SIG_DFL;
061ca91999-04-01Fredrik Hübinette (Hubbe)  break;
70e9781999-03-06Fredrik Hübinette (Hubbe)  } } else {
fc68462002-10-31Henrik Grubbström (Grubba)  if(SAFE_IS_ZERO(Pike_sp+1-args))
70e9781999-03-06Fredrik Hübinette (Hubbe)  {
5f06241999-04-11Fredrik Hübinette (Hubbe)  /* Fixme: this can disrupt sigchild and other important signal handling */
70e9781999-03-06Fredrik Hübinette (Hubbe)  func=(sigfunctype) SIG_IGN; }else{ func=receive_signal;
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #ifdef USE_SIGCHILD
70e9781999-03-06Fredrik Hübinette (Hubbe)  if(signum == SIGCHLD) func=receive_sigchild; #endif } }
fc68462002-10-31Henrik Grubbström (Grubba)  assign_svalue(Pike_sp-args,signal_callbacks+signum); assign_svalue(signal_callbacks + signum, Pike_sp+1-args);
70e9781999-03-06Fredrik Hübinette (Hubbe)  my_signal(signum, func);
c6e0d32000-03-07Fredrik Hübinette (Hubbe)  pop_n_elems(args-1);
70e9781999-03-06Fredrik Hübinette (Hubbe) }
5f06241999-04-11Fredrik Hübinette (Hubbe) void set_default_signal_handler(int signum, void (*func)(INT32)) {
9f516a2001-12-16Martin Stjernholm  int is_on=!!SAFE_IS_ZERO(signal_callbacks+signum);
5f06241999-04-11Fredrik Hübinette (Hubbe)  int want_on=!!func; default_signals[signum]=func; if(is_on!=want_on) my_signal(signum, want_on ? receive_signal : (sigfunctype) SIG_DFL); }
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl int signum(string sig) *! *! Get a signal number given a descriptive string. *! *! This function is the inverse of @[signame()]. *! *! @seealso *! @[signame()], @[kill()], @[signal()] */
70e9781999-03-06Fredrik Hübinette (Hubbe) static void f_signum(int args) { int i; if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("signum", 1);
70e9781999-03-06Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != T_STRING)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("signum", 1, "string");
70e9781999-03-06Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  i=signum(Pike_sp[-args].u.string->str);
70e9781999-03-06Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(i); }
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl string signame(int sig) *! *! Returns a string describing the signal @[sig]. *! *! @seealso *! @[kill()], @[signum()], @[signal()] */
70e9781999-03-06Fredrik Hübinette (Hubbe) static void f_signame(int args) { char *n; if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("signame", 1);
70e9781999-03-06Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("signame", 1, "int");
70e9781999-03-06Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  n=signame(Pike_sp[-args].u.integer);
70e9781999-03-06Fredrik Hübinette (Hubbe)  pop_n_elems(args); if(n)
2d1a3e2003-12-06Martin Nilsson  push_text(n);
70e9781999-03-06Fredrik Hübinette (Hubbe)  else push_int(0); }
ef24072009-04-22Henrik Grubbström (Grubba) /* #define PIKE_USE_FORKD */ #ifdef PIKE_USE_FORKD /* Forkd communication fd. */ static int forkd_fd = -1; void forkd(int fd) { struct msghdr msg; struct iovec iov; char cmsgbuf[CMSG_LEN(sizeof(int))]; char buf; int i; int num_fail = 0; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; /* Clean up the fds so we don't need to do it for the children. */ if (fd != 3) { do { i = dup2(fd, 3);
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(i < 0) && UNLIKELY((errno == EINTR) || (errno == EBUSY)));
ef24072009-04-22Henrik Grubbström (Grubba)  if (i < 0) { write(2, "FORKD: Failed to dup fd!\n", 25); _exit(0); } fd = 3; } for (i = 4; num_fail < PIKE_BADF_LIMIT; i++) { int j; do { j = close(i);
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(j < 0) && UNLIKELY(errno == EINTR));
b0a1a92012-12-02Peter Bortas  if ((j < 0) && (errno == EBADF)) num_fail++;
ef24072009-04-22Henrik Grubbström (Grubba)  } while (1) { int i; struct cmsghdr *cmsg; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); iov.iov_base = &buf; iov.iov_len = 1; do { i = recvmsg(fd, &msg, 0);
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(i < 0) && UNLIKELY(errno == EINTR));
ef24072009-04-22Henrik Grubbström (Grubba)  if (!i) _exit(0); /* Connection closed, shutdown forkd. */ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { int ctrl_fd = NULL; if ((cmsg->cmsg_level != SOL_SOCKET) || (cmsg->cmsg_type != SCM_RIGHTS) || (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))) { continue; } ctrl_fd = ((int *)CMSG_DATA(cmsg))[0]; num_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); do { i = fork();
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(i < 0) && UNLIKELY(errno == EINTR));
ef24072009-04-22Henrik Grubbström (Grubba)  if (i < 0) { /* Fork failure. */ } else if (i) { /* Fork success. */ } else { /* Child. */ forkd_child(ctrl_fd); } do { i = close(ctrl_fd);
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(i < 0) && UNLIKELY(errno == EINTR));
ef24072009-04-22Henrik Grubbström (Grubba)  } } } #endif
70e9781999-03-06Fredrik Hübinette (Hubbe) 
acff292003-03-25Henrik Grubbström (Grubba) /* Define two macros: * * WAITPID(pid_t PID, WAITSTATUSTYPE *STATUS, int OPT) * Wait for pid PID. * * MY_WAIT_ANY(WAITSTATUSTYPE *STATUS, int OPT) * Wait for any child process. */ #if defined(HAVE_WAIT4) && defined(HAVE_WAITPID) && defined(__FreeBSD__) /* waitpid(2) is more broken than wait4(2) on FreeBSD. * wait4(2) is more broken than waitpid(2) on AIX 5L 5.1.0.0/ia64. */ #undef HAVE_WAITPID
70e9781999-03-06Fredrik Hübinette (Hubbe) #endif
ae2cc61998-05-19Fredrik Hübinette (Hubbe) 
8dd2371995-11-02Fredrik Hübinette (Hubbe) #ifdef HAVE_WAITPID
acff292003-03-25Henrik Grubbström (Grubba) #define WAITPID(PID,STATUS,OPT) waitpid((PID), (STATUS), (OPT)) #define MY_WAIT_ANY(STATUS,OPT) waitpid(-1, (STATUS), (OPT))
8dd2371995-11-02Fredrik Hübinette (Hubbe) #else
acff292003-03-25Henrik Grubbström (Grubba) #ifdef HAVE_WAIT4 #define WAITPID(PID,STATUS,OPT) wait4((PID), (STATUS), (OPT), 0) #define MY_WAIT_ANY(STATUS,OPT) wait4(0, (STATUS), (OPT), 0) #else #define WAITPID(PID,STATUS,OPT) -1
8dd2371995-11-02Fredrik Hübinette (Hubbe) #ifdef HAVE_WAIT3
acff292003-03-25Henrik Grubbström (Grubba) #define MY_WAIT_ANY(STATUS,OPT) wait3((STATUS), (OPT), 0)
8dd2371995-11-02Fredrik Hübinette (Hubbe) #else
acff292003-03-25Henrik Grubbström (Grubba) #define MY_WAIT_ANY(STATUS,OPT) ((errno=ENOTSUP), -1)
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif #endif #endif
b3cc131998-01-15Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe) 
d3c5f41999-03-10Fredrik Hübinette (Hubbe) #ifdef USE_SIGCHILD
4743f81999-06-02Fredrik Hübinette (Hubbe) 
b6722b2014-07-03Arne Goedeke #ifdef SIGNAL_ONESHOT static RETSIGTYPE receive_sigchild(int signum) #else
dffabf2014-02-24Per Hedbor static RETSIGTYPE receive_sigchild(int UNUSED(signum))
b6722b2014-07-03Arne Goedeke #endif
70e9781999-03-06Fredrik Hübinette (Hubbe) { pid_t pid; WAITSTATUSTYPE status;
11c2a22014-09-17Tobias S. Josefowitz  int masked_errno = errno;
4743f81999-06-02Fredrik Hübinette (Hubbe) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] receive_sigchild\n", getpid());
4c4a742002-12-18Martin Stjernholm 
80d7702013-01-01Henrik Grubbström (Grubba) #ifdef SIGNAL_ONESHOT /* Reregister the signal early, so that we don't * miss any children. */ my_signal(signum, receive_sigchild); #endif
4743f81999-06-02Fredrik Hübinette (Hubbe)  SAFE_FIFO_DEBUG_BEGIN();
70e9781999-03-06Fredrik Hübinette (Hubbe)  try_reap_again: /* We carefully reap what we saw */
b143542003-02-28Henrik Grubbström (Grubba)  pid=MY_WAIT_ANY(&status, WNOHANG|WUNTRACED);
13670c2015-05-25Martin Nilsson 
70e9781999-03-06Fredrik Hübinette (Hubbe)  if(pid>0) {
fae26d2013-01-26Henrik Grubbström (Grubba)  wait_data wd;
392e4b2004-04-01Henrik Grubbström (Grubba) 
c6196a2009-07-23Henrik Grubbström (Grubba) #ifdef __CHECKER__ /* Clear potential padding. */
21b12a2014-09-03Martin Nilsson  memset(&wd, 0, sizeof(wd));
c6196a2009-07-23Henrik Grubbström (Grubba) #endif
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] receive_sigchild got pid %d\n", getpid(), pid);
392e4b2004-04-01Henrik Grubbström (Grubba) 
fae26d2013-01-26Henrik Grubbström (Grubba)  wd.pid=pid; wd.status=status; wait_push(wd);
4743f81999-06-02Fredrik Hübinette (Hubbe)  goto try_reap_again;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] receive_sigchild: No more dead children.\n", getpid());
e51c9b1999-05-03Fredrik Hübinette (Hubbe)  register_signal(SIGCHLD);
4743f81999-06-02Fredrik Hübinette (Hubbe)  SAFE_FIFO_DEBUG_END();
11c2a22014-09-17Tobias S. Josefowitz  /* The wait and possibly the signal stuff can obfuscate errno here, * while outside of the signal handler we might be in, say, the backend, * and cause a bit of trouble there. Let's leave errno as we found it. */ errno = masked_errno;
70e9781999-03-06Fredrik Hübinette (Hubbe) }
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
b143542003-02-28Henrik Grubbström (Grubba) #define PROCESS_UNKNOWN -1 #define PROCESS_RUNNING 0 #define PROCESS_STOPPED 1 #define PROCESS_EXITED 2
42c95b2003-03-03Henrik Grubbström (Grubba) 
b143542003-02-28Henrik Grubbström (Grubba) #define PROCESS_FLAG_TRACED 0x01
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
85f59e1998-01-08Fredrik Hübinette (Hubbe) #undef THIS
60d9872000-03-23Fredrik Hübinette (Hubbe) #define THIS ((struct pid_status *)CURRENT_STORAGE)
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef USE_PID_MAPPING static struct mapping *pid_mapping=0; #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) struct pid_status {
0995032011-09-08Henrik Grubbström (Grubba)  INT_TYPE pid;
85f59e1998-01-08Fredrik Hübinette (Hubbe) #ifdef __NT__ HANDLE handle;
15f49f2020-02-13Henrik Grubbström (Grubba)  struct pid_status *next_pty_client; /* PTY client chain. */ struct my_pty *pty; /* PTY master, refcounted. */
85f59e1998-01-08Fredrik Hübinette (Hubbe) #else
0995032011-09-08Henrik Grubbström (Grubba)  INT_TYPE sig; INT_TYPE flags; INT_TYPE state; INT_TYPE result;
2fc55f2006-12-27Henrik Grubbström (Grubba)  struct svalue callback;
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif }; static struct program *pid_status_program=0;
74dfe82012-12-30Jonas Walldén static void init_pid_status(struct object *UNUSED(o))
85f59e1998-01-08Fredrik Hübinette (Hubbe) { THIS->pid=-1; #ifdef __NT__
bd67392015-10-14Martin Nilsson  THIS->handle = INVALID_HANDLE_VALUE;
85f59e1998-01-08Fredrik Hübinette (Hubbe) #else
b143542003-02-28Henrik Grubbström (Grubba)  THIS->sig=0; THIS->flags=0;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  THIS->state=PROCESS_UNKNOWN; THIS->result=-1;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(THIS->callback, T_INT, NUMBER_NUMBER, integer, 0);
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
8dd2371995-11-02Fredrik Hübinette (Hubbe) }
15f49f2020-02-13Henrik Grubbström (Grubba) #ifdef __NT__ struct pid_status *pid_status_unlink_pty(struct pid_status *pid) { struct pid_status *ret; if (!pid) return NULL; ret = pid->next_pty_client; pid->next_pty_client = NULL; if (pid->pty) { free_pty(pid->pty); pid->pty = NULL; } return ret; } static void pid_status_link_pty(struct pid_status *pid, struct my_pty *pty) { add_ref(pty); pid->pty = pty; pid->next_pty_client = pty->clients; pty->clients = pid; } int check_pty_clients(struct my_pty *pty) { struct pid_status *pid; while ((pid = pty->clients)) { DWORD status; /* FIXME: RACE: pid->handle my be INVALID_HANDLE_VALUE if * the process is about to be started. */ if ((pid->pid == -1) && (pid->handle == INVALID_HANDLE_VALUE)) return 1; if (GetExitCodeProcess(pid->handle, &status) && (status == STILL_ACTIVE)) { return 1; } /* Process has terminated. Unlink and check the next. */ pty->clients = pid_status_unlink_pty(pid); } return 0; } #endif /* __NT__ */
74dfe82012-12-30Jonas Walldén static void exit_pid_status(struct object *UNUSED(o))
cb22561995-10-11Fredrik Hübinette (Hubbe) {
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef USE_PID_MAPPING
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(pid_mapping) { struct svalue key;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(key, PIKE_T_INT, NUMBER_NUMBER, integer, THIS->pid);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  map_delete(pid_mapping, &key); }
70e9781999-03-06Fredrik Hübinette (Hubbe) #endif #ifdef __NT__
15f49f2020-02-13Henrik Grubbström (Grubba)  if (THIS->pty) { struct my_pty *pty = THIS->pty;
d59f122020-02-13Henrik Grubbström (Grubba)  struct pid_status **pidptr = &pty->clients;
15f49f2020-02-13Henrik Grubbström (Grubba)  while (*pidptr && (*pidptr != THIS)) { pidptr = &(*pidptr)->next_pty_client; } if (*pidptr) { *pidptr = pid_status_unlink_pty(THIS); }
d59f122020-02-13Henrik Grubbström (Grubba)  if (!pty->clients && !pty->other && pty->conpty) { /* Last client for this ConPTY has terminated, * and our local copy of the slave has been closed. * * Close the ConPTY. */ Pike_NT_ClosePseudoConsole(pty->conpty); pty->conpty = 0; }
15f49f2020-02-13Henrik Grubbström (Grubba)  }
85f59e1998-01-08Fredrik Hübinette (Hubbe)  CloseHandle(THIS->handle); #endif }
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef USE_PID_MAPPING
74dfe82012-12-30Jonas Walldén static void call_pid_status_callback(struct callback *cb, void *pid, void *UNUSED(arg))
2fc55f2006-12-27Henrik Grubbström (Grubba) { struct object *o = pid; struct pid_status *p; remove_callback(cb); if (!o) return;
13b5ed2014-05-26Per Hedbor  if(!(p=get_storage(o, pid_status_program))) {
2fc55f2006-12-27Henrik Grubbström (Grubba)  free_object(o); return; } /* Steal the reference from o. */ push_object(o); safe_apply_svalue(&p->callback, 1, 1); pop_stack(); }
85f59e1998-01-08Fredrik Hübinette (Hubbe) static void report_child(int pid,
b143542003-02-28Henrik Grubbström (Grubba)  WAITSTATUSTYPE status, const char *from)
85f59e1998-01-08Fredrik Hübinette (Hubbe) {
53acc21999-05-24Henrik Grubbström (Grubba)  /* FIXME: This won't work if WAITSTATUSTYPE == union wait. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] report_child(%d, %d, \"%s\")\n", getpid(), (int)pid, *(int *) &status, from);
392e4b2004-04-01Henrik Grubbström (Grubba) 
b143542003-02-28Henrik Grubbström (Grubba)  if (!WIFSTOPPED(status)) { process_done(pid, from); }
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(pid_mapping) { struct svalue *s, key;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(key, PIKE_T_INT, NUMBER_NUMBER, integer, pid);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if((s=low_mapping_lookup(pid_mapping, &key))) {
2fc55f2006-12-27Henrik Grubbström (Grubba)  struct pid_status *p = NULL; int call_callback = 0;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) == T_OBJECT)
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
2fc55f2006-12-27Henrik Grubbström (Grubba)  struct object *o;
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Found pid object for pid %d: %p\n", getpid(), (int)pid, s->u.object);
13b5ed2014-05-26Per Hedbor  if((p=get_storage((o = s->u.object), pid_status_program)))
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
2fc55f2006-12-27Henrik Grubbström (Grubba)  if (!SAFE_IS_ZERO(&p->callback)) { /* Call the callback from a proper pike thread... */ add_ref(o); add_to_callback(&evaluator_callbacks, call_pid_status_callback, o, NULL);
13f8cb2009-03-30Per Hedbor  wake_up_backend();
2fc55f2006-12-27Henrik Grubbström (Grubba)  }
b143542003-02-28Henrik Grubbström (Grubba)  if(WIFSTOPPED(status)) { p->sig = WSTOPSIG(status); p->state = PROCESS_STOPPED;
b4b3a82015-07-31Martin Nilsson 
b143542003-02-28Henrik Grubbström (Grubba)  /* Make sure we don't remove the entry from the mapping... */ return;
5096d71998-05-17Henrik Grubbström (Grubba)  } else {
b143542003-02-28Henrik Grubbström (Grubba)  if(WIFEXITED(status)) { p->result = WEXITSTATUS(status); } else { if (WIFSIGNALED(status)) {
3745762007-06-17Martin Stjernholm #if 0
940a4b2005-05-25Henrik Grubbström (Grubba)  if (WTERMSIG(status) != 9) { fprintf(stderr, "Process %d died of signal %d.\n", pid, WTERMSIG(status)); }
3745762007-06-17Martin Stjernholm #endif
b143542003-02-28Henrik Grubbström (Grubba)  p->sig = WTERMSIG(status);
940a4b2005-05-25Henrik Grubbström (Grubba)  } else {
35e1152016-02-07Martin Nilsson  DWERR("Process %d died of strange cause 0x%08lx.\n", pid, (unsigned long)status); }
b143542003-02-28Henrik Grubbström (Grubba)  p->result=-1; } p->state = PROCESS_EXITED;
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Pid %d has exited\n", getpid(), (int)pid);
5096d71998-05-17Henrik Grubbström (Grubba)  }
85f59e1998-01-08Fredrik Hübinette (Hubbe)  } }
77a2e81999-04-23Henrik Grubbström (Grubba)  /* FIXME: Is this a good idea? * Shouldn't this only be done if p->state is PROCESS_EXITED? * /grubba 1999-04-23
8822ff2002-12-18Martin Stjernholm  * * But that will only happen if there isn't a proper pid status * object in the value, i.e. either a destructed object or * garbage that shouldn't be in the mapping to begin with. /mast
b143542003-02-28Henrik Grubbström (Grubba)  * * Now when we wait(2) with WUNTRACED, there are cases * when we want to keep the entry. This is currently * achieved with the return above. * /grubba 2003-02-28
2fc55f2006-12-27Henrik Grubbström (Grubba)  * * Note that this also invalidates s (and p unless we have added * extra references to the object). * /grubba 2006-12-27
77a2e81999-04-23Henrik Grubbström (Grubba)  */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  map_delete(pid_mapping, &key);
f097771999-01-07Fredrik Hübinette (Hubbe)  }else{
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] report_child on unknown child: %d,%d\n", getpid(),pid,status);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  } } }
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef USE_WAIT_THREAD
b4b3a82015-07-31Martin Nilsson static COND_T process_status_change;
70e9781999-03-06Fredrik Hübinette (Hubbe) static COND_T start_wait_thread;
74ea782016-01-29Martin Nilsson static PIKE_MUTEX_T wait_thread_mutex;
eecd3d2003-11-21Henrik Grubbström (Grubba) static int wait_thread_running = 0;
70e9781999-03-06Fredrik Hübinette (Hubbe) 
d561d61999-03-07Fredrik Hübinette (Hubbe) static void do_da_lock(void)
70e9781999-03-06Fredrik Hübinette (Hubbe) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] fork: getting the lock.\n", getpid());
392e4b2004-04-01Henrik Grubbström (Grubba) 
d561d61999-03-07Fredrik Hübinette (Hubbe)  mt_lock(&wait_thread_mutex);
392e4b2004-04-01Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] fork: got the lock.\n", getpid());
d561d61999-03-07Fredrik Hübinette (Hubbe) }
70e9781999-03-06Fredrik Hübinette (Hubbe) 
d561d61999-03-07Fredrik Hübinette (Hubbe) static void do_bi_do_da_lock(void) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait thread: This is your wakeup call!\n", getpid());
392e4b2004-04-01Henrik Grubbström (Grubba) 
d561d61999-03-07Fredrik Hübinette (Hubbe)  co_signal(&start_wait_thread);
392e4b2004-04-01Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] fork: releasing the lock.\n", getpid());
392e4b2004-04-01Henrik Grubbström (Grubba) 
d561d61999-03-07Fredrik Hübinette (Hubbe)  mt_unlock(&wait_thread_mutex); }
70e9781999-03-06Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén static TH_RETURN_TYPE wait_thread(void *UNUSED(data))
d561d61999-03-07Fredrik Hübinette (Hubbe) {
71ac9e1999-08-29Fredrik Hübinette (Hubbe)  if(th_atfork(do_da_lock,do_bi_do_da_lock,0))
d561d61999-03-07Fredrik Hübinette (Hubbe)  { perror("pthread atfork"); exit(1); }
fb45492014-05-20Per Hedbor 
70e9781999-03-06Fredrik Hübinette (Hubbe)  while(1) { WAITSTATUSTYPE status;
d561d61999-03-07Fredrik Hübinette (Hubbe)  int pid;
42c95b2003-03-03Henrik Grubbström (Grubba)  int err;
d561d61999-03-07Fredrik Hübinette (Hubbe) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait_thread: getting the lock.\n", getpid());
915d091999-04-23Henrik Grubbström (Grubba) 
d561d61999-03-07Fredrik Hübinette (Hubbe)  mt_lock(&wait_thread_mutex);
b143542003-02-28Henrik Grubbström (Grubba)  pid=MY_WAIT_ANY(&status, WNOHANG|WUNTRACED);
42c95b2003-03-03Henrik Grubbström (Grubba)  err = errno;
fb45492014-05-20Per Hedbor 
42c95b2003-03-03Henrik Grubbström (Grubba)  if(pid < 0 && err == ECHILD)
d561d61999-03-07Fredrik Hübinette (Hubbe)  {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait_thread: sleeping\n", getpid());
392e4b2004-04-01Henrik Grubbström (Grubba) 
d561d61999-03-07Fredrik Hübinette (Hubbe)  co_wait(&start_wait_thread, &wait_thread_mutex);
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait_thread: waking up\n", getpid());
d561d61999-03-07Fredrik Hübinette (Hubbe)  }
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait_thread: releasing the lock.\n", getpid());
915d091999-04-23Henrik Grubbström (Grubba) 
d561d61999-03-07Fredrik Hübinette (Hubbe)  mt_unlock(&wait_thread_mutex);
70e9781999-03-06Fredrik Hübinette (Hubbe) 
840d482003-03-18Henrik Grubbström (Grubba) #ifdef ENODEV do { #endif errno = 0; if(pid <= 0) pid=MY_WAIT_ANY(&status, 0|WUNTRACED);
d561d61999-03-07Fredrik Hübinette (Hubbe) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait thread: pid=%d status=%d errno=%d\n", getpid(), pid, status, errno);
0d7c542014-05-20Per Hedbor 
840d482003-03-18Henrik Grubbström (Grubba) #ifdef ENODEV /* FreeBSD threads are broken, and sometimes * signals status 0, errno ENODEV on living processes. */
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(errno == ENODEV));
840d482003-03-18Henrik Grubbström (Grubba) #endif
70e9781999-03-06Fredrik Hübinette (Hubbe)  if(pid>0) {
9282542003-05-17Henrik Grubbström (Grubba) #if defined(HAVE_PTRACE) && \ (defined(SIGPROF) || \ defined(_W_SLWTED) || defined(_W_SEWTED) || defined(_W_SFWTED)) if (WIFSTOPPED(status) &&
7a24f52003-05-17Henrik Grubbström (Grubba) #if !defined(_W_SLWTED) && !defined(_W_SEWTED) && !defined(_W_SFWTED)
52531f2003-05-17Henrik Grubbström (Grubba)  /* FreeBSD sends spurious SIGPROF signals to the child process * which interferes with the process trace startup code. */
baf4c22003-05-23Henrik Grubbström (Grubba)  ((WSTOPSIG(status) == SIGPROF) ||
f9cc132003-05-22Henrik Grubbström (Grubba)  /* FreeBSD is further broken in that it catches SIGKILL, and * it even does it twice, so that two PTRACE_CONT(9) are * required before the traced process dies. This makes it a * bit hard to kill traced processes... */
baf4c22003-05-23Henrik Grubbström (Grubba)  (WSTOPSIG(status) == SIGKILL))
9282542003-05-17Henrik Grubbström (Grubba) #else
52531f2003-05-17Henrik Grubbström (Grubba)  /* AIX has these... * _W_SLWTED Stopped after Load Wait TracED. * _W_SEWTED Stopped after Exec Wait TracED. * _W_SFWTED Stopped after Fork Wait TracED. * * Ignore them for now. */
9282542003-05-17Henrik Grubbström (Grubba)  ((status & 0xff) != 0x7f) #endif ) {
52531f2003-05-17Henrik Grubbström (Grubba) #if !defined(_W_SLWTED) && !defined(_W_SEWTED) && !defined(_W_SFWTED)
392e4b2004-04-01Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait thread: Got signal %d from pid %d\n", getpid(), WSTOPSIG(status), pid);
392e4b2004-04-01Henrik Grubbström (Grubba) 
f9cc132003-05-22Henrik Grubbström (Grubba)  ptrace(PTRACE_CONT, pid, CAST_TO_PTRACE_ADDR(1), WSTOPSIG(status));
f6fd612003-05-17Henrik Grubbström (Grubba) #else /* defined(_W_SLWTED) || defined(_W_SEWTED) || defined(_W_SFWTED) */
392e4b2004-04-01Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait thread: Got L/E/F status (0x%08x) from pid %d\n", getpid(), status, pid);
392e4b2004-04-01Henrik Grubbström (Grubba) 
f6fd612003-05-17Henrik Grubbström (Grubba)  ptrace(PTRACE_CONT, pid, CAST_TO_PTRACE_ADDR(1), 0); #endif /* !defined(_W_SLWTED) && !defined(_W_SEWTED) && !defined(_W_SFWTED) */
a4b2dd2003-03-16Henrik Grubbström (Grubba)  continue; }
9282542003-05-17Henrik Grubbström (Grubba) #endif /* HAVE_PTRACE && (SIGPROF || _W_SLWTED || _W_SEWTED || _W_SFWTED) */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait thread: locking interpreter, pid=%d\n", getpid(), pid);
915d091999-04-23Henrik Grubbström (Grubba) 
bc21dc2001-11-01Martin Stjernholm  low_mt_lock_interpreter(); /* Can run even if threads_disabled. */
915d091999-04-23Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait thread: reporting the event!\n", getpid());
392e4b2004-04-01Henrik Grubbström (Grubba) 
b143542003-02-28Henrik Grubbström (Grubba)  report_child(pid, status, "wait_thread");
70e9781999-03-06Fredrik Hübinette (Hubbe)  co_broadcast(& process_status_change);
c91f892000-04-19Martin Stjernholm  mt_unlock_interpreter();
d561d61999-03-07Fredrik Hübinette (Hubbe)  continue; } if(pid == -1) {
42c95b2003-03-03Henrik Grubbström (Grubba)  switch(err)
d561d61999-03-07Fredrik Hübinette (Hubbe)  {
940a4b2005-05-25Henrik Grubbström (Grubba) #if 0 case 0: /* Some versions of FreeBSD have a waitpid that fails with * errno 0. See [bug 3917]. */ #endif /* 0 */
d561d61999-03-07Fredrik Hübinette (Hubbe)  case EINTR: case ECHILD: break; default:
42c95b2003-03-03Henrik Grubbström (Grubba)  fprintf(stderr,"Wait thread: waitpid returned error: %d\n",err);
d561d61999-03-07Fredrik Hübinette (Hubbe)  }
70e9781999-03-06Fredrik Hübinette (Hubbe)  } } } #endif
eb9a042001-08-14Martin Nilsson /*! @module Process */ /*! @class create_process *! This is the recommended and most portable way to start processes *! in Pike. The process object is a pike abstraction of the running *! system process, with methods for various process housekeeping.
0995032011-09-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[Process]
685fb62001-01-31Henrik Grubbström (Grubba)  */
70e9781999-03-06Fredrik Hübinette (Hubbe) 
dad69b2003-03-01Henrik Grubbström (Grubba) /*! @decl int wait()
b143542003-02-28Henrik Grubbström (Grubba)  *! Waits for the process to end. *!
0b3a1b2002-10-31Johan Sundström  *! @returns
b143542003-02-28Henrik Grubbström (Grubba)  *! @int *! @value 0.. *! The exit code of the process. *! @value -1 *! The process was killed by a signal.
9cb49c2007-10-04Henrik Grubbström (Grubba)  *! @value -2 *! The process is stopped.
b143542003-02-28Henrik Grubbström (Grubba)  *! @endint
dad69b2003-03-01Henrik Grubbström (Grubba)  *!
992ac62003-03-13Martin Nilsson  *! @seealso
dad69b2003-03-01Henrik Grubbström (Grubba)  *! @[TraceProcess()->wait()]
685fb62001-01-31Henrik Grubbström (Grubba)  */
85f59e1998-01-08Fredrik Hübinette (Hubbe) static void f_pid_status_wait(INT32 args) { if(THIS->pid == -1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("This process object has no process associated with it.\n");
b143542003-02-28Henrik Grubbström (Grubba) 
85f59e1998-01-08Fredrik Hübinette (Hubbe) #ifdef __NT__ { int err=0; DWORD xcode; HANDLE h=THIS->handle; THREADS_ALLOW(); while(1) { if(GetExitCodeProcess(h, &xcode)) { if(xcode == STILL_ACTIVE) { WaitForSingleObject(h, INFINITE); }else{ break; } }else{ err=1; break; } } THREADS_DISALLOW(); if(err)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to get status of process.\n");
42c95b2003-03-03Henrik Grubbström (Grubba)  pop_n_elems(args);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  push_int(xcode); } #else
1abbfb2006-07-05Martin Stjernholm  {
2209de2013-01-18Stephen R. van den Berg  int wait_for_stopped, alreadydied = 0;
cb5e3a2004-04-01Henrik Grubbström (Grubba)  if (THIS->pid == getpid()) Pike_error("Waiting for self.\n");
42c95b2003-03-03Henrik Grubbström (Grubba)  /* NB: This function also implements TraceProcess()->wait(). */ wait_for_stopped = THIS->flags & PROCESS_FLAG_TRACED;
a4b2dd2003-03-16Henrik Grubbström (Grubba)  while((THIS->state == PROCESS_RUNNING) || (!wait_for_stopped && (THIS->state == PROCESS_STOPPED)))
70e9781999-03-06Fredrik Hübinette (Hubbe)  {
b4b3a82015-07-31Martin Nilsson #ifdef USE_WAIT_THREAD
70e9781999-03-06Fredrik Hübinette (Hubbe)  SWAP_OUT_CURRENT_THREAD();
b4b3a82015-07-31Martin Nilsson  co_wait_interpreter( & process_status_change);
70e9781999-03-06Fredrik Hübinette (Hubbe)  SWAP_IN_CURRENT_THREAD();
b4b3a82015-07-31Martin Nilsson #else int err; int pid = THIS->pid; WAITSTATUSTYPE status;
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait(%d): Waiting for child...\n", getpid(), pid);
b4b3a82015-07-31Martin Nilsson  THREADS_ALLOW(); pid = WAITPID(pid, &status, 0|WUNTRACED); err = errno; THREADS_DISALLOW(); if(pid > 0) { report_child(pid, status, "->wait"); } else if(pid<0) { switch(err) { case EINTR: break; #if defined(_REENTRANT) || defined(USE_SIGCHILD) case ECHILD: /* If there is a SIGCHILD handler, it might have reaped * the child before the call to WAITPID() above. */ /* Linux stupidity... * child might be forked by another thread (aka process). * * SIGCHILD will be sent to all threads on Linux. * The sleep in the loop below will thus be awakened by EINTR. * * But not if there's a race or if Linux has gotten more * POSIX compliant (>= 2.4), so don't sleep too long * unless we can poll the wait data pipe. /mast */ pid = THIS->pid; if ((THIS->state == PROCESS_RUNNING) || (!wait_for_stopped && (THIS->state == PROCESS_STOPPED))) { struct pid_status *this = THIS; int killret, killerr; THREADS_ALLOW(); while ((!(killret = kill(pid, 0), killerr = errno, killret)) && (!wait_for_stopped || (this->state != PROCESS_STOPPED))) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait(%d): Sleeping...\n", getpid(), pid);
b4b3a82015-07-31Martin Nilsson #ifdef HAVE_POLL { struct pollfd pfd[1]; #ifdef NEED_SIGNAL_SAFE_FIFO pfd[0].fd = wait_fd[0]; pfd[0].events = POLLIN; poll (pfd, 1, 10000); #else poll(pfd, 0, 100); #endif } #else /* !HAVE_POLL */ /* FIXME: If this actually gets used then we really * ought to do better here. :P */ sleep(1); #endif /* HAVE_POLL */ } THREADS_DISALLOW(); if (killret && killerr == ESRCH) { if (alreadydied) goto lostchild; /* But if we already looped, punt */ alreadydied = 1; /* We try looping once, to cover for races */ } } /* The process has died. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait(%d): Process dead.\n", getpid(), pid);
b4b3a82015-07-31Martin Nilsson  if ((THIS->state == PROCESS_RUNNING) || (!wait_for_stopped && THIS->state == PROCESS_STOPPED)) { /* The child hasn't been reaped yet. * Try waiting some more, and if that * doesn't work, let the main loop complain. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait(%d): ... but not officially, yet.\n" "[%d] wait(%d): Sleeping some more...\n", getpid(), pid, getpid(), pid);
b4b3a82015-07-31Martin Nilsson  THREADS_ALLOW(); #ifdef HAVE_POLL poll(NULL, 0, 100); #else /* !HAVE_POLL */ sleep(1); #endif /* HAVE_POLL */ THREADS_DISALLOW(); /* We can get here if several threads are waiting on the * same process, or if the second sleep above wasn't enough * for receive_sigchild to put the entry into the wait_data * fifo. In either case we just loop and try again. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] wait(%d): Child isn't reaped yet, looping.\n", getpid(), pid);
b4b3a82015-07-31Martin Nilsson  } break; #endif /* _REENTRANT || USE_SIGCHILD */ default: lostchild: Pike_error("Lost track of a child (pid %d, errno from wait %d).\n", THIS->pid, err); break; } } else { /* This should not happen! */ Pike_fatal("Pid = 0 in waitpid(%d)\n",pid); } #endif
3cad0a2013-01-01Henrik Grubbström (Grubba)  check_threads_etc();
cb5e3a2004-04-01Henrik Grubbström (Grubba)  }
42c95b2003-03-03Henrik Grubbström (Grubba)  pop_n_elems(args);
b143542003-02-28Henrik Grubbström (Grubba)  if (THIS->state == PROCESS_STOPPED) { push_int(-2); } else { push_int(THIS->result); }
1abbfb2006-07-05Martin Stjernholm  }
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif /* __NT__ */
f010202011-11-16Tobias S. Josefowitz  INVALIDATE_CURRENT_TIME();
cb22561995-10-11Fredrik Hübinette (Hubbe) }
b143542003-02-28Henrik Grubbström (Grubba) /*! @decl int(-1..2) status() *! Returns the status of the process:
0b3a1b2002-10-31Johan Sundström  *! @int *! @value -1 *! Unknown *! @value 0 *! Running *! @value 1
b143542003-02-28Henrik Grubbström (Grubba)  *! Stopped *! @value 2
0b3a1b2002-10-31Johan Sundström  *! Exited *! @endint
685fb62001-01-31Henrik Grubbström (Grubba)  */
85f59e1998-01-08Fredrik Hübinette (Hubbe) static void f_pid_status_status(INT32 args) { pop_n_elems(args); #ifdef __NT__ { DWORD x; if(GetExitCodeProcess(THIS->handle, &x)) { push_int( x == STILL_ACTIVE ? PROCESS_RUNNING : PROCESS_EXITED); }else{ push_int(PROCESS_UNKNOWN); } } #else push_int(THIS->state); #endif }
b143542003-02-28Henrik Grubbström (Grubba) /*! @decl int(0..) last_signal() *! Returns the last signal that was sent to the process. */ static void f_pid_status_last_signal(INT32 args) { pop_n_elems(args); #ifdef __NT__ push_int(0); #else push_int(THIS->sig); #endif }
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl int pid()
0b3a1b2002-10-31Johan Sundström  *! Returns the process identifier of the process.
685fb62001-01-31Henrik Grubbström (Grubba)  */
85f59e1998-01-08Fredrik Hübinette (Hubbe) static void f_pid_status_pid(INT32 args) { pop_n_elems(args); push_int(THIS->pid); }
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl int set_priority(string priority)
0b3a1b2002-10-31Johan Sundström  *! Sets the priority of the process. @[priority] is one of the strings *! @dl *! @item "realtime" *! @item "highest" *! @item "higher" *! @item "high"
2d3e792014-10-08Per Cederqvist  *! @item "normal"
0b3a1b2002-10-31Johan Sundström  *! @item "low" *! @item "lowest" *! @enddl
685fb62001-01-31Henrik Grubbström (Grubba)  */
72850a1999-02-01Per Hedbor static void f_pid_status_set_priority(INT32 args) { char *to; int r;
8111162003-09-07Martin Nilsson 
c91b1d2018-08-05Martin Nilsson  get_all_args(NULL, args, "%s", &to);
72850a1999-02-01Per Hedbor  r = set_priority( THIS->pid, to ); pop_n_elems(args); push_int(r); }
685fb62001-01-31Henrik Grubbström (Grubba) 
b143542003-02-28Henrik Grubbström (Grubba) 
dad69b2003-03-01Henrik Grubbström (Grubba) /*! @endclass */
b143542003-02-28Henrik Grubbström (Grubba) #ifdef HAVE_PTRACE
dad69b2003-03-01Henrik Grubbström (Grubba)  /*! @class TraceProcess *! *! Class that enables tracing of processes. *! *! The new process will be started in stopped state. *! Use @[cont()] to let it start executing. *! *! @note *! This class currently only exists on systems that *! implement @tt{ptrace()@}. */ /*! @decl inherit create_process */ /* NB: The code below can use THIS only because * pid_status_program is inherited first. */
74dfe82012-12-30Jonas Walldén static void init_trace_process(struct object *UNUSED(o))
dad69b2003-03-01Henrik Grubbström (Grubba) { THIS->flags |= PROCESS_FLAG_TRACED; }
74dfe82012-12-30Jonas Walldén static void exit_trace_process(struct object *UNUSED(o))
dad69b2003-03-01Henrik Grubbström (Grubba) { /* FIXME: Detach the process? */ } /*! @decl int wait() *! Waits for the process to stop. *! *! @returns *! @int *! @value 0.. *! The exit code of the process. *! @value -1 *! The process was killed by a signal. *! @value -2 *! The process has stopped. *! @endint *! *! @seealso *! @[create_process::wait()] */ /*! @decl void cont(int|void signal)
b143542003-02-28Henrik Grubbström (Grubba)  *! Allow a traced process to continue. *! *! @param signal *! Deliver this signal to the process. *! *! @note
dad69b2003-03-01Henrik Grubbström (Grubba)  *! This function may only be called for stopped processes.
b143542003-02-28Henrik Grubbström (Grubba)  *!
dad69b2003-03-01Henrik Grubbström (Grubba)  *! @seealso *! @[wait()]
b143542003-02-28Henrik Grubbström (Grubba)  */
dad69b2003-03-01Henrik Grubbström (Grubba) static void f_trace_process_cont(INT32 args)
b143542003-02-28Henrik Grubbström (Grubba) { int cont_signal = 0;
8111162003-09-07Martin Nilsson 
b143542003-02-28Henrik Grubbström (Grubba)  if(THIS->pid == -1) Pike_error("This process object has no process associated with it.\n"); if (THIS->state != PROCESS_STOPPED) { if (THIS->state == PROCESS_RUNNING) { Pike_error("Process already running.\n"); } Pike_error("Process not stopped\n"); }
017b572011-10-28Henrik Grubbström (Grubba)  if (args && TYPEOF(Pike_sp[-args]) == PIKE_T_INT) {
b143542003-02-28Henrik Grubbström (Grubba)  cont_signal = Pike_sp[-args].u.integer; } THIS->state = PROCESS_RUNNING;
ab6e692003-04-06Henrik Grubbström (Grubba)  /* The addr argument must be 1 for this request. */ if (ptrace(PTRACE_CONT, THIS->pid, CAST_TO_PTRACE_ADDR(1), cont_signal) == -1) { int err = errno; THIS->state = PROCESS_STOPPED; /* FIXME: Better diagnostics. */
5272b22004-09-22Martin Stjernholm  Pike_error("Failed to release process: %s (errno %d)\n", strerror (err), err);
b143542003-02-28Henrik Grubbström (Grubba)  }
f9cc132003-05-22Henrik Grubbström (Grubba)  #ifdef __FreeBSD__ /* Traced processes on FreeBSD have a tendency not to die * of cont(SIGKILL) unless they get some help... */ if (cont_signal == SIGKILL) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] cont(): Continue with SIGKILL for pid %d on FreeBSD\n", getpid(), THIS->pid);
f9cc132003-05-22Henrik Grubbström (Grubba)  if (kill(THIS->pid, SIGKILL) == -1) { int err = errno;
baf4c22003-05-23Henrik Grubbström (Grubba)  if (err != ESRCH) { Pike_error("Failed to kill process. errno:%d\n", err); }
f9cc132003-05-22Henrik Grubbström (Grubba)  } } #endif /* __FreeBSD__ */
b143542003-02-28Henrik Grubbström (Grubba) }
dad69b2003-03-01Henrik Grubbström (Grubba)  /*! @decl void exit() *! Cause the traced process to exit. *! *! @note *! This function may only be called for stopped processes. *! *! @seealso *! @[cont()], @[wait()] */ static void f_trace_process_exit(INT32 args) { if(THIS->pid == -1) Pike_error("This process object has no process associated with it.\n"); if (THIS->state != PROCESS_STOPPED) { if (THIS->state == PROCESS_EXITED) { Pike_error("Process already exited.\n"); } Pike_error("Process not stopped\n"); } if (ptrace(PTRACE_KILL, THIS->pid, NULL, 0) == -1) { int err = errno; /* FIXME: Better diagnostics. */ Pike_error("Failed to exit process. errno:%d\n", err); } pop_n_elems(args); }
b143542003-02-28Henrik Grubbström (Grubba) 
4499d52003-03-06Henrik Grubbström (Grubba) #if 0 /* Disabled for now. */ /*! @class Registers *! Interface to the current register contents of *! a stopped process. *! *! @seealso *! @[TraceProcess] */ /* NB: No storage needed, all state is in the parent object. */
13e2ba2014-04-26Henrik Grubbström (Grubba) #define THIS_PROC_REG_PROC_ID ((struct pid_status *)parent_storage(1, pid_status_program))
4499d52003-03-06Henrik Grubbström (Grubba)  /*! @decl int `[](int regno) *! Get the contents of register @[regno]. */ static void f_proc_reg_index(INT32 args) { struct pid_status *proc = THIS_PROC_REG_PROC_ID;
a92ad62003-10-13Henrik Grubbström (Grubba)  INT_TYPE regno = 0;
4499d52003-03-06Henrik Grubbström (Grubba)  long val; if(proc->pid == -1) Pike_error("This process object has no process associated with it.\n"); if (proc->state != PROCESS_STOPPED) { if (proc->state == PROCESS_EXITED) { Pike_error("Process has exited.\n"); } Pike_error("Process not stopped.\n"); }
c91b1d2018-08-05Martin Nilsson  get_all_args(NULL, args, "%+", &regno);
4499d52003-03-06Henrik Grubbström (Grubba) 
111b1d2014-08-22Martin Nilsson  if (regno * sizeof(long) > sizeof(((struct user *)NULL)->regs))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("`[]", 1, "register number");
4499d52003-03-06Henrik Grubbström (Grubba)  if ((val = ptrace(PTRACE_PEEKUSER, proc->pid,
d2361e2003-06-30Martin Stjernholm  ((long *)(((struct user *)NULL)->regs)) + regno, 0)) == -1) {
4499d52003-03-06Henrik Grubbström (Grubba)  int err = errno; /* FIXME: Better diagnostics. */ if (errno) { Pike_error("Failed to exit process. errno:%d\n", err); } } pop_n_elems(args); push_int64(val); } /*! @endclass */ #endif /* 0 */
685fb62001-01-31Henrik Grubbström (Grubba) /*! @endclass */
dad69b2003-03-01Henrik Grubbström (Grubba) #endif /* HAVE_PTRACE */
eb9a042001-08-14Martin Nilsson /*! @endmodule */
0c95942018-01-12Stephen R. van den Berg #ifdef __amigaos__ extern struct DosLibrary *DOSBase; #ifdef __amigaos4__ extern struct DOSIFace *IDOS; #endif static BPTR get_amigados_handle(struct mapping *optional, char *name, int fd) { char buf[32]; long ext; struct svalue *tmp; BPTR b; if(optional && (tmp=simple_mapping_string_lookup(optional, name))) { if(TYPEOF(*tmp) == T_OBJECT) { fd = fd_from_object(tmp->u.object); if(fd == -1) Pike_error("File for %s is not open.\n",name); } } #ifdef __ixemul__ if((ext = fcntl(fd, F_EXTERNALIZE, 0)) < 0) Pike_error("File for %s can not be externalized.\n", name); sprintf(buf, "IXPIPE:%lx", ext); /* It's a kind of magic... */ if((b = Open(buf, 0x4242)) == 0) Pike_error("File for %s can not be internalized.\n", name); return b; #else /* FIXME! */ return MKBADDR(NULL); #endif } struct perishables { BPTR stdin_b; BPTR stdout_b; BPTR stderr_b; BPTR cwd_lock; struct byte_buffer cmd_buf; }; static void free_perishables(struct perishables *storage) { if(storage->stdin_b!=0) Close(storage->stdin_b); if(storage->stdout_b!=0) Close(storage->stdout_b); if(storage->stderr_b!=0) Close(storage->stderr_b); if(storage->cwd_lock!=0) UnLock(storage->cwd_lock); buffer_free(&storage->cmd_buf); } #else /* !__amigaos__ */
85f59e1998-01-08Fredrik Hübinette (Hubbe) #ifdef __NT__
65c26d2018-04-26Henrik Grubbström (Grubba) /* NB: Handles returned by this function are only safe as * long as the interpreter lock isn't released. */
864d3c1998-01-29Fredrik Hübinette (Hubbe) static HANDLE get_inheritable_handle(struct mapping *optional, char *name,
1797d92020-02-10Henrik Grubbström (Grubba)  int for_reading, HPCON *conpty)
85f59e1998-01-08Fredrik Hübinette (Hubbe) {
bd67392015-10-14Martin Nilsson  HANDLE ret = INVALID_HANDLE_VALUE;
fc68462002-10-31Henrik Grubbström (Grubba)  struct svalue *save_stack=Pike_sp;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  struct svalue *tmp; if((tmp=simple_mapping_string_lookup(optional, name))) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp) == T_OBJECT)
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
965cb11998-04-06Fredrik Hübinette (Hubbe)  INT32 fd=fd_from_object(tmp->u.object);
65c26d2018-04-26Henrik Grubbström (Grubba)  HANDLE h;
1797d92020-02-10Henrik Grubbström (Grubba)  int type;
5a7ab61998-01-31Fredrik Hübinette (Hubbe) 
965cb11998-04-06Fredrik Hübinette (Hubbe)  if(fd == -1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File for %s is not open.\n",name);
965cb11998-04-06Fredrik Hübinette (Hubbe)  if(!(fd_query_properties(fd, 0) & fd_INTERPROCESSABLE)) { void create_proxy_pipe(struct object *o, int for_reading);
13670c2015-05-25Martin Nilsson 
965cb11998-04-06Fredrik Hübinette (Hubbe)  create_proxy_pipe(tmp->u.object, for_reading);
fc68462002-10-31Henrik Grubbström (Grubba)  fd=fd_from_object(Pike_sp[-1].u.object);
965cb11998-04-06Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
1797d92020-02-10Henrik Grubbström (Grubba)  if(fd_to_handle(fd, &type, &h, 0) < 0)
65c26d2018-04-26Henrik Grubbström (Grubba)  Pike_error("File for %s is not open.\n",name);
13670c2015-05-25Martin Nilsson 
1797d92020-02-10Henrik Grubbström (Grubba)  if (type == FD_PTY) { struct my_pty *pty = (struct my_pty *)h; if (!conpty || pty->conpty || !pty->other || !pty->other->conpty || (*conpty && (*conpty != pty->other->conpty))) { /* Master side, or detached slave, * or we have already selected a different conpty. */ if (for_reading) {
8587702020-02-10Henrik Grubbström (Grubba)  h = pty->read_pipe;
1797d92020-02-10Henrik Grubbström (Grubba)  } else {
8587702020-02-10Henrik Grubbström (Grubba)  h = pty->write_pipe;
1797d92020-02-10Henrik Grubbström (Grubba)  } } else { /* Slave side. Get the conpty from the master side. *
d59f122020-02-13Henrik Grubbström (Grubba)  * NB: Stdin, stdout and stderr are handled automatically * by setting the conpty. The conpty has duplicated * handles of the original pipes, and in turn provides * actual CONSOLE handles to the subprocess. We thus * do NOT return the base pipe handle.
1797d92020-02-10Henrik Grubbström (Grubba)  * * BUGS: It is not possible to have multiple conpty * objects for the same process, so the first * pty for stdin, stdout and stderr wins * (see above).
d59f122020-02-13Henrik Grubbström (Grubba)  *
126a972020-02-19Henrik Grubbström (Grubba)  * BUGS: As the conpty is a separate process that may survive * our subprocess terminating, we need to keep track
d59f122020-02-13Henrik Grubbström (Grubba)  * of which master pty the process was bound to so * that we can close the corresponding conpty * when no one else will use it.
126a972020-02-19Henrik Grubbström (Grubba)  * * BUGS: The above behavior is apparently a bug according * to the ConPTY developers. Fixing the bug however * leads to a race condition with respect to short- * lived processes causing the ConPTY to terminate * before we have closed out slave connection.
1797d92020-02-10Henrik Grubbström (Grubba)  */
d59f122020-02-13Henrik Grubbström (Grubba)  pid_status_link_pty(THIS, pty->other);
1797d92020-02-10Henrik Grubbström (Grubba)  *conpty = pty->other->conpty; release_fd(fd);
d59f122020-02-13Henrik Grubbström (Grubba)  /* From the documentation for GetStdHandle(): * * If the existing value of the standard handle is NULL, or * the existing value of the standard handle looks like a * console pseudohandle, the handle is replaced with a * console handle. * * This is not documented in conjunction with CreateProcess() or * PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, but it seems to work. */ return 0;
1797d92020-02-10Henrik Grubbström (Grubba)  } }
8d60122000-10-08Henrik Grubbström (Grubba)  if(!DuplicateHandle(GetCurrentProcess(), /* Source process */
65c26d2018-04-26Henrik Grubbström (Grubba)  h,
8d60122000-10-08Henrik Grubbström (Grubba)  GetCurrentProcess(), /* Target process */ &ret, 0, /* Access */ 1,
65c26d2018-04-26Henrik Grubbström (Grubba)  DUPLICATE_SAME_ACCESS)) { release_fd(fd); /* This could cause handle-leaks */ Pike_error("Failed to duplicate handle %d.\n", GetLastError()); } release_fd(fd);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  } }
fc68462002-10-31Henrik Grubbström (Grubba)  pop_n_elems(Pike_sp-save_stack);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  return ret; } #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) #ifndef __NT__
72850a1999-02-01Per Hedbor #ifdef HAVE_SETRLIMIT #include <sys/time.h>
f1e4ee2003-03-06Henrik Grubbström (Grubba) struct pike_limit
72850a1999-02-01Per Hedbor { int resource; struct rlimit rlp;
f1e4ee2003-03-06Henrik Grubbström (Grubba)  struct pike_limit *next;
72850a1999-02-01Per Hedbor }; #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) struct perishables
f087c41998-02-04Fredrik Hübinette (Hubbe) {
965cb11998-04-06Fredrik Hübinette (Hubbe)  char **env; char **argv;
72850a1999-02-01Per Hedbor 
47a7452000-01-14Henrik Grubbström (Grubba)  int *fds;
2833611998-07-09Henrik Grubbström (Grubba)  int disabled;
72850a1999-02-01Per Hedbor #ifdef HAVE_SETRLIMIT
f1e4ee2003-03-06Henrik Grubbström (Grubba)  struct pike_limit *limits;
72850a1999-02-01Per Hedbor #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) #ifdef HAVE_SETGROUPS gid_t *wanted_gids; struct array *wanted_gids_array; int num_wanted_gids;
f087c41998-02-04Fredrik Hübinette (Hubbe) #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) };
f087c41998-02-04Fredrik Hübinette (Hubbe) 
965cb11998-04-06Fredrik Hübinette (Hubbe) static void free_perishables(struct perishables *storage)
f087c41998-02-04Fredrik Hübinette (Hubbe) {
6e92231998-08-07Henrik Grubbström (Grubba)  if (storage->disabled) {
ffb70d1998-07-09Henrik Grubbström (Grubba)  exit_threads_disable(NULL);
6e92231998-08-07Henrik Grubbström (Grubba)  }
b8d9ee1998-06-30Henrik Grubbström (Grubba) 
47a7452000-01-14Henrik Grubbström (Grubba)  if (storage->fds) free(storage->fds);
72850a1999-02-01Per Hedbor  if(storage->env) free( storage->env ); if(storage->argv) free( storage->argv );
bccf0c2000-07-11David Hedbor #ifdef HAVE_SETRLIMIT
13670c2015-05-25Martin Nilsson  while(storage->limits)
72850a1999-02-01Per Hedbor  {
f1e4ee2003-03-06Henrik Grubbström (Grubba)  struct pike_limit *n = storage->limits->next;
72850a1999-02-01Per Hedbor  free( storage->limits ); storage->limits = n; }
bccf0c2000-07-11David Hedbor #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) #ifdef HAVE_SETGROUPS
72850a1999-02-01Per Hedbor  if(storage->wanted_gids) free(storage->wanted_gids);
965cb11998-04-06Fredrik Hübinette (Hubbe)  if(storage->wanted_gids_array) free_array(storage->wanted_gids_array);
f087c41998-02-04Fredrik Hübinette (Hubbe) #endif }
965cb11998-04-06Fredrik Hübinette (Hubbe) 
f087c41998-02-04Fredrik Hübinette (Hubbe) #endif
0c95942018-01-12Stephen R. van den Berg #endif #if !defined(__NT__) && !defined(__amigaos__)
77ae431998-11-29Henrik Grubbström (Grubba)  extern int pike_make_pipe(int *); /* * Errors that can be generated by the child process
80923b1999-05-01Henrik Grubbström (Grubba)  * * NOTE: 0 is reserved.
77ae431998-11-29Henrik Grubbström (Grubba)  */ #define PROCE_CHDIR 1 #define PROCE_DUP2 2 #define PROCE_SETGID 3 #define PROCE_SETGROUPS 4 #define PROCE_GETPWUID 5 #define PROCE_INITGROUPS 6 #define PROCE_SETUID 7 #define PROCE_EXEC 8
d887b61999-05-26Fredrik Hübinette (Hubbe) #define PROCE_CLOEXEC 9
47a7452000-01-14Henrik Grubbström (Grubba) #define PROCE_DUP 10
8f63852000-09-16Mirar (Pontus Hagland) #define PROCE_SETSID 11
06dda52002-08-21Marcus Comstedt #define PROCE_SETCTTY 12
6b47142003-12-05Martin Nilsson #define PROCE_CHROOT 13
493ee52004-07-02Henrik Grubbström (Grubba) #define PROCE_CLRCLOEXEC 14
77ae431998-11-29Henrik Grubbström (Grubba)  #define PROCERROR(err, id) do { int _l, _i; \ buf[0] = err; buf[1] = errno; buf[2] = id; \ for(_i = 0; _i < 3; _i += _l) { \ while (((_l = write(control_pipe[1], buf + _i, 3 - _i)) < 0) && \ (errno == EINTR)) \ ; \
941b5a2004-06-21Martin Stjernholm  if (_l < 0) exit (99 - errno); \
77ae431998-11-29Henrik Grubbström (Grubba)  } \
941b5a2004-06-21Martin Stjernholm  while((_l = close(control_pipe[1])) < 0 && errno==EINTR); \ if (_l < 0) exit (99 + errno); \
77ae431998-11-29Henrik Grubbström (Grubba)  exit(99); \ } while(0)
0c95942018-01-12Stephen R. van den Berg #endif /* !__NT__ && !__amigaos__ */
77ae431998-11-29Henrik Grubbström (Grubba) 
dedd3d1999-02-01Per Hedbor #ifdef HAVE___PRIOCNTL # include <sys/priocntl.h> # include <sys/rtpriocntl.h> # include <sys/tspriocntl.h> #else # ifdef HAVE_SCHED_SETSCHEDULER
3adb2f2000-08-28Fredrik Hübinette (Hubbe) # ifdef HAVE_SCHED_H # include <sched.h> # else # ifdef HAVE_SYS_SCHED_H # include <sys/sched.h> # endif # endif
dedd3d1999-02-01Per Hedbor # endif #endif
77ae431998-11-29Henrik Grubbström (Grubba) 
72850a1999-02-01Per Hedbor static int set_priority( int pid, char *to ) { int prilevel = 0; /* Yes, a char*. We call this function from create_process and other similar places, so a struct pike_string * is not really all that good an idea here */ if(!strcmp( to, "realtime" ) || !strcmp( to, "highest" )) prilevel = 3;
1f8eb42014-10-08Per Cederqvist  else if(!strcmp( to, "higher" ))
72850a1999-02-01Per Hedbor  prilevel = 2; else if(!strcmp( to, "high" )) prilevel = 1;
2d3e792014-10-08Per Cederqvist  else if(!strcmp( to, "normal" )) prilevel = 0;
72850a1999-02-01Per Hedbor  else if(!strcmp( to, "low" )) prilevel = -1; else if(!strcmp( to, "lowest" )) prilevel = -2;
1f8eb42014-10-08Per Cederqvist  else Pike_error("bad priority %s", to);
bebf3e2003-01-11Per Hedbor #ifdef __NT__ { HANDLE process;
da6c402004-11-20Martin Nilsson  DWORD how = NORMAL_PRIORITY_CLASS;
8d7cee2003-05-04Martin Nilsson  if( pid == getpid() || !pid ) /* pid == 0 == this process. */
bebf3e2003-01-11Per Hedbor  process = GetCurrentProcess(); else process = OpenProcess( PROCESS_SET_INFORMATION, FALSE, pid ); if( !process ) {
8d7cee2003-05-04Martin Nilsson  /* Permission denied, or no such process. */
bebf3e2003-01-11Per Hedbor  return 0; }
13670c2015-05-25Martin Nilsson 
bebf3e2003-01-11Per Hedbor  switch( prilevel ) {
da6c402004-11-20Martin Nilsson  case -1:
56a1992014-10-08Per Cederqvist # ifdef BELOW_NORMAL_PRIORITY_CLASS
da6c402004-11-20Martin Nilsson  how = BELOW_NORMAL_PRIORITY_CLASS; break;
56a1992014-10-08Per Cederqvist # endif
da6c402004-11-20Martin Nilsson  /* Fallthrough */ case -2: how = IDLE_PRIORITY_CLASS; break;
bebf3e2003-01-11Per Hedbor  case 0: how = NORMAL_PRIORITY_CLASS; break;
da6c402004-11-20Martin Nilsson  case 1:
56a1992014-10-08Per Cederqvist # ifdef ABOVE_NORMAL_PRIORITY_CLASS
da6c402004-11-20Martin Nilsson  how = ABOVE_NORMAL_PRIORITY_CLASS; break;
56a1992014-10-08Per Cederqvist # endif
da6c402004-11-20Martin Nilsson  /* Fallthrough */ case 2: how = HIGH_PRIORITY_CLASS; break;
bebf3e2003-01-11Per Hedbor  case 3: how = REALTIME_PRIORITY_CLASS; break; }
13670c2015-05-25Martin Nilsson 
bebf3e2003-01-11Per Hedbor  if( SetPriorityClass( process, how ) ) how = 1;
13670c2015-05-25Martin Nilsson  else
bebf3e2003-01-11Per Hedbor  how = 0; CloseHandle( process ); return how; } #else
56a1992014-10-08Per Cederqvist # ifdef HAVE___PRIOCNTL
72850a1999-02-01Per Hedbor  if(!pid) pid = getpid(); if( prilevel > 1 ) { /* Time to get tricky :-) */ struct { id_t pc_cid;
d4bb2a1999-05-17Fredrik Hübinette (Hubbe)  short rt_pri;
72850a1999-02-01Per Hedbor  ulong rt_tqsecs; long rt_tqnsecs; long padding[10]; } params; struct { id_t pc_cid; char pc_clname[PC_CLNMSZ]; short rt_maxpri; short _pad; long pad2[10]; } foo;
21b12a2014-09-03Martin Nilsson  memset(&params, 0, sizeof(params)); memset(&foo, 0, sizeof(foo));
72850a1999-02-01Per Hedbor  strcpy(foo.pc_clname, "RT");
6d81e41999-02-17Henrik Grubbström (Grubba)  if( priocntl((idtype_t)0, (id_t)0, PC_GETCID, (void *)(&foo)) == -1)
72850a1999-02-01Per Hedbor  return 0; params.pc_cid = foo.pc_cid; params.rt_pri = prilevel == 3 ? foo.rt_maxpri : 0; params.rt_tqsecs = 1; params.rt_tqnsecs = 0;
6d81e41999-02-17Henrik Grubbström (Grubba)  return priocntl(P_PID, (id_t)pid, PC_SETPARMS, (void *)(&params)) != -1;
72850a1999-02-01Per Hedbor  } else { struct { id_t pc_cid; pri_t ts_uprilim; pri_t ts_upri; long padding[12]; } params; struct { id_t pc_cid; char pc_clname[PC_CLNMSZ]; short ts_maxupri; short _pad; long pad2[10]; } foo;
21b12a2014-09-03Martin Nilsson  memset(&params, 0, sizeof(params)); memset(&foo, 0, sizeof(foo));
72850a1999-02-01Per Hedbor  strcpy(foo.pc_clname, "TS");
6d81e41999-02-17Henrik Grubbström (Grubba)  if( priocntl((idtype_t)0, (id_t)0, PC_GETCID, (void *)(&foo)) == -1)
72850a1999-02-01Per Hedbor  return 0; params.pc_cid = foo.pc_cid; params.ts_upri = TS_NOCHANGE; params.ts_uprilim = prilevel*foo.ts_maxupri/2;
6d81e41999-02-17Henrik Grubbström (Grubba)  return priocntl(P_PID, (id_t)pid, PC_SETPARMS, (void *)(&params)) != -1;
72850a1999-02-01Per Hedbor  }
56a1992014-10-08Per Cederqvist # else # ifdef HAVE_SCHED_SETSCHEDULER
72850a1999-02-01Per Hedbor  {
48aa6a2014-10-08Per Cederqvist  int class; int maxprio = 2; int minprio = -2;
0994f92014-10-09Martin Nilsson  struct sched_param param; memset(&param, 0, sizeof(param));
48aa6a2014-10-08Per Cederqvist  if( prilevel == 3 ) { class = SCHED_FIFO; param.sched_priority = sched_get_priority_max( class ); return !sched_setscheduler( pid, class, &param ); }
56a1992014-10-08Per Cederqvist # ifdef SCHED_RR
72850a1999-02-01Per Hedbor  if(prilevel == 2) { class = SCHED_RR;
f91b7e2014-10-08Per Cederqvist  param.sched_priority = sched_get_priority_min( class );
72850a1999-02-01Per Hedbor  return !sched_setscheduler( pid, class, &param );
f91b7e2014-10-08Per Cederqvist  }
48aa6a2014-10-08Per Cederqvist  maxprio = 1;
56a1992014-10-08Per Cederqvist # endif
23e8e52014-10-08Per Cederqvist # ifdef SCHED_IDLE if(prilevel == -2) { class = SCHED_IDLE; param.sched_priority = sched_get_priority_min( class ); return !sched_setscheduler( pid, class, &param ); } minprio = -1; # endif
48aa6a2014-10-08Per Cederqvist  class = SCHED_OTHER;
72850a1999-02-01Per Hedbor  param.sched_priority = sched_get_priority_min( class )+ (sched_get_priority_max( class )-
48aa6a2014-10-08Per Cederqvist  sched_get_priority_min( class ))/(maxprio-minprio) * (prilevel-minprio); if (sched_setscheduler( pid, class, &param ) < 0) return 0; /* When using SCHED_OTHER, we also want to use setpriority, so we don't return in here in that case. Instead, we fall through to the HAVE_SETPRIORITY (or even HAVE_NICE) code blocks, if available. */
72850a1999-02-01Per Hedbor  }
48aa6a2014-10-08Per Cederqvist  # endif # ifdef HAVE_SETPRIORITY
72850a1999-02-01Per Hedbor  {
13670c2015-05-25Martin Nilsson  if(prilevel == 3)
72850a1999-02-01Per Hedbor  prilevel = 2; errno = 0; return setpriority( PRIO_PROCESS, pid, -prilevel*10 )!=-1 || errno==0; }
48aa6a2014-10-08Per Cederqvist # else # ifdef HAVE_NICE
72850a1999-02-01Per Hedbor  if(!pid || pid == getpid()) { errno=0; return !(nice( -prilevel*10 - nice(0) ) != -1) || errno!=EPERM; }
56a1992014-10-08Per Cederqvist # endif # endif # endif
72850a1999-02-01Per Hedbor #endif return 0; }
111b1d2014-08-22Martin Nilsson /*! @decl int set_priority(string level, int(0..)|void pid)
685fb62001-01-31Henrik Grubbström (Grubba)  */
72850a1999-02-01Per Hedbor void f_set_priority( INT32 args ) {
edbaf32008-01-13Henrik Grubbström (Grubba)  INT_TYPE pid = 0;
72850a1999-02-01Per Hedbor  char *plevel;
8111162003-09-07Martin Nilsson 
111b1d2014-08-22Martin Nilsson  get_all_args("set_priority", args, "%s.%+", &plevel, &pid);
72850a1999-02-01Per Hedbor  pid = set_priority( pid, plevel ); pop_n_elems(args); push_int( pid ); }
965cb11998-04-06Fredrik Hübinette (Hubbe) 
0c95942018-01-12Stephen R. van den Berg #ifndef __amigaos__
72850a1999-02-01Per Hedbor #ifdef HAVE_SETRLIMIT
13670c2015-05-25Martin Nilsson static void internal_add_limit( struct perishables *storage,
72850a1999-02-01Per Hedbor  int limit_resource, struct svalue *limit_value ) { struct rlimit ol;
f1e4ee2003-03-06Henrik Grubbström (Grubba)  struct pike_limit *l = NULL;
fb45492014-05-20Per Hedbor  if( limit_resource < 0 ) return; /* Compat: Ignore unknown limits. */
72850a1999-02-01Per Hedbor #ifndef RLIM_SAVED_MAX getrlimit( limit_resource, &ol ); #else ol.rlim_max = RLIM_SAVED_MAX; ol.rlim_cur = RLIM_SAVED_CUR; #endif
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*limit_value) == PIKE_T_INT)
72850a1999-02-01Per Hedbor  {
f1e4ee2003-03-06Henrik Grubbström (Grubba)  l = malloc(sizeof( struct pike_limit ));
72850a1999-02-01Per Hedbor  l->rlp.rlim_max = ol.rlim_max; l->rlp.rlim_cur = limit_value->u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  } else if(TYPEOF(*limit_value) == T_MAPPING) {
72850a1999-02-01Per Hedbor  struct svalue *tmp3;
f1e4ee2003-03-06Henrik Grubbström (Grubba)  l = malloc(sizeof( struct pike_limit ));
14b8101999-02-11Henrik Grubbström (Grubba)  if((tmp3=simple_mapping_string_lookup(limit_value->u.mapping, "soft"))) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp3) == PIKE_T_INT)
7e8ea32000-08-13Henrik Grubbström (Grubba)  l->rlp.rlim_cur = (tmp3->u.integer >= 0) ? (unsigned INT32)tmp3->u.integer:(unsigned INT32)ol.rlim_cur;
72850a1999-02-01Per Hedbor  else l->rlp.rlim_cur = RLIM_INFINITY;
14b8101999-02-11Henrik Grubbström (Grubba)  } else
72850a1999-02-01Per Hedbor  l->rlp.rlim_cur = ol.rlim_cur;
14b8101999-02-11Henrik Grubbström (Grubba)  if((tmp3=simple_mapping_string_lookup(limit_value->u.mapping, "hard"))) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp3) == PIKE_T_INT)
7e8ea32000-08-13Henrik Grubbström (Grubba)  l->rlp.rlim_max = (tmp3->u.integer >= 0) ? (unsigned INT32)tmp3->u.integer:(unsigned INT32)ol.rlim_max;
72850a1999-02-01Per Hedbor  else l->rlp.rlim_max = RLIM_INFINITY;
14b8101999-02-11Henrik Grubbström (Grubba)  } else
72850a1999-02-01Per Hedbor  l->rlp.rlim_max = ol.rlim_max;
017b572011-10-28Henrik Grubbström (Grubba)  } else if(TYPEOF(*limit_value) == T_ARRAY && limit_value->u.array->size == 2) {
f1e4ee2003-03-06Henrik Grubbström (Grubba)  l = malloc(sizeof( struct pike_limit ));
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(limit_value->u.array->item[0]) == PIKE_T_INT)
72850a1999-02-01Per Hedbor  l->rlp.rlim_max = limit_value->u.array->item[0].u.integer; else l->rlp.rlim_max = ol.rlim_max;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(limit_value->u.array->item[1]) == PIKE_T_INT)
72850a1999-02-01Per Hedbor  l->rlp.rlim_cur = limit_value->u.array->item[1].u.integer; else
81d9292013-01-29Henrik Grubbström (Grubba)  l->rlp.rlim_cur = ol.rlim_cur;
017b572011-10-28Henrik Grubbström (Grubba)  } else if(TYPEOF(*limit_value) == T_STRING) {
f1e4ee2003-03-06Henrik Grubbström (Grubba)  l = malloc(sizeof(struct pike_limit));
72850a1999-02-01Per Hedbor  l->rlp.rlim_max = RLIM_INFINITY; l->rlp.rlim_cur = RLIM_INFINITY; } if(l) { l->resource = limit_resource; l->next = storage->limits; storage->limits = l; } } #endif
0c95942018-01-12Stephen R. van den Berg #endif /* __amigaos__ */
72850a1999-02-01Per Hedbor 
2b52ff2001-01-16Johan Sundström  /*! @module Process */ /*! @class create_process */
6ace4f2006-04-24Henrik Grubbström (Grubba) #ifdef HAVE_FDWALK struct fd_cleanup_info { int num_fds; int control_pipe; }; int fd_cleanup_cb(void *data, int fd) { struct fd_cleanup_info *info = data; if ((fd < 2) || (fd < info->num_fds)) return 0; #ifdef HAVE_BROKEN_F_SETFD if (fd == info->control_pipe) return 0; while ((close(fd) == -1) && (errno == EINTR)) ; #else set_close_on_exec(fd, 1); #endif
2fc55f2006-12-27Henrik Grubbström (Grubba)  return 0;
6ace4f2006-04-24Henrik Grubbström (Grubba) } #endif /* HAVE_FDWALK */
2b52ff2001-01-16Johan Sundström /*! @decl constant limit_value = int|array(int|string)|mapping(string:int|string)|string *! Each @i{limit_value@} may be either of: *! *! @dl *! @item integer *! sets current limit, max is left as it is. *! @item mapping *! ([ "hard":int, "soft":int ]) Both values are optional, *! hard <= soft. *! @item array *! ({ hard, soft }), both can be set to the string *! "unlimited". A value of -1 means 'keep the old value'. *! @item string *! The string "unlimited" sets both the hard and soft limit to unlimited *! @enddl */
b4e0fc2001-01-23David Norlin /*! @decl void create(array(string) command_args, void|mapping modifiers);
2b52ff2001-01-16Johan Sundström  *! *! @param command_args *! The command name and its command-line arguments. You do not have *! to worry about quoting them; pike does this for you. *! *! @param modifiers *! This optional mapping can can contain zero or more of the *! following parameters: *! *! @mapping *!
2fc55f2006-12-27Henrik Grubbström (Grubba)  *! @member function(Process.Process:void) "callback" *! Function called when the created process changes state. *!
ce852e2015-05-25Henrik Grubbström (Grubba)  *! Note that this function is called in a signal handler context, *! which means that it may be called by any thread at any time after *! the child process has changed state, and is thus not only called *! by the main thread when the main backend is idle. Indeed, you can *! specify a callback even if your program does not use a backend. *!
2b52ff2001-01-16Johan Sundström  *! @member string "cwd" *! Execute the command in another directory than the current *! directory of this process. Please note that if the command is *! given is a relative path, it will be relative to this directory *! rather than the current directory of this process. *!
e2eb642015-05-25Henrik Grubbström (Grubba)  *! Note also that the path is relative to the @expr{"chroot"@} if used. *!
bd9d402003-12-05Stephen R. van den Berg  *! @member string "chroot" *! Chroot to this directory before executing the command. *!
28370c2013-02-01Henrik Grubbström (Grubba)  *! Note that the current directory will be changed to @expr{"/"@} in *! the chroot environment, unless @expr{"cwd"@} above has been set. *!
2b52ff2001-01-16Johan Sundström  *! @member Stdio.File "stdin" *! @member Stdio.File "stdout" *! @member Stdio.File "stderr" *! These parameters allows you to change the standard input, output *! and error streams of the newly created process. This is *! particularly useful in combination with @[Stdio.File.pipe]. *! *! @member mapping(string:string) "env" *! This mapping will become the environment variables for the *! created process. Normally you will want to only add or change *! variables which can be achived by getting the environment mapping *! for this process with @[getenv]. See the examples section. *! *! @member int|string "uid" *! This parameter changes which user the new process will execute *! as. Note that the current process must be running as UID 0 to use *! this option. The uid can be given either as an integer as a *! string containing the login name of that user. *! *! The "gid" and "groups" for the new process will be set to the *! right values for that user unless overriden by options below. *! *! (See @[setuid] and @[getpwuid] for more info.) *! *! @member int|string "gid" *! This parameter changes the primary group for the new process. *! When the new process creates files, they will will be created *! with this group. The group can either be given as an int or a *! string containing the name of the group. (See @[setuid] *! and @[getgrgid] for more info.) *!
06dda52002-08-21Marcus Comstedt  *! @member int(0..1)|object(Stdio.File) "setsid"
cbe8c92003-04-07Martin Nilsson  *! Set this to @expr{1@} to create a new session group.
06dda52002-08-21Marcus Comstedt  *! It is also possible to set it to a File object, in which *! case a new session group will be created with this file *! as the controlling terminal.
2a82e72001-04-29Henrik Grubbström (Grubba)  *!
2b52ff2001-01-16Johan Sundström  *! @member array(int|string) "setgroups" *! This parameter allows you to the set the list of groups that the *! new process belongs to. It is recommended that if you use this *! parameter you supply at least one and no more than 16 groups. *! (Some system only support up to 8...) The groups can be given as *! gids or as strings with the group names. *! *! @member int(0..1) "noinitgroups" *! This parameter overrides a behaviour of the "uid" parameter. If *! this parameter is used, the gid and groups of the new process *! will be inherited from the current process rather than changed to *! the approperiate values for that uid. *! *! @member string "priority" *! This sets the priority of the new process, see *! @[set_priority] for more info. *! *! @member int "nice" *! This sets the nice level of the new process; the lower the *! number, the higher the priority of the process. Note that only *! UID 0 may use negative numbers. *! *! @member int(0..1) "keep_signals" *! This prevents Pike from restoring all signal handlers to their *! default values for the new process. Useful to ignore certain *! signals in the new process. *! *! @member array(Stdio.File|int(0..0)) "fds" *! This parameter allows you to map files to filedescriptors 3 and
cbe8c92003-04-07Martin Nilsson  *! up. The file @expr{fds[0]@} will be remapped to fd 3 in the new
2b52ff2001-01-16Johan Sundström  *! process, etc. *! *! @member mapping(string:limit_value) "rlimit" *! There are two values for each limit, the soft limit and the hard *! limit. Processes that do not have UID 0 may not raise the hard *! limit, and the soft limit may never be increased over the hard *! limit. The indices of the mapping indicate what limit to impose, *! and the values dictate what the limit should be. (See also
e1ea352002-02-14Martin Nilsson  *! @[System.setrlimit])
2b52ff2001-01-16Johan Sundström  *! *! @mapping *! @member limit_value "core" *! maximum core file size in bytes *! *! @member limit_value "cpu" *! maximum amount of cpu time used by the process in seconds *! *! @member limit_value "data" *! maximum heap (brk, malloc) size in bytes *! *! @member limit_value "fsize" *! maximum size of files created by the process in bytes *! *! @member limit_value "map_mem" *! maximum size of the process's mapped address space (mmap() and *! heap size) in bytes *! *! @member limit_value "mem" *! maximum size of the process's total amount of available memory *! (mmap, heap and stack size) in bytes *! *! @member limit_value "nofile" *! maximum number of file descriptors the process may create *! *! @member limit_value "stack" *! maximum stack size in bytes *! @endmapping *!
126a972020-02-19Henrik Grubbström (Grubba)  *! @member Stdio.File "conpty" *! Bind the process to the console associated with this *! pty slave. NT only. *!
2b52ff2001-01-16Johan Sundström  *! @endmapping *! *! @example *! Process.create_process(({ "/usr/bin/env" }), *! (["env" : getenv() + (["TERM":"vt100"]) ])); *!
a4bb2a2001-10-08Johan Sundström  *! @example
230dd22002-11-26Henrik Grubbström (Grubba)  *! //! Spawn a new process with the args @@[args] and optionally a *! //! standard input if you provide such a @@[Stdio.File] object. *! //! @@returns *! //! Returns the new process and a pipe from which you can read *! //! its output.
a4bb2a2001-10-08Johan Sundström  *! array(Process.Process|Stdio.File) spawn(Stdio.File|void stdin, string ... args) *! { *! Stdio.File stdout = Stdio.File(); *! mapping opts = ([ "stdout" : stdout->pipe() ]); *! if( stdin ) *! opts->stdin = stdin; *! return ({ Process.create_process( args, opts ), stdout }); *! } *!
2b52ff2001-01-16Johan Sundström  *! @note
230dd22002-11-26Henrik Grubbström (Grubba)  *! All parameters that accept both string or int input can be *! noticeably slower using a string instead of an integer; if maximum *! performance is an issue, please use integers.
2b52ff2001-01-16Johan Sundström  *!
2fc55f2006-12-27Henrik Grubbström (Grubba)  *! @note
28370c2013-02-01Henrik Grubbström (Grubba)  *! On NT the only supported modifiers are: @expr{"cwd"@},
126a972020-02-19Henrik Grubbström (Grubba)  *! @expr{"conpty"@}, @expr{"stdin"@}, @expr{"stdout"@}, @expr{"stderr"@} *! and @expr{"env"@}. All other modifiers are silently ignored.
2fc55f2006-12-27Henrik Grubbström (Grubba)  *! *! @note *! Support for @expr{"callback"@} was added in Pike 7.7.
28370c2013-02-01Henrik Grubbström (Grubba)  *! *! @note *! Chroot changing directory to @expr{"/"@} was added in Pike 7.9.
2b52ff2001-01-16Johan Sundström  */ /*! @endclass */ /*! @endmodule */
98e0832002-02-04Tomas Nilsson #ifdef __NT__ DEFINE_IMUTEX(handle_protection_mutex);
3032072002-02-04Martin Nilsson #endif /* __NT__ */
98e0832002-02-04Tomas Nilsson 
fb45492014-05-20Per Hedbor #ifdef HAVE_SETRLIMIT extern int get_limit_id( const char *limit ); #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) void f_create_process(INT32 args) { struct array *cmd=0; struct mapping *optional=0; struct svalue *tmp; int e;
d103422018-08-05Martin Nilsson  check_all_args(NULL, args, BIT_ARRAY, BIT_MAPPING | BIT_VOID, 0);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  switch(args) { default:
fc68462002-10-31Henrik Grubbström (Grubba)  optional=Pike_sp[1-args].u.mapping;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  mapping_fix_type_field(optional); if(m_ind_types(optional) & ~BIT_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad index type in argument 2 to Process->create()\n");
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
7447e72015-04-22Henrik Grubbström (Grubba) 
fc68462002-10-31Henrik Grubbström (Grubba)  case 1: cmd=Pike_sp[-args].u.array;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(cmd->size < 1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too few elements in argument array.\n");
13670c2015-05-25Martin Nilsson 
2575242004-05-14Martin Nilsson  if( (cmd->type_field & ~BIT_STRING) && (array_fix_type_field(cmd) & ~BIT_STRING) ) Pike_error("Bad argument 1 to Process().\n");
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
e0d56d2004-05-03Martin Nilsson  for(e=0;e<cmd->size;e++) if(ITEM(cmd)[e].u.string->size_shift)
13670c2015-05-25Martin Nilsson  Pike_error("Argument is not an 8-bit string.\n");
85f59e1998-01-08Fredrik Hübinette (Hubbe)  } #ifdef __NT__ {
bd67392015-10-14Martin Nilsson  HANDLE t1 = INVALID_HANDLE_VALUE; HANDLE t2 = INVALID_HANDLE_VALUE; HANDLE t3 = INVALID_HANDLE_VALUE;
d639152020-02-10Henrik Grubbström (Grubba)  STARTUPINFOEXW info;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  PROCESS_INFORMATION proc;
175ede2020-02-12Henrik Grubbström (Grubba)  int ret = 0, err;
6027742020-02-07Henrik Grubbström (Grubba)  WCHAR *filename=NULL, *command_line=NULL, *dir=NULL; WCHAR *env=NULL;
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
126c381998-04-24Fredrik Hübinette (Hubbe)  /* Quote command to allow all characters (if possible) */
1d7b371998-05-01Fredrik Hübinette (Hubbe)  /* Damn! NT doesn't have quoting! The below code attempts to * fake it */
e5d0292001-09-13Henrik Grubbström (Grubba)  /* Note: On NT the following characters are illegal in filenames: * \ / : * ? " < > | */
126c381998-04-24Fredrik Hübinette (Hubbe)  { int e,d;
c73de52020-02-07Henrik Grubbström (Grubba)  struct byte_buffer buf;
2d10fb2016-12-29Arne Goedeke  buffer_init(&buf);
126c381998-04-24Fredrik Hübinette (Hubbe)  for(e=0;e<cmd->size;e++) {
2fafca1999-07-20Fredrik Hübinette (Hubbe)  int quote=0;
83f2e31999-08-06Fredrik Hübinette (Hubbe)  if(e)
126c381998-04-24Fredrik Hübinette (Hubbe)  {
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, ' ');
1d7b371998-05-01Fredrik Hübinette (Hubbe)  }
dc10f22001-10-12Tomas Nilsson  /* If the argument begins AND ends with double quote assume * it is already correctly quoted */ if (ITEM(cmd)[e].u.string->len <= 1 || ITEM(cmd)[e].u.string->str[0] != '"' || ITEM(cmd)[e].u.string->str[ITEM(cmd)[e].u.string->len-1] != '"') {
5aa54c2014-09-03Martin Nilsson  quote=strchr(ITEM(cmd)[e].u.string->str,'"') || strchr(ITEM(cmd)[e].u.string->str,' ');
dc10f22001-10-12Tomas Nilsson  }
1d7b371998-05-01Fredrik Hübinette (Hubbe)  if(quote) {
dc10f22001-10-12Tomas Nilsson  int numslash;
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, '"');
1d7b371998-05-01Fredrik Hübinette (Hubbe) 
dc10f22001-10-12Tomas Nilsson  /* Quoting rules used by Microsoft VC startup code: * literal double quote must be preceeded by * a backslash, ONLY backslashes BEFORE double quote must be * escaped by doubling the backslashes */
1d7b371998-05-01Fredrik Hübinette (Hubbe)  for(d=0;d<ITEM(cmd)[e].u.string->len;d++)
126c381998-04-24Fredrik Hübinette (Hubbe)  {
1d7b371998-05-01Fredrik Hübinette (Hubbe)  switch(ITEM(cmd)[e].u.string->str[d]) { case '\\':
dc10f22001-10-12Tomas Nilsson  numslash = 1; /* count number of backslashes, used below */ while(++d<ITEM(cmd)[e].u.string->len && ITEM(cmd)[e].u.string->str[d] == '\\') { numslash++; } if (d >= ITEM(cmd)[e].u.string->len)
13670c2015-05-25Martin Nilsson  numslash *= 2; /* argument ends with backslashes, need to
dc10f22001-10-12Tomas Nilsson  double because we add a doubleqoute below */ else if (ITEM(cmd)[e].u.string->str[d] == '"') numslash = 2*numslash + 1; /* escape backslashes and the the doublequote */ /* insert the correct number of backslashes */ for (;numslash > 0; numslash--)
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, '\\');
dc10f22001-10-12Tomas Nilsson  /* add the character following backslash, if any */ if (d<ITEM(cmd)[e].u.string->len)
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, ITEM(cmd)[e].u.string->str[d]);
dc10f22001-10-12Tomas Nilsson 
2b24ea2000-05-23Fredrik Hübinette (Hubbe)  break;
dc10f22001-10-12Tomas Nilsson 
2b24ea2000-05-23Fredrik Hübinette (Hubbe)  case '"':
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, '\\');
dc10f22001-10-12Tomas Nilsson  /* fall through */
1d7b371998-05-01Fredrik Hübinette (Hubbe)  default:
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, ITEM(cmd)[e].u.string->str[d]);
1d7b371998-05-01Fredrik Hübinette (Hubbe)  }
126c381998-04-24Fredrik Hübinette (Hubbe)  }
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, '"');
1d7b371998-05-01Fredrik Hübinette (Hubbe)  }else{
2d10fb2016-12-29Arne Goedeke  buffer_memcpy(&buf, ITEM(cmd)[e].u.string->str, ITEM(cmd)[e].u.string->len);
126c381998-04-24Fredrik Hübinette (Hubbe)  } }
2d10fb2016-12-29Arne Goedeke  buffer_add_char( &buf, 0);
13670c2015-05-25Martin Nilsson 
83f2e31999-08-06Fredrik Hübinette (Hubbe) /* fprintf(stderr,"COM: %s\n",buf.s.str); */
e5d0292001-09-13Henrik Grubbström (Grubba)  /* NOTE: buf isn't finalized, since CreateProcess performs destructive * operations on it. */
c73de52020-02-07Henrik Grubbström (Grubba)  command_line = pike_dwim_utf8_to_utf16(buffer_get_string(&buf)); buffer_free(&buf);
126c381998-04-24Fredrik Hübinette (Hubbe)  }
e5d0292001-09-13Henrik Grubbström (Grubba)  /* FIXME: Ought to set filename properly. */
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
21b12a2014-09-03Martin Nilsson  memset(&info,0,sizeof(info));
8587702020-02-10Henrik Grubbström (Grubba)  info.StartupInfo.cb = sizeof(info);
13670c2015-05-25Martin Nilsson 
175ede2020-02-12Henrik Grubbström (Grubba) #if 0 /* CAUTION!!!! * * This function fills in several reserved fields in the * StartupInfo, which in turn cause CreateProcessW() below * to fail with error ERROR_INVALID_PARAMETER (87) when * EXTENDED_STARTUPINFO_PRESENT is set. */
d639152020-02-10Henrik Grubbström (Grubba)  GetStartupInfoW(&info.StartupInfo);
175ede2020-02-12Henrik Grubbström (Grubba) #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
98e0832002-02-04Tomas Nilsson  /* Protect inherit status for handles */ LOCK_IMUTEX(&handle_protection_mutex);
8587702020-02-10Henrik Grubbström (Grubba)  info.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); SetHandleInformation(info.StartupInfo.hStdInput, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(info.StartupInfo.hStdOutput, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(info.StartupInfo.hStdError, HANDLE_FLAG_INHERIT, 0);
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
d639152020-02-10Henrik Grubbström (Grubba)  info.lpAttributeList = NULL;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(optional) {
1797d92020-02-10Henrik Grubbström (Grubba)  HPCON conpty = (HPCON)0;
da6c402004-11-20Martin Nilsson  if( (tmp=simple_mapping_string_lookup(optional, "cwd")) )
83f2e31999-08-06Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp) == T_STRING)
83f2e31999-08-06Fredrik Hübinette (Hubbe)  {
6027742020-02-07Henrik Grubbström (Grubba)  dir = pike_dwim_utf8_to_utf16(STR0(tmp->u.string));
9245772000-06-26Martin Stjernholm  /* fprintf(stderr,"DIR: %s\n",STR0(tmp->u.string)); */
83f2e31999-08-06Fredrik Hübinette (Hubbe)  } }
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
126a972020-02-19Henrik Grubbström (Grubba)  CloseHandle(get_inheritable_handle(optional, "conpty", 1, &conpty));
1797d92020-02-10Henrik Grubbström (Grubba)  t1 = get_inheritable_handle(optional, "stdin", 1, &conpty);
3eee2e2020-02-10Henrik Grubbström (Grubba)  if(t1 != INVALID_HANDLE_VALUE) {
8587702020-02-10Henrik Grubbström (Grubba)  info.StartupInfo.hStdInput = t1; }
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
1797d92020-02-10Henrik Grubbström (Grubba)  t2 = get_inheritable_handle(optional, "stdout", 0, &conpty);
3eee2e2020-02-10Henrik Grubbström (Grubba)  if(t2 != INVALID_HANDLE_VALUE) {
8587702020-02-10Henrik Grubbström (Grubba)  info.StartupInfo.hStdOutput = t2; }
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
1797d92020-02-10Henrik Grubbström (Grubba)  t3 = get_inheritable_handle(optional, "stderr", 0, &conpty);
3eee2e2020-02-10Henrik Grubbström (Grubba)  if(t3 != INVALID_HANDLE_VALUE) {
8587702020-02-10Henrik Grubbström (Grubba)  info.StartupInfo.hStdError = t3; }
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
1797d92020-02-10Henrik Grubbström (Grubba)  if (conpty) { LPPROC_THREAD_ATTRIBUTE_LIST attrlist = NULL; SIZE_T attrlist_sz = 0; /* Hook in the pty controller. */ /* Get the required size for a single attribute. */ Pike_NT_InitializeProcThreadAttributeList(attrlist, 1, 0, &attrlist_sz); if (!(attrlist = malloc(attrlist_sz)) || !(Pike_NT_InitializeProcThreadAttributeList(attrlist, 1, 0, &attrlist_sz) && (info.lpAttributeList = attrlist)) || !Pike_NT_UpdateProcThreadAttribute(attrlist, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, conpty, sizeof(conpty), NULL, NULL)) { /* Out of memory or similar. */ if (attrlist) { err = GetLastError(); if (!info.lpAttributeList) { /* InitializeProcThreadAttributeList() failed. */ free(attrlist); } } else { /* malloc() failed. */ err = ERROR_NOT_ENOUGH_MEMORY; } goto fail; } }
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  if((tmp=simple_mapping_string_lookup(optional, "env"))) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp) == T_MAPPING)
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  { struct mapping *m=tmp->u.mapping; struct array *i,*v; int ptr=0; i=mapping_indices(m);
0912b31999-04-08Fredrik Hübinette (Hubbe)  v=mapping_values(m);
0d52dd1998-01-16Fredrik Hübinette (Hubbe) 
3f6e522001-11-13Tomas Nilsson  /* make sure the environment block is sorted */ ref_push_array(i); ref_push_array(v); f_sort(2); pop_stack();
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  for(e=0;e<i->size;e++) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(ITEM(i)[e]) == T_STRING && TYPEOF(ITEM(v)[e]) == T_STRING)
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  { check_stack(3);
7ced791998-04-09Henrik Grubbström (Grubba)  ref_push_string(ITEM(i)[e].u.string);
75367d2014-08-22Arne Goedeke  push_static_text("=");
7ced791998-04-09Henrik Grubbström (Grubba)  ref_push_string(ITEM(v)[e].u.string);
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  f_add(3); ptr++; } } free_array(i); free_array(v);
3f6e522001-11-13Tomas Nilsson  push_string(make_shared_binary_string("\0",1));
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  f_aggregate(ptr+1);
0912b31999-04-08Fredrik Hübinette (Hubbe)  push_string(make_shared_binary_string("\0",1));
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  o_multiply();
6027742020-02-07Henrik Grubbström (Grubba)  /* NB: The environment string contains lots of NUL characters, * so we must use the low-level variant here. */ env = low_dwim_utf8_to_utf16(Pike_sp[-1].u.string->str,
c844292020-02-07Henrik Grubbström (Grubba)  Pike_sp[-1].u.string->len);
6027742020-02-07Henrik Grubbström (Grubba)  pop_stack();
0d52dd1998-01-16Fredrik Hübinette (Hubbe)  } }
85f59e1998-01-08Fredrik Hübinette (Hubbe)  /* FIX: env, cleanup */ }
ba510c1998-03-27Henrik Grubbström (Grubba)  THREADS_ALLOW_UID();
83f2e31999-08-06Fredrik Hübinette (Hubbe) 
8587702020-02-10Henrik Grubbström (Grubba)  SetHandleInformation(info.StartupInfo.hStdInput, HANDLE_FLAG_INHERIT,
6027742020-02-07Henrik Grubbström (Grubba)  HANDLE_FLAG_INHERIT);
8587702020-02-10Henrik Grubbström (Grubba)  SetHandleInformation(info.StartupInfo.hStdOutput, HANDLE_FLAG_INHERIT,
6027742020-02-07Henrik Grubbström (Grubba)  HANDLE_FLAG_INHERIT);
8587702020-02-10Henrik Grubbström (Grubba)  SetHandleInformation(info.StartupInfo.hStdError, HANDLE_FLAG_INHERIT,
6027742020-02-07Henrik Grubbström (Grubba)  HANDLE_FLAG_INHERIT); ret = CreateProcessW(filename, command_line, NULL, /* process security attribute */ NULL, /* thread security attribute */ 1, /* inherithandles */
d639152020-02-10Henrik Grubbström (Grubba)  CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT, /* create flags */
6027742020-02-07Henrik Grubbström (Grubba)  env, /* environment */ dir, /* current dir */
d639152020-02-10Henrik Grubbström (Grubba)  &info.StartupInfo,
6027742020-02-07Henrik Grubbström (Grubba)  &proc);
83f2e31999-08-06Fredrik Hübinette (Hubbe)  err=GetLastError();
13670c2015-05-25Martin Nilsson 
5267bd2004-09-06Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
1797d92020-02-10Henrik Grubbström (Grubba)  fail:
76b0aa2004-09-13Henrik Grubbström (Grubba)  UNLOCK_IMUTEX(&handle_protection_mutex);
1797d92020-02-10Henrik Grubbström (Grubba)  if (info.lpAttributeList) { Pike_NT_DeleteProcThreadAttributeList(info.lpAttributeList); free(info.lpAttributeList); }
6027742020-02-07Henrik Grubbström (Grubba)  if(env) free(env); if(dir) free(dir); if(filename) free(filename);
0f87291999-05-07Fredrik Hübinette (Hubbe)  if(command_line) free(command_line);
a12f271998-01-10Fredrik Hübinette (Hubbe) #if 1
bd67392015-10-14Martin Nilsson  if(t1 != INVALID_HANDLE_VALUE) CloseHandle(t1); if(t2 != INVALID_HANDLE_VALUE) CloseHandle(t2); if(t3 != INVALID_HANDLE_VALUE) CloseHandle(t3);
a12f271998-01-10Fredrik Hübinette (Hubbe) #endif
13670c2015-05-25Martin Nilsson 
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(ret) { CloseHandle(proc.hThread); THIS->handle=proc.hProcess;
72850a1999-02-01Per Hedbor 
85f59e1998-01-08Fredrik Hübinette (Hubbe)  THIS->pid=proc.dwProcessId; }else{
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to start process (%d).\n",err);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  } }
d6ac731998-04-20Henrik Grubbström (Grubba) #else /* !__NT__ */
0c95942018-01-12Stephen R. van den Berg #ifdef __amigaos__ { ONERROR err; struct perishables storage; int d, e; storage.stdin_b = storage.stdout_b = storage.stderr_b = 0; storage.cwd_lock = 0; buffer_init(&storage.cmd_buf); SET_ONERROR(err, free_perishables, &storage); for(e=0;e<cmd->size;e++) { if(e) buffer_add_char( &storage.cmd_buf, ' '); if(strchr(STR0(ITEM(cmd)[e].u.string),'"') || strchr(STR0(ITEM(cmd)[e].u.string),' ')) { buffer_add_char( &storage.cmd_buf, '"'); for(d=0;d<ITEM(cmd)[e].u.string->len;d++) { switch(STR0(ITEM(cmd)[e].u.string)[d]) { case '*': case '"': buffer_add_char( &storage.cmd_buf, '*'); default: buffer_add_char( &storage.cmd_buf, STR0(ITEM(cmd)[e].u.string)[d]); } } buffer_add_char( &storage.cmd_buf, '"'); } else buffer_memcpy(&storage.cmd_buf, STR0(ITEM(cmd)[e].u.string), ITEM(cmd)[e].u.string->len); } buffer_add_char( &storage.cmd_buf, '\0'); if(optional && (tmp=simple_mapping_string_lookup(optional, "cwd"))) if(TYPEOF(*tmp) == T_STRING) if((storage.cwd_lock=Lock((char *)STR0(tmp->u.string), ACCESS_READ))==0) Pike_error("Failed to lock cwd \"%S\".\n", tmp->u.string); storage.stdin_b = get_amigados_handle(optional, "stdin", 0); storage.stdout_b = get_amigados_handle(optional, "stdout", 1); storage.stderr_b = get_amigados_handle(optional, "stderr", 2); PROC_FPRINTF("[%d] SystemTags(\"%s\", SYS_Asynch, TRUE, NP_Input, %p, " "NP_Output, %p, NP_Error, %p, %s, %p, TAG_END);\n", getpid(),
dfbce82019-12-15Marcus Comstedt  buffer_get_string(&storage.cmd_buf), storage.stdin_b,
0c95942018-01-12Stephen R. van den Berg  storage.stdout_b, storage.stderr_b, (storage.cwd_lock!=0? "NP_CurrentDir":"TAG_IGNORE"), storage.cwd_lock);
dfbce82019-12-15Marcus Comstedt  if(SystemTags(buffer_get_string(&storage.cmd_buf), SYS_Asynch, TRUE,
0c95942018-01-12Stephen R. van den Berg  NP_Input, storage.stdin_b, NP_Output, storage.stdout_b, NP_Error, storage.stderr_b, (storage.cwd_lock!=0? NP_CurrentDir:TAG_IGNORE), storage.cwd_lock, TAG_END)) Pike_error("Failed to start process (%ld).\n", IoErr()); UNSET_ONERROR(err); /* * Ideally, these resources should be freed here. * But that would cause dos.library to go nutzoid, so * we better not... if(storage.cwd_lock!=0) UnLock(storage.cwd_lock); buffer_free(&storage.cmd_buf); */ } #else /* !__amigaos__ */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
fc68462002-10-31Henrik Grubbström (Grubba)  struct svalue *stack_save=Pike_sp;
965cb11998-04-06Fredrik Hübinette (Hubbe)  ONERROR err; struct passwd *pw=0; struct perishables storage; int do_initgroups=1;
b143542003-02-28Henrik Grubbström (Grubba)  int do_trace=0;
8af5221998-04-30Fredrik Hübinette (Hubbe)  uid_t wanted_uid; gid_t wanted_gid;
965cb11998-04-06Fredrik Hübinette (Hubbe)  int gid_request=0;
8f63852000-09-16Mirar (Pontus Hagland)  int setsid_request=0;
b4f0221998-04-12Henrik Grubbström (Grubba)  int keep_signals = 0;
f62ab81999-06-25Fredrik Hübinette (Hubbe)  pid_t pid=-2;
77ae431998-11-29Henrik Grubbström (Grubba)  int control_pipe[2]; /* Used for communication with the child. */ char buf[4];
965cb11998-04-06Fredrik Hübinette (Hubbe) 
72850a1999-02-01Per Hedbor  int nice_val; int stds[3]; /* stdin, out and err */
06dda52002-08-21Marcus Comstedt  int cterm; /* controlling terminal */
72850a1999-02-01Per Hedbor  char *tmp_cwd; /* to CD to */
bd9d402003-12-05Stephen R. van den Berg  char *mchroot;
72850a1999-02-01Per Hedbor  char *priority = NULL;
47a7452000-01-14Henrik Grubbström (Grubba)  int *fds; int num_fds = 3;
42c95b2003-03-03Henrik Grubbström (Grubba)  int errnum = 0;
72850a1999-02-01Per Hedbor 
47a7452000-01-14Henrik Grubbström (Grubba)  stds[0] = stds[1] = stds[2] = -1;
06dda52002-08-21Marcus Comstedt  cterm = -1;
47a7452000-01-14Henrik Grubbström (Grubba)  fds = stds;
72850a1999-02-01Per Hedbor  nice_val = 0; tmp_cwd = NULL;
bd9d402003-12-05Stephen R. van den Berg  mchroot = NULL;
72850a1999-02-01Per Hedbor 
965cb11998-04-06Fredrik Hübinette (Hubbe)  storage.env=0; storage.argv=0;
ffb70d1998-07-09Henrik Grubbström (Grubba)  storage.disabled=0;
72850a1999-02-01Per Hedbor 
47a7452000-01-14Henrik Grubbström (Grubba)  storage.fds = NULL;
72850a1999-02-01Per Hedbor #ifdef HAVE_SETRLIMIT storage.limits = 0; #endif
965cb11998-04-06Fredrik Hübinette (Hubbe)  #ifdef HAVE_SETGROUPS storage.wanted_gids=0; storage.wanted_gids_array=0; #endif #ifdef HAVE_GETEUID
a9590d1998-04-21Henrik Grubbström (Grubba)  wanted_uid=geteuid();
965cb11998-04-06Fredrik Hübinette (Hubbe) #else
d171581998-04-21Henrik Grubbström (Grubba)  wanted_uid=getuid();
965cb11998-04-06Fredrik Hübinette (Hubbe) #endif
a9590d1998-04-21Henrik Grubbström (Grubba) #ifdef HAVE_GETEGID wanted_gid=getegid();
965cb11998-04-06Fredrik Hübinette (Hubbe) #else
a9590d1998-04-21Henrik Grubbström (Grubba)  wanted_gid=getgid();
965cb11998-04-06Fredrik Hübinette (Hubbe) #endif
831c4a1998-07-16Henrik Grubbström (Grubba)  SET_ONERROR(err, free_perishables, &storage);
965cb11998-04-06Fredrik Hübinette (Hubbe)  if(optional) {
2fc55f2006-12-27Henrik Grubbström (Grubba)  if ((tmp = simple_mapping_string_lookup(optional, "callback"))) { assign_svalue(&(THIS->callback), tmp); }
72850a1999-02-01Per Hedbor  if((tmp = simple_mapping_string_lookup(optional, "priority")) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_STRING)
72850a1999-02-01Per Hedbor  priority = tmp->u.string->str;
a9590d1998-04-21Henrik Grubbström (Grubba)  if((tmp = simple_mapping_string_lookup(optional, "gid")))
965cb11998-04-06Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(*tmp))
965cb11998-04-06Fredrik Hübinette (Hubbe)  {
fe2c202003-04-14Henrik Grubbström (Grubba)  case PIKE_T_INT:
965cb11998-04-06Fredrik Hübinette (Hubbe)  wanted_gid=tmp->u.integer; gid_request=1; break; #if defined(HAVE_GETGRNAM) || defined(HAVE_GETGRENT) case T_STRING: { extern void f_getgrnam(INT32); push_svalue(tmp); f_getgrnam(1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No such group.\n");
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1].u.array->item[2]) != PIKE_T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Getgrnam failed!\n");
fc68462002-10-31Henrik Grubbström (Grubba)  wanted_gid = Pike_sp[-1].u.array->item[2].u.integer;
965cb11998-04-06Fredrik Hübinette (Hubbe)  pop_stack(); gid_request=1; }
a9590d1998-04-21Henrik Grubbström (Grubba)  break;
965cb11998-04-06Fredrik Hübinette (Hubbe) #endif default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid argument for gid.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe)  } }
bd9d402003-12-05Stephen R. van den Berg  if((tmp = simple_mapping_string_lookup( optional, "chroot" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_STRING && !tmp->u.string->size_shift)
bd9d402003-12-05Stephen R. van den Berg  mchroot = tmp->u.string->str;
72850a1999-02-01Per Hedbor  if((tmp = simple_mapping_string_lookup( optional, "cwd" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_STRING && !tmp->u.string->size_shift)
72850a1999-02-01Per Hedbor  tmp_cwd = tmp->u.string->str;
8f63852000-09-16Mirar (Pontus Hagland)  if((tmp = simple_mapping_string_lookup( optional, "setsid" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  ((TYPEOF(*tmp) == PIKE_T_INT && tmp->u.integer) || (TYPEOF(*tmp) == T_OBJECT &&
06dda52002-08-21Marcus Comstedt  (cterm = fd_from_object(tmp->u.object)) >= 0)))
8f63852000-09-16Mirar (Pontus Hagland)  setsid_request=1;
47a7452000-01-14Henrik Grubbström (Grubba)  if ((tmp = simple_mapping_string_lookup( optional, "fds" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_ARRAY) {
47a7452000-01-14Henrik Grubbström (Grubba)  struct array *a = tmp->u.array; int i = a->size; if (i) { /* Don't forget stdin, stdout, and stderr */ num_fds = i+3;
dc8d022014-04-27Martin Nilsson  storage.fds = fds = xalloc(sizeof(int)*(num_fds));
47a7452000-01-14Henrik Grubbström (Grubba)  fds[0] = fds[1] = fds[2] = -1; while (i--) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(a->item[i]) == T_OBJECT) {
47a7452000-01-14Henrik Grubbström (Grubba)  fds[i+3] = fd_from_object(a->item[i].u.object); /* FIXME: Error if -1? */ } else { fds[i+3] = -1; } } } }
72850a1999-02-01Per Hedbor  if((tmp = simple_mapping_string_lookup( optional, "stdin" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_OBJECT)
72850a1999-02-01Per Hedbor  {
47a7452000-01-14Henrik Grubbström (Grubba)  fds[0] = fd_from_object( tmp->u.object ); if(fds[0] == -1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid stdin file\n");
72850a1999-02-01Per Hedbor  }
66440c1999-02-16Henrik Grubbström (Grubba)  if((tmp = simple_mapping_string_lookup( optional, "stdout" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_OBJECT)
72850a1999-02-01Per Hedbor  {
47a7452000-01-14Henrik Grubbström (Grubba)  fds[1] = fd_from_object( tmp->u.object ); if(fds[1] == -1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid stdout file\n");
72850a1999-02-01Per Hedbor  }
66440c1999-02-16Henrik Grubbström (Grubba)  if((tmp = simple_mapping_string_lookup( optional, "stderr" )) &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(*tmp) == T_OBJECT)
72850a1999-02-01Per Hedbor  {
47a7452000-01-14Henrik Grubbström (Grubba)  fds[2] = fd_from_object( tmp->u.object ); if(fds[2] == -1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid stderr file\n");
72850a1999-02-01Per Hedbor  } if((tmp = simple_mapping_string_lookup( optional, "nice"))
017b572011-10-28Henrik Grubbström (Grubba)  && TYPEOF(*tmp) == PIKE_T_INT )
72850a1999-02-01Per Hedbor  nice_val = tmp->u.integer; #ifdef HAVE_SETRLIMIT if((tmp=simple_mapping_string_lookup(optional, "rlimit"))) { struct svalue *tmp2;
fb45492014-05-20Per Hedbor  unsigned int i; struct mapping *m = tmp->u.mapping; struct keypair *k;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp) != T_MAPPING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong type of argument for the 'rusage' option. "
fb45492014-05-20Per Hedbor  "Should be mapping.\n"); NEW_MAPPING_LOOP( m->data ) if( TYPEOF(k->ind) == PIKE_T_STRING ) internal_add_limit( &storage, get_limit_id(k->ind.u.string->str), &k->val );
72850a1999-02-01Per Hedbor  }
fb45492014-05-20Per Hedbor #endif
72850a1999-02-01Per Hedbor 
965cb11998-04-06Fredrik Hübinette (Hubbe)  if((tmp=simple_mapping_string_lookup(optional, "uid"))) {
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(*tmp))
965cb11998-04-06Fredrik Hübinette (Hubbe)  {
fe2c202003-04-14Henrik Grubbström (Grubba)  case PIKE_T_INT:
965cb11998-04-06Fredrik Hübinette (Hubbe)  wanted_uid=tmp->u.integer; #if defined(HAVE_GETPWUID) || defined(HAVE_GETPWENT) if(!gid_request) {
a9590d1998-04-21Henrik Grubbström (Grubba)  extern void f_getpwuid(INT32); push_int(wanted_uid); f_getpwuid(1);
965cb11998-04-06Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) == T_ARRAY)
965cb11998-04-06Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1].u.array->item[3]) != PIKE_T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Getpwuid failed!\n");
fc68462002-10-31Henrik Grubbström (Grubba)  wanted_gid = Pike_sp[-1].u.array->item[3].u.integer;
965cb11998-04-06Fredrik Hübinette (Hubbe)  } pop_stack(); } #endif break;
fb45492014-05-20Per Hedbor 
965cb11998-04-06Fredrik Hübinette (Hubbe) #if defined(HAVE_GETPWNAM) || defined(HAVE_GETPWENT) case T_STRING: { extern void f_getpwnam(INT32); push_svalue(tmp); f_getpwnam(1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No such user.\n");
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1].u.array->item[2]) != PIKE_T_INT || TYPEOF(Pike_sp[-1].u.array->item[3]) != PIKE_T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Getpwnam failed!\n");
fc68462002-10-31Henrik Grubbström (Grubba)  wanted_uid=Pike_sp[-1].u.array->item[2].u.integer;
965cb11998-04-06Fredrik Hübinette (Hubbe)  if(!gid_request)
fc68462002-10-31Henrik Grubbström (Grubba)  wanted_gid=Pike_sp[-1].u.array->item[3].u.integer;
965cb11998-04-06Fredrik Hübinette (Hubbe)  pop_stack(); break; } #endif default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid argument for uid.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe)  } } if((tmp=simple_mapping_string_lookup(optional, "setgroups"))) { #ifdef HAVE_SETGROUPS
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp) == T_ARRAY)
965cb11998-04-06Fredrik Hübinette (Hubbe)  { storage.wanted_gids_array=tmp->u.array;
868c301998-04-21Henrik Grubbström (Grubba)  add_ref(storage.wanted_gids_array);
965cb11998-04-06Fredrik Hübinette (Hubbe)  for(e=0;e<storage.wanted_gids_array->size;e++)
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(storage.wanted_gids_array->item[e]) != PIKE_T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid type for setgroups.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe)  do_initgroups=0; }else{
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid type for setgroups.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe)  } #else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Setgroups is not available.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe) #endif } if((tmp=simple_mapping_string_lookup(optional, "env"))) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*tmp) == T_MAPPING)
965cb11998-04-06Fredrik Hübinette (Hubbe)  { struct mapping *m=tmp->u.mapping; struct array *i,*v; int ptr=0; i=mapping_indices(m); v=mapping_values(m);
fb45492014-05-20Per Hedbor 
dc8d022014-04-27Martin Nilsson  storage.env=xalloc((1+m_sizeof(m)) * sizeof(char *));
965cb11998-04-06Fredrik Hübinette (Hubbe)  for(e=0;e<i->size;e++) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(ITEM(i)[e]) == T_STRING && TYPEOF(ITEM(v)[e]) == T_STRING)
965cb11998-04-06Fredrik Hübinette (Hubbe)  { check_stack(3);
acded51998-04-09Henrik Grubbström (Grubba)  ref_push_string(ITEM(i)[e].u.string);
75367d2014-08-22Arne Goedeke  push_static_text("=");
acded51998-04-09Henrik Grubbström (Grubba)  ref_push_string(ITEM(v)[e].u.string);
965cb11998-04-06Fredrik Hübinette (Hubbe)  f_add(3);
fc68462002-10-31Henrik Grubbström (Grubba)  storage.env[ptr++]=Pike_sp[-1].u.string->str;
965cb11998-04-06Fredrik Hübinette (Hubbe)  } } storage.env[ptr++]=0; free_array(i); free_array(v); } } if((tmp=simple_mapping_string_lookup(optional, "noinitgroups")))
9f516a2001-12-16Martin Stjernholm  if(!SAFE_IS_ZERO(tmp))
965cb11998-04-06Fredrik Hübinette (Hubbe)  do_initgroups=0;
b4f0221998-04-12Henrik Grubbström (Grubba)  if((tmp=simple_mapping_string_lookup(optional, "keep_signals")))
9f516a2001-12-16Martin Stjernholm  keep_signals = !SAFE_IS_ZERO(tmp);
965cb11998-04-06Fredrik Hübinette (Hubbe)  }
dad69b2003-03-01Henrik Grubbström (Grubba)  if (THIS->flags & PROCESS_FLAG_TRACED) { /* We're inherited from TraceProcess. * Start the process in trace mode. */ do_trace = 1; }
965cb11998-04-06Fredrik Hübinette (Hubbe) #ifdef HAVE_SETGROUPS #ifdef HAVE_GETGRENT if(wanted_uid != getuid() && do_initgroups) { extern void f_get_groups_for_user(INT32); push_int(wanted_uid); f_get_groups_for_user(1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) == T_ARRAY)
965cb11998-04-06Fredrik Hübinette (Hubbe)  {
fc68462002-10-31Henrik Grubbström (Grubba)  storage.wanted_gids_array=Pike_sp[-1].u.array; Pike_sp--; dmalloc_touch_svalue(Pike_sp);
a9590d1998-04-21Henrik Grubbström (Grubba)  } else { pop_stack();
965cb11998-04-06Fredrik Hübinette (Hubbe)  } } #endif if(storage.wanted_gids_array) { int e;
6799451998-04-06Fredrik Hübinette (Hubbe)  storage.wanted_gids=(gid_t *)xalloc(sizeof(gid_t) * (storage.wanted_gids_array->size + 1)); storage.wanted_gids[0]=65534; /* Paranoia */
965cb11998-04-06Fredrik Hübinette (Hubbe)  for(e=0;e<storage.wanted_gids_array->size;e++) {
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(storage.wanted_gids_array->item[e]))
965cb11998-04-06Fredrik Hübinette (Hubbe)  {
fe2c202003-04-14Henrik Grubbström (Grubba)  case PIKE_T_INT:
965cb11998-04-06Fredrik Hübinette (Hubbe)  storage.wanted_gids[e]=storage.wanted_gids_array->item[e].u.integer; break; #if defined(HAVE_GETGRENT) || defined(HAVE_GETGRNAM) case T_STRING: { extern void f_getgrnam(INT32); ref_push_string(storage.wanted_gids_array->item[e].u.string); f_getgrnam(2);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No such group.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  storage.wanted_gids[e]=Pike_sp[-1].u.array->item[2].u.integer;
965cb11998-04-06Fredrik Hübinette (Hubbe)  pop_stack(); break; } #endif default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Gids must be integers or strings only.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe)  } } storage.num_wanted_gids=storage.wanted_gids_array->size; free_array(storage.wanted_gids_array); storage.wanted_gids_array=0; do_initgroups=0; } #endif /* HAVE_SETGROUPS */
fb45492014-05-20Per Hedbor 
965cb11998-04-06Fredrik Hübinette (Hubbe)  storage.argv=(char **)xalloc((1+cmd->size) * sizeof(char *));
77ae431998-11-29Henrik Grubbström (Grubba)  if (pike_make_pipe(control_pipe) < 0) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to create child communication pipe.\n");
77ae431998-11-29Henrik Grubbström (Grubba)  }
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] control_pipe: %d, %d\n", getpid(), control_pipe[0], control_pipe[1]);
eecd3d2003-11-21Henrik Grubbström (Grubba) #ifdef USE_WAIT_THREAD if (!wait_thread_running) { THREAD_T foo; if (th_create_small(&foo, wait_thread, 0)) { Pike_error("Failed to create wait thread!\n" "errno: %d\n", errno); } wait_thread_running = 1; } num_threads++; /* We use the interpreter lock */ #endif
71ac9e1999-08-29Fredrik Hübinette (Hubbe)  th_atfork_prepare();
f43e421999-10-21Fredrik Hübinette (Hubbe)  {
bb24ae2000-10-16Henrik Grubbström (Grubba)  int loop_cnt = 0;
f43e421999-10-21Fredrik Hübinette (Hubbe)  sigset_t new_sig, old_sig; sigfillset(&new_sig);
bfd94e2000-10-18Henrik Grubbström (Grubba)  while(sigprocmask(SIG_BLOCK, &new_sig, &old_sig)) ;
f43e421999-10-21Fredrik Hübinette (Hubbe) 
bb24ae2000-10-16Henrik Grubbström (Grubba)  do {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Forking... (pid=%d errno=%d)\n", getpid(), pid, errno);
bf782a2003-12-01Henrik Grubbström (Grubba) #ifdef HAVE_VFORK pid=vfork(); #else /* !HAVE_VFORK */
85f59e1998-01-08Fredrik Hübinette (Hubbe) #if defined(HAVE_FORK1) && defined(_REENTRANT)
bb24ae2000-10-16Henrik Grubbström (Grubba)  pid=fork1();
85f59e1998-01-08Fredrik Hübinette (Hubbe) #else
bb24ae2000-10-16Henrik Grubbström (Grubba)  pid=fork(); #endif
bf782a2003-12-01Henrik Grubbström (Grubba) #endif /* HAVE_VFORK */
bb24ae2000-10-16Henrik Grubbström (Grubba)  if (pid == -1) {
42c95b2003-03-03Henrik Grubbström (Grubba)  errnum = errno;
0d7c542014-05-20Per Hedbor  if (UNLIKELY(errnum == EAGAIN)) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Fork failed with EAGAIN\n", getpid());
bb24ae2000-10-16Henrik Grubbström (Grubba)  /* Process table full or similar. * Try sleeping for a bit. * * FIXME: Ought to release the interpreter lock. */ if (loop_cnt++ < 60) { /* Don't sleep for too long... */ #ifdef HAVE_POLL poll(NULL, 0, 100); #else /* !HAVE_POLL */ sleep(1); #endif /* HAVE_POLL */ /* Try again */ continue; }
0d7c542014-05-20Per Hedbor  } else if (UNLIKELY(errnum == EINTR)) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Fork failed with EINTR\n", getpid());
bb24ae2000-10-16Henrik Grubbström (Grubba)  /* Try again */ continue;
b3752c2001-06-20Henrik Grubbström (Grubba)  } else {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Fork failed with errno:%d\n", getpid(), errnum);
bb24ae2000-10-16Henrik Grubbström (Grubba)  } }
b3752c2001-06-20Henrik Grubbström (Grubba) #ifdef PROC_DEBUG
42c95b2003-03-03Henrik Grubbström (Grubba)  else if (pid) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Fork ok pid:%d\n", getpid(), pid);
b3752c2001-06-20Henrik Grubbström (Grubba)  } else { write(2, "Fork ok pid:0\n", 14); } #endif /* PROC_DEBUG */
bb24ae2000-10-16Henrik Grubbström (Grubba)  break; } while(1);
0f77871998-07-16Henrik Grubbström (Grubba) 
0d7c542014-05-20Per Hedbor  while(UNLIKELY(sigprocmask(SIG_SETMASK, &old_sig, 0))) {
b3752c2001-06-20Henrik Grubbström (Grubba) #ifdef PROC_DEBUG char errcode[3] = { '0'+((errno/100)%10), '0'+((errno/10)%10), '0'+(errno%10), }; write(2, "sigprocmask() failed with errno:", 32); write(2, errcode, 3); write(2, "\n", 1); #endif /* PROC_DEBUG */ }
f43e421999-10-21Fredrik Hübinette (Hubbe)  }
57f53c1999-09-25Henrik Grubbström (Grubba)  if(pid) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] th_at_fork_parent()...\n", getpid());
fec3001999-08-30Fredrik Hübinette (Hubbe)  th_atfork_parent();
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] th_at_fork_parent() done\n", getpid());
57f53c1999-09-25Henrik Grubbström (Grubba)  } else {
b3752c2001-06-20Henrik Grubbström (Grubba) #ifdef PROC_DEBUG write(2, "th_at_fork_child()...\n", 22); #endif /* PROC_DEBUG */
fec3001999-08-30Fredrik Hübinette (Hubbe)  th_atfork_child();
b3752c2001-06-20Henrik Grubbström (Grubba) #ifdef PROC_DEBUG write(2, "th_at_fork_child() done\n", 24); #endif /* PROC_DEBUG */
57f53c1999-09-25Henrik Grubbström (Grubba)  }
71ac9e1999-08-29Fredrik Hübinette (Hubbe) 
b3752c2001-06-20Henrik Grubbström (Grubba)  if (pid) { /* It's a bad idea to do this in the forked process... */ UNSET_ONERROR(err); }
0f77871998-07-16Henrik Grubbström (Grubba) 
0144fe1998-11-30Henrik Grubbström (Grubba)  if(pid == -1) { /* * fork() failed */
c5679e2015-05-07Chris Angelico  while(UNLIKELY(close(control_pipe[0]) < 0) && UNLIKELY(errno==EINTR)); while(UNLIKELY(close(control_pipe[1]) < 0) && UNLIKELY(errno==EINTR));
77ae431998-11-29Henrik Grubbström (Grubba) 
0f77871998-07-16Henrik Grubbström (Grubba)  free_perishables(&storage);
0d7c542014-05-20Per Hedbor  if (UNLIKELY(errnum == EAGAIN)) {
d3a1c82014-10-31Martin Nilsson  Pike_error("fork() failed with EAGAIN. Process table full?\n");
d951de2000-02-08Henrik Grubbström (Grubba)  } #ifdef ENOMEM
0d7c542014-05-20Per Hedbor  if (UNLIKELY(errnum == ENOMEM)) {
d3a1c82014-10-31Martin Nilsson  Pike_error("fork() failed with ENOMEM. Out of memory?\n");
d951de2000-02-08Henrik Grubbström (Grubba)  } #endif /* ENOMEM */
d3a1c82014-10-31Martin Nilsson  Pike_error("fork() failed. errno:%d\n", errnum);
0f77871998-07-16Henrik Grubbström (Grubba)  } else if(pid) {
70b5081999-05-01Henrik Grubbström (Grubba)  int olderrno;
6a9cbc2006-04-05Henrik Grubbström (Grubba)  int cnt = 0;
70b5081999-05-01Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Parent\n", getpid());
b3752c2001-06-20Henrik Grubbström (Grubba) 
70e9781999-03-06Fredrik Hübinette (Hubbe)  process_started(pid); /* Debug */
0144fe1998-11-30Henrik Grubbström (Grubba)  /* * The parent process */ /* Close our child's end of the pipe. */
0d7c542014-05-20Per Hedbor  while(UNLIKELY(close(control_pipe[1]) < 0) && UNLIKELY(errno==EINTR));
77ae431998-11-29Henrik Grubbström (Grubba) 
965cb11998-04-06Fredrik Hübinette (Hubbe)  free_perishables(&storage);
8058341998-06-25Henrik Grubbström (Grubba) 
fc68462002-10-31Henrik Grubbström (Grubba)  pop_n_elems(Pike_sp - stack_save);
965cb11998-04-06Fredrik Hübinette (Hubbe) 
70e9781999-03-06Fredrik Hübinette (Hubbe)  #ifdef USE_SIGCHILD
a4a1722000-12-05Per Hedbor  /* FIXME: Can anything of the following throw an error? */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(!signal_evaluator_callback) { signal_evaluator_callback=add_to_callback(&evaluator_callbacks, check_signals, 0,0);
424d9c1999-05-02Fredrik Hübinette (Hubbe)  dmalloc_accept_leak(signal_evaluator_callback);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }
70e9781999-03-06Fredrik Hübinette (Hubbe) #endif
0144fe1998-11-30Henrik Grubbström (Grubba)  THIS->pid = pid; THIS->state = PROCESS_RUNNING;
628cd22000-08-13Henrik Grubbström (Grubba)  ref_push_object(Pike_fp->current_object);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  push_int(pid);
fc68462002-10-31Henrik Grubbström (Grubba)  mapping_insert(pid_mapping, Pike_sp-1, Pike_sp-2);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  pop_n_elems(2);
77ae431998-11-29Henrik Grubbström (Grubba)  /* Wake up the child. */ buf[0] = 0;
46fb4a1999-09-11Fredrik Hübinette (Hubbe) 
a4b2dd2003-03-16Henrik Grubbström (Grubba)  THREADS_ALLOW();
68aab52003-03-16Henrik Grubbström (Grubba) 
bf782a2003-12-01Henrik Grubbström (Grubba) #ifndef HAVE_VFORK /* The following code won't work with a real vfork(). */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Parent: Wake up child.\n", getpid());
0d7c542014-05-20Per Hedbor  while (UNLIKELY(((e = write(control_pipe[0], buf, 1)) < 0)) && UNLIKELY(errno == EINTR))
77ae431998-11-29Henrik Grubbström (Grubba)  ;
1a68791999-03-13Henrik Grubbström (Grubba)  if(e!=1) { /* Paranoia in case close() sets errno. */
80923b1999-05-01Henrik Grubbström (Grubba)  olderrno = errno;
0d7c542014-05-20Per Hedbor  while(UNLIKELY(close(control_pipe[0]) < 0) && UNLIKELY(errno==EINTR))
a4b2dd2003-03-16Henrik Grubbström (Grubba)  ;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Child process died prematurely. (e=%d errno=%d)\n",
42c95b2003-03-03Henrik Grubbström (Grubba)  e ,olderrno);
1a68791999-03-13Henrik Grubbström (Grubba)  }
bf782a2003-12-01Henrik Grubbström (Grubba) #endif /* !HAVE_VFORK */
1e3da51999-01-07Fredrik Hübinette (Hubbe) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Parent: Wait for child...\n", getpid());
a4a1722000-12-05Per Hedbor  /* Wait for exec or error */
6a9cbc2006-04-05Henrik Grubbström (Grubba) #if defined(EBADF) && defined(EPIPE) /* Attempt to workaround spurious errors from read(2) on FreeBSD. */
0d7c542014-05-20Per Hedbor  while (UNLIKELY((e = read(control_pipe[0], buf, 3)) < 0) &&
d56a962016-09-23Tobias S. Josefowitz  (errno == EINTR || (LIKELY(errno != EBADF) && (errno != EPIPE) && (cnt++ < 16))))
6a9cbc2006-04-05Henrik Grubbström (Grubba)  ; #else /* !EBADF || !EPIPE */ /* This code *should* work... */
0d7c542014-05-20Per Hedbor  while (UNLIKELY((e = read(control_pipe[0], buf, 3)) < 0) && (errno == EINTR))
77ae431998-11-29Henrik Grubbström (Grubba)  ;
6a9cbc2006-04-05Henrik Grubbström (Grubba) #endif /* EBADF && EPIPE */
80923b1999-05-01Henrik Grubbström (Grubba)  /* Paranoia in case close() sets errno. */ olderrno = errno;
d887b61999-05-26Fredrik Hübinette (Hubbe) 
0d7c542014-05-20Per Hedbor  while(UNLIKELY(close(control_pipe[0]) < 0) && UNLIKELY(errno==EINTR));
68aab52003-03-16Henrik Grubbström (Grubba)  THREADS_DISALLOW();
46fb4a1999-09-11Fredrik Hübinette (Hubbe) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Parent: Child init done.\n", getpid());
a4b2dd2003-03-16Henrik Grubbström (Grubba) 
77ae431998-11-29Henrik Grubbström (Grubba)  if (!e) { /* OK! */
0144fe1998-11-30Henrik Grubbström (Grubba)  pop_n_elems(args);
05e4e22016-12-12Martin Nilsson  return;
c2eb242003-11-21Henrik Grubbström (Grubba)  } else if (e < 0) { /* Something went wrong with our read(2). */ #ifdef ENODEV if (olderrno == ENODEV) { /* This occurrs sometimes on FreeBSD... */
d3a1c82014-10-31Martin Nilsson  Pike_error("read(2) failed with ENODEV. Probable operating system bug.\n");
c2eb242003-11-21Henrik Grubbström (Grubba)  } #endif /* ENODEV */
d3a1c82014-10-31Martin Nilsson  Pike_error("read(2) failed with errno %d.\n", olderrno);
77ae431998-11-29Henrik Grubbström (Grubba)  } else {
c2eb242003-11-21Henrik Grubbström (Grubba)  /* Something went wrong in the child. */
64f9451998-11-29Henrik Grubbström (Grubba)  switch(buf[0]) { case PROCE_CHDIR:
28370c2013-02-01Henrik Grubbström (Grubba)  if (buf[2]) {
d3a1c82014-10-31Martin Nilsson  Pike_error("chdir(\"/\") in chroot failed. errno:%d.\n", buf[1]);
28370c2013-02-01Henrik Grubbström (Grubba)  }
d3a1c82014-10-31Martin Nilsson  Pike_error("chdir() failed. errno:%d.\n", buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break;
47a7452000-01-14Henrik Grubbström (Grubba)  case PROCE_DUP:
d3a1c82014-10-31Martin Nilsson  Pike_error("dup() failed. errno:%d.\n", buf[1]);
47a7452000-01-14Henrik Grubbström (Grubba)  break;
64f9451998-11-29Henrik Grubbström (Grubba)  case PROCE_DUP2:
ca75342000-01-27Henrik Grubbström (Grubba)  if (buf[1] == EINVAL) {
d3a1c82014-10-31Martin Nilsson  Pike_error("dup2(x, %d) failed with EINVAL.\n", buf[2]);
ca75342000-01-27Henrik Grubbström (Grubba)  }
d3a1c82014-10-31Martin Nilsson  Pike_error("dup2(x, %d) failed. errno:%d.\n", buf[2], buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break; case PROCE_SETGID:
d3a1c82014-10-31Martin Nilsson  Pike_error("setgid(%d) failed. errno:%d\n", buf[2], buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break;
bccf0c2000-07-11David Hedbor #ifdef HAVE_SETGROUPS
64f9451998-11-29Henrik Grubbström (Grubba)  case PROCE_SETGROUPS:
ca75342000-01-27Henrik Grubbström (Grubba)  if (buf[1] == EINVAL) {
d3a1c82014-10-31Martin Nilsson  Pike_error("setgroups() failed with EINVAL.\n"
42c95b2003-03-03Henrik Grubbström (Grubba)  "Too many supplementary groups (%d)?\n", storage.num_wanted_gids);
ca75342000-01-27Henrik Grubbström (Grubba)  }
d3a1c82014-10-31Martin Nilsson  Pike_error("setgroups() failed. errno:%d.\n", buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break;
bccf0c2000-07-11David Hedbor #endif
64f9451998-11-29Henrik Grubbström (Grubba)  case PROCE_GETPWUID:
d3a1c82014-10-31Martin Nilsson  Pike_error("getpwuid(%d) failed. errno:%d.\n", buf[2], buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break; case PROCE_INITGROUPS:
d3a1c82014-10-31Martin Nilsson  Pike_error("initgroups() failed. errno:%d.\n", buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break; case PROCE_SETUID:
ca75342000-01-27Henrik Grubbström (Grubba)  if (buf[1] == EINVAL) {
d3a1c82014-10-31Martin Nilsson  Pike_error("Invalid uid: %d.\n", (int)wanted_uid);
ca75342000-01-27Henrik Grubbström (Grubba)  }
d3a1c82014-10-31Martin Nilsson  Pike_error("setuid(%d) failed. errno:%d.\n", buf[2], buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break;
8f63852000-09-16Mirar (Pontus Hagland)  case PROCE_SETSID:
d3a1c82014-10-31Martin Nilsson  Pike_error("setsid() failed.\n");
8f63852000-09-16Mirar (Pontus Hagland)  break;
06dda52002-08-21Marcus Comstedt  case PROCE_SETCTTY:
d3a1c82014-10-31Martin Nilsson  Pike_error("Failed to set controlling TTY. errno:%d.\n", buf[1]);
06dda52002-08-21Marcus Comstedt  break;
64f9451998-11-29Henrik Grubbström (Grubba)  case PROCE_EXEC:
cb250e2001-10-10Henrik Grubbström (Grubba)  switch(buf[1]) { case ENOENT:
d3a1c82014-10-31Martin Nilsson  Pike_error("Executable file not found.\n");
cb250e2001-10-10Henrik Grubbström (Grubba)  break; case EACCES:
d3a1c82014-10-31Martin Nilsson  Pike_error("Access denied.\n");
cb250e2001-10-10Henrik Grubbström (Grubba)  break; #ifdef E2BIG case E2BIG:
d3a1c82014-10-31Martin Nilsson  Pike_error("Arglist too long.\n");
cb250e2001-10-10Henrik Grubbström (Grubba)  break; #endif /* E2BIG */
ca75342000-01-27Henrik Grubbström (Grubba)  }
fb45492014-05-20Per Hedbor 
d3a1c82014-10-31Martin Nilsson  Pike_error("exec() failed. errno:%d. File not found?\n", buf[1]);
64f9451998-11-29Henrik Grubbström (Grubba)  break;
d887b61999-05-26Fredrik Hübinette (Hubbe)  case PROCE_CLOEXEC:
d3a1c82014-10-31Martin Nilsson  Pike_error("set_close_on_exec(%d, 1) failed. errno:%d.\n",
493ee52004-07-02Henrik Grubbström (Grubba)  buf[2], buf[1]); break; case PROCE_CLRCLOEXEC:
d3a1c82014-10-31Martin Nilsson  Pike_error("set_close_on_exec(%d, 0) failed. errno:%d.\n",
493ee52004-07-02Henrik Grubbström (Grubba)  buf[2], buf[1]);
d887b61999-05-26Fredrik Hübinette (Hubbe)  break;
5c70db2003-12-05Henrik Grubbström (Grubba)  case PROCE_CHROOT:
d3a1c82014-10-31Martin Nilsson  Pike_error("chroot() failed. errno:%d.\n", buf[1]);
5c70db2003-12-05Henrik Grubbström (Grubba)  break;
64f9451998-11-29Henrik Grubbström (Grubba)  case 0: /* read() probably failed. */ default:
d3a1c82014-10-31Martin Nilsson  Pike_error("Child failed: %d, %d, %d, %d, %d!\n",
42c95b2003-03-03Henrik Grubbström (Grubba)  buf[0], buf[1], buf[2], e, olderrno);
64f9451998-11-29Henrik Grubbström (Grubba)  break; }
77ae431998-11-29Henrik Grubbström (Grubba)  }
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }else{
0144fe1998-11-30Henrik Grubbström (Grubba)  /* * The child process
e974952013-01-01Henrik Grubbström (Grubba)  * * NB: Avoid calling any functions in libc here, since * internal mutexes may be held by other nonforked * threads.
0144fe1998-11-30Henrik Grubbström (Grubba)  */
85f59e1998-01-08Fredrik Hübinette (Hubbe) #ifdef DECLARE_ENVIRON extern char **environ; #endif extern void my_set_close_on_exec(int,int); extern void do_set_close_on_exec(void);
b3752c2001-06-20Henrik Grubbström (Grubba) #ifdef PROC_DEBUG
e974952013-01-01Henrik Grubbström (Grubba)  char debug_prefix[] = { '[', '0' + (getpid()/100000)%10, '0' + (getpid()/10000)%10, '0' + (getpid()/1000)%10, '0' + (getpid()/100)%10, '0' + (getpid()/10)%10, '0' + getpid()%10, ']', ' ', }; write(2, debug_prefix, sizeof(debug_prefix));
b3752c2001-06-20Henrik Grubbström (Grubba)  write(2, "Child\n", 6); #endif /* PROC_DEBUG */
06dda52002-08-21Marcus Comstedt  pid = getpid();
0144fe1998-11-30Henrik Grubbström (Grubba)  /* Close our parent's end of the pipe. */
0d7c542014-05-20Per Hedbor  while(UNLIKELY(close(control_pipe[0]) < 0) && UNLIKELY(errno==EINTR));
d887b61999-05-26Fredrik Hübinette (Hubbe) 
bf782a2003-12-01Henrik Grubbström (Grubba) #ifndef HAVE_VFORK
77ae431998-11-29Henrik Grubbström (Grubba)  /* Wait for parent to get ready... */
0d7c542014-05-20Per Hedbor  while (UNLIKELY((( e = read(control_pipe[1], buf, 1)) < 0)) && UNLIKELY((errno == EINTR)))
77ae431998-11-29Henrik Grubbström (Grubba)  ;
a4b2dd2003-03-16Henrik Grubbström (Grubba) #ifdef PROC_DEBUG
e974952013-01-01Henrik Grubbström (Grubba)  if (e < 0) { char buf[5] = { '0' + (errno/1000)%10, '0' + (errno/100)%10, '0' + (errno/10)%10, '0' + errno%10, '\n' }; write(2, debug_prefix, sizeof(debug_prefix)); write(2, "Child: Control pipe read failed with errno: ", 44); write(2, buf, 5); } else if (!e) { write(2, debug_prefix, sizeof(debug_prefix)); write(2, "Child: No data from control pipe.\n", 34); } write(2, debug_prefix, sizeof(debug_prefix));
a4b2dd2003-03-16Henrik Grubbström (Grubba)  write(2, "Child: Woken up.\n", 17); #endif /* PROC_DEBUG */
bf782a2003-12-01Henrik Grubbström (Grubba) #endif /* HAVE_VFORK */
303a832001-09-26Fredrik Hübinette (Hubbe)  for(e=0;e<cmd->size;e++) storage.argv[e]=cmd->item[e].u.string->str;
965cb11998-04-06Fredrik Hübinette (Hubbe)  storage.argv[e]=0;
f087c41998-02-04Fredrik Hübinette (Hubbe) 
965cb11998-04-06Fredrik Hübinette (Hubbe)  if(storage.env) environ=storage.env;
f087c41998-02-04Fredrik Hübinette (Hubbe)  #ifdef HAVE_SETEUID
dffabf2014-02-24Per Hedbor  if( seteuid(0) == -1 ) { /* all is ok, just silencing gcc-warning */ }
9a8c981998-03-03Henrik Grubbström (Grubba) #else /* !HAVE_SETEUID */ #ifdef HAVE_SETRESUID setresuid(0,0,-1); #endif /* HAVE_SETRESUID */ #endif /* HAVE_SETEUID */
0d52dd1998-01-16Fredrik Hübinette (Hubbe) 
fb45492014-05-20Per Hedbor  if (!keep_signals)
72850a1999-02-01Per Hedbor  {
5f32852007-05-17Henrik Grubbström (Grubba)  int i;
b4f0221998-04-12Henrik Grubbström (Grubba)  /* Restore the signals to the defaults. */
15fafe1999-11-16Henrik Grubbström (Grubba) #ifdef _sys_nsig for(i=0; i<_sys_nsig; i++) signal(i, SIG_DFL); #else /* !_sys_nsig */
54a9791999-11-16Thomas Bellman  for(i=0; i<NSIG; i++)
72850a1999-02-01Per Hedbor  signal(i, SIG_DFL);
15fafe1999-11-16Henrik Grubbström (Grubba) #endif /* _sys_nsig */
b4f0221998-04-12Henrik Grubbström (Grubba)  }
a42cce2021-01-04Marcus Comstedt #ifdef HAVE_CHROOT
bd9d402003-12-05Stephen R. van den Berg  if(mchroot) { if( chroot( mchroot ) ) {
2936242014-05-20Martin Nilsson  /* fprintf is not safe if we use vfork. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] child: chroot(\"%s\") failed, errno=%d\n", getpid(), chroot, errno);
6b47142003-12-05Martin Nilsson  PROCERROR(PROCE_CHROOT, 0);
bd9d402003-12-05Stephen R. van den Berg  }
28370c2013-02-01Henrik Grubbström (Grubba)  if (chdir("/")) {
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] child: chdir(\"/\") failed, errno=%d\n", getpid(), errno);
28370c2013-02-01Henrik Grubbström (Grubba)  PROCERROR(PROCE_CHDIR, 1); }
bd9d402003-12-05Stephen R. van den Berg  }
a42cce2021-01-04Marcus Comstedt #endif
bd9d402003-12-05Stephen R. van den Berg 
72850a1999-02-01Per Hedbor  if(tmp_cwd)
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
72850a1999-02-01Per Hedbor  if( chdir( tmp_cwd ) ) {
2936242014-05-20Martin Nilsson  /* fprintf is not safe if we use vfork. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] child: chdir(\"%s\") failed, errno=%d\n", getpid(), tmp_cwd, errno);
72850a1999-02-01Per Hedbor  PROCERROR(PROCE_CHDIR, 0); } }
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
c7cfc91998-01-20Henrik Grubbström (Grubba) #ifdef HAVE_NICE
72850a1999-02-01Per Hedbor  if(nice_val)
dffabf2014-02-24Per Hedbor  if( nice(nice_val) == -1 ) { /* nice failed. Should we do something? */ }
72850a1999-02-01Per Hedbor #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
72850a1999-02-01Per Hedbor #ifdef HAVE_SETRLIMIT if(storage.limits) {
f1e4ee2003-03-06Henrik Grubbström (Grubba)  struct pike_limit *l = storage.limits;
72850a1999-02-01Per Hedbor  while(l) { setrlimit( l->resource, &l->rlp ); l = l->next; } } #endif
0d52dd1998-01-16Fredrik Hübinette (Hubbe) 
06dda52002-08-21Marcus Comstedt #ifdef HAVE_SETSID if (setsid_request) { int fd; #ifdef TIOCNOTTY fd = open("/dev/tty", O_RDWR | O_NOCTTY); if (fd >= 0) { (void) ioctl(fd, TIOCNOTTY, NULL); close(fd); } #endif if (setsid()==-1) PROCERROR(PROCE_SETSID,0); #ifdef TCSETCTTY if (cterm >= 0) if (ioctl(cterm, TCSETCTTY, NULL)<0) PROCERROR(PROCE_SETCTTY,0); #else if (cterm >= 0) { char *ttn; #ifdef TIOCSCTTY if (ioctl(cterm, TIOCSCTTY, NULL)<0) PROCERROR(PROCE_SETCTTY,0); #endif ttn = ttyname(cterm); if (ttn == NULL) PROCERROR(PROCE_SETCTTY,0); fd = open(ttn, O_RDWR); if (fd < 0) PROCERROR(PROCE_SETCTTY,0); close(fd); } /* FIXME: else... what? error or ignore? */ #endif } /* FIXME: else... what? error or ignore? */ #endif
47a7452000-01-14Henrik Grubbström (Grubba)  /* Perform fd remapping */
72850a1999-02-01Per Hedbor  {
6465ab2002-04-26Henrik Grubbström (Grubba)  int fd;
47a7452000-01-14Henrik Grubbström (Grubba)  /* Note: This is O(n²), but that ought to be ok. */ for (fd=0; fd<num_fds; fd++) {
493ee52004-07-02Henrik Grubbström (Grubba)  /*fprintf(stderr, "Remapping fd %d to %d\n", fds[fd], fd);*/ if (fds[fd] == -1) continue; if (fds[fd] == fd) { /* Clear close on exec. */ int code = set_close_on_exec(fd, 0); if (code < 0) PROCERROR(PROCE_CLRCLOEXEC, fd); continue; } if (fd == control_pipe[1]) { /* Our control pipe is in the way. * Move it. */ int remapped; if ((remapped = dup(fd)) < 0) PROCERROR(PROCE_DUP, fd); /*fprintf(stderr, "Moved control pipe to fd %d\n", remapped);*/ control_pipe[1] = remapped; } else { /* Is there any other fd in the way? */ int fd2; int remapped = -1; for (fd2 = fd+1; fd2 < num_fds; fd2++) { if (fds[fd2] == fd) {
940a4b2005-05-25Henrik Grubbström (Grubba)  /* We need to temporarily remap this fd,
493ee52004-07-02Henrik Grubbström (Grubba)  * since it's in the way */ if (remapped == -1) { if ((remapped = dup(fd)) < 0) PROCERROR(PROCE_DUP, fd); } /*fprintf(stderr, "Moved fd %d to be mapped to fd %d to fd %d\n", fds[fd2], fd2, remapped);*/ fds[fd2] = remapped;
47a7452000-01-14Henrik Grubbström (Grubba)  } } } if (dup2(fds[fd], fd) < 0) PROCERROR(PROCE_DUP2, fd);
493ee52004-07-02Henrik Grubbström (Grubba)  /*fprintf(stderr, "fd %d successfully remapped to fd %d\n", fds[fd], fd);*/
47a7452000-01-14Henrik Grubbström (Grubba)  } /* Close the source fds. */ for (fd=0; fd<num_fds; fd++) { /* FIXME: Should it be a comparison against -1 instead? */ /* Always keep stdin, stdout & stderr. */ if (fds[fd] > 2) { if ((fds[fd] >= num_fds) || (fds[fds[fd]] == -1)) {
493ee52004-07-02Henrik Grubbström (Grubba)  /*fprintf(stderr, "Closing fd %d\n", fds[fd]);*/
47a7452000-01-14Henrik Grubbström (Grubba)  close(fds[fd]); } } }
1e1ebe2002-04-24Jonas Wallden  /* Close unknown fds which have been created elsewhere (e.g. in the Java environment) */
6ace4f2006-04-24Henrik Grubbström (Grubba) #ifdef HAVE_FDWALK { struct fd_cleanup_info info = { num_fds, control_pipe[1], }; fdwalk(fd_cleanup_cb, &info); } #else /* !HAVE_FDWALK */
6465ab2002-04-26Henrik Grubbström (Grubba)  { int num_fail = 0;
1f3ce32002-10-03Martin Stjernholm #ifdef _SC_OPEN_MAX
6465ab2002-04-26Henrik Grubbström (Grubba)  int max_fds = sysconf(_SC_OPEN_MAX);
1f3ce32002-10-03Martin Stjernholm #endif for (fd = num_fds; #ifdef _SC_OPEN_MAX fd < max_fds; #else 1; #endif fd++) {
6ace4f2006-04-24Henrik Grubbström (Grubba) #ifdef HAVE_CLOSEFROM if (fd > control_pipe[1]) {
9b56002006-05-02Henrik Grubbström (Grubba)  /* NOTE: We need to loop on all errno's since we don't know * if any of them failed with EINTR and got overwritten. * NOTE: EBADF shouldn't occur as an overwritten errno, since * if would mean that close(2) was called for an invalid * fd, which closefrom shouldn't do. */
6ace4f2006-04-24Henrik Grubbström (Grubba)  do { errno = 0; closefrom(fd);
9b56002006-05-02Henrik Grubbström (Grubba)  /* NOTE: OpenBSD sets errno to EBADF if fd is > than * any open fd. */
0d7c542014-05-20Per Hedbor  } while (UNLIKELY(errno && (errno != EBADF)));
6ace4f2006-04-24Henrik Grubbström (Grubba)  break; } #endif
493ee52004-07-02Henrik Grubbström (Grubba) #ifdef HAVE_BROKEN_F_SETFD
6465ab2002-04-26Henrik Grubbström (Grubba)  int code = 0; if (fd != control_pipe[1]) { /* In this case set_close_on_exec is not fork1(2) safe. */ code = close(fd);
493ee52004-07-02Henrik Grubbström (Grubba)  }
1e1ebe2002-04-24Jonas Wallden #else /* !HAVE_BROKEN_F_SETFD */
493ee52004-07-02Henrik Grubbström (Grubba)  /* Delay close to actual exec */ int code = set_close_on_exec(fd, 1);
1e1ebe2002-04-24Jonas Wallden #endif /* HAVE_BROKEN_F_SETFD */
6465ab2002-04-26Henrik Grubbström (Grubba)  if (code == -1) { if (++num_fail >= PIKE_BADF_LIMIT) { break; } } else {
493ee52004-07-02Henrik Grubbström (Grubba)  /*fprintf(stderr, "Set close on exec on fd %d\n", fd);*/
6465ab2002-04-26Henrik Grubbström (Grubba)  num_fail = 0; } } }
6ace4f2006-04-24Henrik Grubbström (Grubba) #endif /* HAVE_FDWALK */
47a7452000-01-14Henrik Grubbström (Grubba)  /* FIXME: Map the fds as not close on exec? */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }
0d52dd1998-01-16Fredrik Hübinette (Hubbe) 
493ee52004-07-02Henrik Grubbström (Grubba)  /* Ensure that the pipe will be closed when the child starts. */ if(set_close_on_exec(control_pipe[1], 1) < 0) PROCERROR(PROCE_CLOEXEC, control_pipe[1]); /*fprintf(stderr, "Set close on exec on fd %d (control_pipe)\n", control_pipe[1]);*/
72850a1999-02-01Per Hedbor  if(priority) set_priority( 0, priority );
f087c41998-02-04Fredrik Hübinette (Hubbe) #ifdef HAVE_SETGID #ifdef HAVE_GETGID if(wanted_gid != getgid()) #endif { if(setgid(wanted_gid)) #ifdef _HPUX_SOURCE /* Kluge for HP-(S)UX */ if(wanted_gid > 60000 && setgid(-2) && setgid(65534) && setgid(60001)) #endif
7dd1971998-10-02Henrik Grubbström (Grubba)  {
77ae431998-11-29Henrik Grubbström (Grubba)  PROCERROR(PROCE_SETGID, (int)wanted_gid);
7dd1971998-10-02Henrik Grubbström (Grubba)  }
f087c41998-02-04Fredrik Hübinette (Hubbe)  }
0d52dd1998-01-16Fredrik Hübinette (Hubbe) #endif
965cb11998-04-06Fredrik Hübinette (Hubbe) #ifdef HAVE_SETGROUPS if(storage.wanted_gids) { if(setgroups(storage.num_wanted_gids, storage.wanted_gids)) {
77ae431998-11-29Henrik Grubbström (Grubba)  PROCERROR(PROCE_SETGROUPS,0);
965cb11998-04-06Fredrik Hübinette (Hubbe)  } } #endif
f087c41998-02-04Fredrik Hübinette (Hubbe) #ifdef HAVE_SETUID #ifdef HAVE_GETUID if(wanted_uid != getuid()) #endif { #ifdef HAVE_INITGROUPS if(do_initgroups) { int initgroupgid; if(!pw) pw=getpwuid(wanted_uid);
90143c1998-08-12Henrik Grubbström (Grubba)  if(!pw) {
77ae431998-11-29Henrik Grubbström (Grubba)  PROCERROR(PROCE_GETPWUID, wanted_uid);
90143c1998-08-12Henrik Grubbström (Grubba)  }
f087c41998-02-04Fredrik Hübinette (Hubbe)  initgroupgid=pw->pw_gid; if(initgroups(pw->pw_name, initgroupgid)) #ifdef _HPUX_SOURCE /* Kluge for HP-(S)UX */
b7fc921998-08-09Henrik Grubbström (Grubba)  if((initgroupgid > 60000) && initgroups(pw->pw_name, -2) && initgroups(pw->pw_name, 65534) && initgroups(pw->pw_name, 60001))
f087c41998-02-04Fredrik Hübinette (Hubbe) #endif /* _HPUX_SOURCE */ { #ifdef HAVE_SETGROUPS gid_t x[]={ 65534 };
b7fc921998-08-09Henrik Grubbström (Grubba)  if(setgroups(0, x))
f087c41998-02-04Fredrik Hübinette (Hubbe) #endif /* SETGROUPS */
90143c1998-08-12Henrik Grubbström (Grubba)  {
77ae431998-11-29Henrik Grubbström (Grubba)  PROCERROR(PROCE_INITGROUPS, 0);
90143c1998-08-12Henrik Grubbström (Grubba)  }
f087c41998-02-04Fredrik Hübinette (Hubbe)  } } #endif /* INITGROUPS */ if(setuid(wanted_uid)) { perror("setuid");
77ae431998-11-29Henrik Grubbström (Grubba)  PROCERROR(PROCE_SETUID, (int)wanted_uid);
f087c41998-02-04Fredrik Hübinette (Hubbe)  } } #endif /* SETUID */ #ifdef HAVE_SETEUID
dffabf2014-02-24Per Hedbor  if( seteuid(wanted_uid) == -1 ) { perror("seteuid"); PROCERROR(PROCE_SETUID, (int)wanted_uid); }
9a8c981998-03-03Henrik Grubbström (Grubba) #else /* !HAVE_SETEUID */ #ifdef HAVE_SETRESUID setresuid(wanted_uid, wanted_uid, -1); #endif /* HAVE_SETRESUID */ #endif /* HAVE_SETEUID */
b143542003-02-28Henrik Grubbström (Grubba) 
85f59e1998-01-08Fredrik Hübinette (Hubbe)  do_set_close_on_exec();
f087c41998-02-04Fredrik Hübinette (Hubbe)  set_close_on_exec(0,0); set_close_on_exec(1,0); set_close_on_exec(2,0);
dffabf2014-02-24Per Hedbor 
5539c51998-06-08Henrik Grubbström (Grubba) #ifdef HAVE_BROKEN_F_SETFD do_close_on_exec(); #endif /* HAVE_BROKEN_F_SETFD */
a4b2dd2003-03-16Henrik Grubbström (Grubba) #ifdef HAVE_PTRACE if (do_trace) { #ifdef PROC_DEBUG
e974952013-01-01Henrik Grubbström (Grubba)  write(2, debug_prefix, sizeof(debug_prefix));
a4b2dd2003-03-16Henrik Grubbström (Grubba)  write(2, "Child: Calling ptrace()...\n", 27); #endif /* PROC_DEBUG */ /* NB: A return value is not defined for this ptrace request! */
1588532012-12-29Jonas Walldén  ptrace(PTRACE_TRACEME, 0, NULL, 0);
a4b2dd2003-03-16Henrik Grubbström (Grubba)  } #endif /* HAVE_PTRACE */
dffabf2014-02-24Per Hedbor 
a4b2dd2003-03-16Henrik Grubbström (Grubba) #ifdef PROC_DEBUG
e974952013-01-01Henrik Grubbström (Grubba)  write(2, debug_prefix, sizeof(debug_prefix));
a4b2dd2003-03-16Henrik Grubbström (Grubba)  write(2, "Child: Calling exec()...\n", 25); #endif /* PROC_DEBUG */
965cb11998-04-06Fredrik Hübinette (Hubbe)  execvp(storage.argv[0],storage.argv);
392e4b2004-04-01Henrik Grubbström (Grubba) 
2936242014-05-20Martin Nilsson  /* fprintf is not safe if we use vfork. */
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] Child: execvp(\"%s\", ...) failed\n" "errno = %d\n", getpid(), storage.argv[0], errno);
a4b2dd2003-03-16Henrik Grubbström (Grubba) #ifndef HAVE_BROKEN_F_SETFD
77ae431998-11-29Henrik Grubbström (Grubba)  /* No way to tell about this on broken OS's :-( */ PROCERROR(PROCE_EXEC, 0); #endif /* HAVE_BROKEN_F_SETFD */ exit(99);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  } }
0c95942018-01-12Stephen R. van den Berg #endif /* __amigaos__ */
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif /* __NT__ */ pop_n_elems(args); } #ifdef HAVE_FORK
4c74bf2003-04-30Martin Nilsson /*! @decl object fork()
ee18f32001-02-09Henrik Grubbström (Grubba)  *! *! Fork the process in two. *!
4c74bf2003-04-30Martin Nilsson  *! Fork splits the process in two, and for the parent it returns a *! pid object for the child. Refer to your Unix manual for further *! details.
ee18f32001-02-09Henrik Grubbström (Grubba)  *! *! @note *! This function can cause endless bugs if used without proper care. *! *! This function is disabled when using threads. *!
45f2a22002-09-10Martin Nilsson  *! This function is not available on all platforms. *!
ee18f32001-02-09Henrik Grubbström (Grubba)  *! The most common use for fork is to start sub programs, which is *! better done with @[Process.create_process()]. *! *! @seealso *! @[Process.create_process()] */
cfbc2e2000-03-21Fredrik Hübinette (Hubbe) void Pike_f_fork(INT32 args)
85f59e1998-01-08Fredrik Hübinette (Hubbe) { struct object *o; pid_t pid; pop_n_elems(args);
ba510c1998-03-27Henrik Grubbström (Grubba) 
965cb11998-04-06Fredrik Hübinette (Hubbe) #ifdef _REENTRANT if(num_threads >1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("You cannot use fork in a multithreaded application.\n");
965cb11998-04-06Fredrik Hübinette (Hubbe) #endif
71ac9e1999-08-29Fredrik Hübinette (Hubbe)  th_atfork_prepare();
3d56e11999-01-07Fredrik Hübinette (Hubbe) /* THREADS_ALLOW_UID(); */
a96cca2004-10-22Henrik Grubbström (Grubba) #if defined(HAVE_FORK1) && defined(_REENTRANT)
b0d10a1999-03-07Henrik Grubbström (Grubba)  /* This section is disabled, since fork1() isn't usefull if * you aren't about do an exec(). * In addition any helper threads (like the wait thread) would * disappear, so the child whould be crippled. * /grubba 1999-03-07
a96cca2004-10-22Henrik Grubbström (Grubba)  * * Reenabled since fork() usually performs a fork1() anyway. * /grubba 2004-04-02
b0d10a1999-03-07Henrik Grubbström (Grubba)  */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  pid=fork1(); #else pid=fork(); #endif
3d56e11999-01-07Fredrik Hübinette (Hubbe) /* THREADS_DISALLOW_UID(); */
ba510c1998-03-27Henrik Grubbström (Grubba) 
57f53c1999-09-25Henrik Grubbström (Grubba)  if(pid) {
a8df4e2003-11-21Henrik Grubbström (Grubba) #ifdef USE_WAIT_THREAD if (!wait_thread_running) { /* NOTE: This code is delayed to after the fork so as to allow for * detaching. */ THREAD_T foo; if (th_create_small(&foo, wait_thread, 0)) {
d3a1c82014-10-31Martin Nilsson  Pike_error("Failed to create wait thread. errno: %d.\n", errno);
a8df4e2003-11-21Henrik Grubbström (Grubba)  } wait_thread_running = 1; } num_threads++; /* We use the interpreter lock */ #endif
fec3001999-08-30Fredrik Hübinette (Hubbe)  th_atfork_parent();
57f53c1999-09-25Henrik Grubbström (Grubba)  } else {
fec3001999-08-30Fredrik Hübinette (Hubbe)  th_atfork_child();
1b3ff52004-06-15Henrik Grubbström (Grubba)  DO_IF_PROFILING({ /* Reset profiling information. */ struct pike_frame *frame = Pike_fp; cpu_time_t now = get_cpu_time(); Pike_interpreter.unlocked_time = 0; Pike_interpreter.accounted_time = 0; while(frame) { frame->start_time = now; frame->children_base = 0; frame = frame->next; } });
ba58572008-07-09Henrik Grubbström (Grubba)  in_forked_child = 1;
57f53c1999-09-25Henrik Grubbström (Grubba)  }
13670c2015-05-25Martin Nilsson 
1b6dba1998-05-19Henrik Grubbström (Grubba)  if(pid==-1) {
d3a1c82014-10-31Martin Nilsson  Pike_error("Fork failed. errno:%d.\n", errno);
1b6dba1998-05-19Henrik Grubbström (Grubba)  }
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(pid) { struct pid_status *p;
70e9781999-03-06Fredrik Hübinette (Hubbe) 
a2e2002003-09-30Martin Stjernholm  process_started(pid);
70e9781999-03-06Fredrik Hübinette (Hubbe) #ifdef USE_SIGCHILD
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(!signal_evaluator_callback) { signal_evaluator_callback=add_to_callback(&evaluator_callbacks, check_signals, 0,0);
424d9c1999-05-02Fredrik Hübinette (Hubbe)  dmalloc_accept_leak(signal_evaluator_callback);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }
70e9781999-03-06Fredrik Hübinette (Hubbe) #endif
cff6342017-06-17Martin Nilsson  o=fast_clone_object(pid_status_program);
13b5ed2014-05-26Per Hedbor  p=get_storage(o,pid_status_program);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  p->pid=pid; p->state=PROCESS_RUNNING; push_object(o); push_int(pid);
fc68462002-10-31Henrik Grubbström (Grubba)  mapping_insert(pid_mapping,Pike_sp-1, Pike_sp-2);
85f59e1998-01-08Fredrik Hübinette (Hubbe)  pop_stack(); }else{ #ifdef _REENTRANT /* forked copy. there is now only one thread running, this one. */ num_threads=1; #endif
23c5132017-10-03Per Cederqvist  REINIT_FIFO(sig, unsigned char); REINIT_FIFO(wait,wait_data);
a92ad62003-10-13Henrik Grubbström (Grubba)  /* FIXME: Ought to clear pid_mapping here. */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  call_callback(&fork_child_callback, 0); push_int(0); } }
a96cca2004-10-22Henrik Grubbström (Grubba) 
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif /* HAVE_FORK */ #ifdef HAVE_KILL
2f70502014-07-10Henrik Grubbström (Grubba) /*! @decl int(0..1) kill(int pid, int signal)
685fb62001-01-31Henrik Grubbström (Grubba)  *!
2f70502014-07-10Henrik Grubbström (Grubba)  *! Send a signal to another process.
685fb62001-01-31Henrik Grubbström (Grubba)  *! *! Some signals and their supposed purpose: *! @int *! @value SIGHUP *! Hang-up, sent to process when user logs out. *! @value SIGINT *! Interrupt, normally sent by ctrl-c. *! @value SIGQUIT *! Quit, sent by ctrl-\. *! @value SIGILL *! Illegal instruction. *! @value SIGTRAP *! Trap, mostly used by debuggers. *! @value SIGABRT *! Aborts process, can be caught, used by Pike whenever something *! goes seriously wrong.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGEMT *! Emulation trap.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGFPE *! Floating point error (such as division by zero). *! @value SIGKILL *! Really kill a process, cannot be caught.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGBUS *! Bus error.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGSEGV *! Segmentation fault, caused by accessing memory where you *! shouldn't. Should never happen to Pike.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGSYS *! Bad system call. Should never happen to Pike. *! @value SIGPIPE *! Broken pipe.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGALRM *! Signal used for timer interrupts. *! @value SIGTERM *! Termination signal.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGUSR1 *! Signal reserved for whatever you want to use it for. *! Note that some OSs reserve this signal for the thread library. *! @value SIGUSR2 *! Signal reserved for whatever you want to use it for. *! Note that some OSs reserve this signal for the thread library.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGCHLD *! Child process died. This signal is reserved for internal use *! by the Pike run-time.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGPWR *! Power failure or restart. *! @value SIGWINCH *! Window change signal. *! @value SIGURG *! Urgent socket data. *! @value SIGIO *! Pollable event.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGSTOP *! Stop (suspend) process.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGTSTP *! Stop (suspend) process. Sent by ctrl-z. *! @value SIGCONT *! Continue suspended.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGTTIN *! TTY input for background process. *! @value SIGTTOU *! TTY output for background process.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGVTALRM *! Virtual timer expired. *! @value SIGPROF *! Profiling trap.
685fb62001-01-31Henrik Grubbström (Grubba)  *! @value SIGXCPU *! Out of CPU. *! @value SIGXFSZ *! File size limit exceeded.
0da61a2001-01-31Henrik Grubbström (Grubba)  *! @value SIGSTKFLT *! Stack fault
685fb62001-01-31Henrik Grubbström (Grubba)  *! @endint *!
2f70502014-07-10Henrik Grubbström (Grubba)  *! @returns *! @int *! @value 1 *! Success. *! @value 0 *! Failure. @[errno()] is set to EINVAL, EPERM or ESRCH. *! @endint *!
685fb62001-01-31Henrik Grubbström (Grubba)  *! @note *! Note that you have to use signame to translate the name of a signal *! to its number. *!
45f2a22002-09-10Martin Nilsson  *! Note that the kill function is not available on platforms that do not
27b40e2002-09-10Henrik Grubbström (Grubba)  *! support signals. Some platforms may also have signals not listed here.
0da61a2001-01-31Henrik Grubbström (Grubba)  *!
685fb62001-01-31Henrik Grubbström (Grubba)  *! @seealso *! @[signal()], @[signum()], @[signame()], @[fork()] */
85f59e1998-01-08Fredrik Hübinette (Hubbe) static void f_kill(INT32 args) {
ba510c1998-03-27Henrik Grubbström (Grubba)  int signum;
571f0a2001-03-29Henrik Grubbström (Grubba)  int pid = 0;
0c6a6c2002-04-16Martin Stjernholm  int res, save_errno;
ba510c1998-03-27Henrik Grubbström (Grubba) 
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(args < 2)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("kill", 2);
b3cc131998-01-15Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(Pike_sp[-args]))
85f59e1998-01-08Fredrik Hübinette (Hubbe)  {
fe2c202003-04-14Henrik Grubbström (Grubba)  case PIKE_T_INT:
fc68462002-10-31Henrik Grubbström (Grubba)  pid = Pike_sp[-args].u.integer;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  break;
53acc21999-05-24Henrik Grubbström (Grubba)  /* FIXME: What about if it's an object? */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  default:
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("kill", 1, "int");
85f59e1998-01-08Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[1-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("kill", 2, "int");
85f59e1998-01-08Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  signum = Pike_sp[1-args].u.integer;
ba510c1998-03-27Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] kill: pid=%d, signum=%d\n", getpid(), pid, signum);
53acc21999-05-24Henrik Grubbström (Grubba) 
ba510c1998-03-27Henrik Grubbström (Grubba)  THREADS_ALLOW_UID(); res = !kill(pid, signum);
0c6a6c2002-04-16Martin Stjernholm  save_errno = errno;
ba510c1998-03-27Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
85f59e1998-01-08Fredrik Hübinette (Hubbe)  check_signals(0,0,0);
ba510c1998-03-27Henrik Grubbström (Grubba)  pop_n_elems(args); push_int(res);
0c6a6c2002-04-16Martin Stjernholm  errno = save_errno;
85f59e1998-01-08Fredrik Hübinette (Hubbe) }
eb9a042001-08-14Martin Nilsson /*! @module Process */ /*! @class create_process
685fb62001-01-31Henrik Grubbström (Grubba)  */
2f70502014-07-10Henrik Grubbström (Grubba) /*! @decl int(0..1) kill(int signal) *! *! Send a signal to the process.
0c88432006-10-31Martin Nilsson  *! *! @returns *! @int *! @value 1
2f70502014-07-10Henrik Grubbström (Grubba)  *! Success.
0c88432006-10-31Martin Nilsson  *! @value 0
2f70502014-07-10Henrik Grubbström (Grubba)  *! Failure. @[errno()] is set to EINVAL, EPERM or ESRCH.
0c88432006-10-31Martin Nilsson  *! @endint
45f2a22002-09-10Martin Nilsson  *! *! @note *! This function is only available on platforms that
27b40e2002-09-10Henrik Grubbström (Grubba)  *! support signals.
c67a1b2011-09-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[predef::kill()]
685fb62001-01-31Henrik Grubbström (Grubba)  */
53acc21999-05-24Henrik Grubbström (Grubba) static void f_pid_status_kill(INT32 args) { int pid = THIS->pid; INT_TYPE signum;
0c6a6c2002-04-16Martin Stjernholm  int res, save_errno;
53acc21999-05-24Henrik Grubbström (Grubba) 
c91b1d2018-08-05Martin Nilsson  get_all_args(NULL, args, "%+", &signum);
53acc21999-05-24Henrik Grubbström (Grubba) 
a91d9a2016-01-11Martin Nilsson  PROC_FPRINTF("[%d] kill: pid=%d, signum=%d\n", getpid(), pid, signum);
53acc21999-05-24Henrik Grubbström (Grubba)  THREADS_ALLOW_UID(); res = !kill(pid, signum);
0c6a6c2002-04-16Martin Stjernholm  save_errno = errno;
53acc21999-05-24Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID(); check_signals(0,0,0); pop_n_elems(args);
685fb62001-01-31Henrik Grubbström (Grubba)  push_int(res);
0c6a6c2002-04-16Martin Stjernholm  errno = save_errno;
53acc21999-05-24Henrik Grubbström (Grubba) }
685fb62001-01-31Henrik Grubbström (Grubba) /*! @endclass */
eb9a042001-08-14Martin Nilsson  /*! @endmodule */
c33e761998-02-27Fredrik Hübinette (Hubbe) #else #ifdef __NT__
ea5c9e1998-02-28Fredrik Hübinette (Hubbe) #define HAVE_KILL
58854e1999-04-11Fredrik Hübinette (Hubbe) static void f_kill(INT32 args)
c33e761998-02-27Fredrik Hübinette (Hubbe) {
bd67392015-10-14Martin Nilsson  HANDLE proc = INVALID_HANDLE_VALUE; HANDLE tofree = INVALID_HANDLE_VALUE;
c33e761998-02-27Fredrik Hübinette (Hubbe)  if(args < 2)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("kill", 2);
c33e761998-02-27Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(Pike_sp[-args]))
c33e761998-02-27Fredrik Hübinette (Hubbe)  {
fe2c202003-04-14Henrik Grubbström (Grubba)  case PIKE_T_INT:
ae36881999-08-27Fredrik Hübinette (Hubbe)  tofree=proc=OpenProcess(PROCESS_TERMINATE, 0,
fc68462002-10-31Henrik Grubbström (Grubba)  Pike_sp[-args].u.integer);
ae36881999-08-27Fredrik Hübinette (Hubbe) /* fprintf(stderr,"PROC: %ld %ld\n",(long)proc,INVALID_HANDLE_VALUE); */
bd67392015-10-14Martin Nilsson  if(!proc || proc == INVALID_HANDLE_VALUE)
c33e761998-02-27Fredrik Hübinette (Hubbe)  { errno=EPERM; pop_n_elems(args);
ae36881999-08-27Fredrik Hübinette (Hubbe)  push_int(0);
c33e761998-02-27Fredrik Hübinette (Hubbe)  return; } break; case T_OBJECT: { struct pid_status *p;
13b5ed2014-05-26Per Hedbor  if((p=get_storage(Pike_sp[-args].u.object, pid_status_program)))
c33e761998-02-27Fredrik Hübinette (Hubbe)  { proc=p->handle; break; } } default:
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("kill", 1, "int|object");
c33e761998-02-27Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[1-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("kill", 2, "int");
c33e761998-02-27Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  switch(Pike_sp[1-args].u.integer)
c33e761998-02-27Fredrik Hübinette (Hubbe)  {
ae36881999-08-27Fredrik Hübinette (Hubbe)  case 0: pop_n_elems(args); push_int(1); break;
13670c2015-05-25Martin Nilsson 
c33e761998-02-27Fredrik Hübinette (Hubbe)  case SIGKILL: {
ae36881999-08-27Fredrik Hübinette (Hubbe)  int i=TerminateProcess(proc,0xff);
c33e761998-02-27Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(i); check_signals(0,0,0); break; }
13670c2015-05-25Martin Nilsson 
c33e761998-02-27Fredrik Hübinette (Hubbe)  default:
ea5c9e1998-02-28Fredrik Hübinette (Hubbe)  errno=EINVAL; pop_n_elems(args);
ae36881999-08-27Fredrik Hübinette (Hubbe)  push_int(0);
ea5c9e1998-02-28Fredrik Hübinette (Hubbe)  break;
c33e761998-02-27Fredrik Hübinette (Hubbe)  }
bd67392015-10-14Martin Nilsson  if(tofree != INVALID_HANDLE_VALUE)
ae36881999-08-27Fredrik Hübinette (Hubbe)  CloseHandle(tofree);
c33e761998-02-27Fredrik Hübinette (Hubbe) }
53acc21999-05-24Henrik Grubbström (Grubba)  static void f_pid_status_kill(INT32 args) { INT_TYPE signum;
c91b1d2018-08-05Martin Nilsson  get_all_args(NULL, args, "%i", &signum);
53acc21999-05-24Henrik Grubbström (Grubba)  pop_n_elems(args); push_int(THIS->pid); push_int(signum); f_kill(2); }
c33e761998-02-27Fredrik Hübinette (Hubbe) #endif
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl int getpid() *! *! Returns the process ID of this process. *! *! @seealso
e1ea352002-02-14Martin Nilsson  *! @[System.getppid()], @[System.getpgrp()]
685fb62001-01-31Henrik Grubbström (Grubba)  */
cb22561995-10-11Fredrik Hübinette (Hubbe) static void f_getpid(INT32 args) { pop_n_elems(args); push_int(getpid()); }
75920f1997-12-28Fredrik Hübinette (Hubbe) #ifdef HAVE_ALARM
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl int alarm(int seconds) *! *! Set an alarm clock for delivery of a signal. *! *! @[alarm()] arranges for a SIGALRM signal to be delivered to the *! process in @[seconds] seconds. *!
cbe8c92003-04-07Martin Nilsson  *! If @[seconds] is @expr{0@} (zero), no new alarm will be scheduled.
685fb62001-01-31Henrik Grubbström (Grubba)  *! *! Any previous alarms will in any case be canceled. *! *! @returns *! Returns the number of seconds remaining until any previously *! scheduled alarm was due to be delivered, or zero if there was *! no previously scheduled alarm. *!
45f2a22002-09-10Martin Nilsson  *! @note
27b40e2002-09-10Henrik Grubbström (Grubba)  *! This function is only available on platforms that support
45f2a22002-09-10Martin Nilsson  *! signals. *!
685fb62001-01-31Henrik Grubbström (Grubba)  *! @seealso *! @[ualarm()], @[signal()], @[call_out()] */
cf2a151996-04-13Fredrik Hübinette (Hubbe) static void f_alarm(INT32 args) { long seconds; if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("alarm", 1);
cf2a151996-04-13Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("alarm", 1, "int");
cf2a151996-04-13Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  seconds=Pike_sp[-args].u.integer;
cf2a151996-04-13Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(alarm(seconds)); }
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
cf2a151996-04-13Fredrik Hübinette (Hubbe) 
d1b8ea1998-09-05Henrik Grubbström (Grubba) #if defined(HAVE_UALARM) || defined(HAVE_SETITIMER)
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl int ualarm(int useconds) *! *! Set an alarm clock for delivery of a signal. *! *! @[alarm()] arranges for a SIGALRM signal to be delivered to the *! process in @[useconds] microseconds. *!
cbe8c92003-04-07Martin Nilsson  *! If @[useconds] is @expr{0@} (zero), no new alarm will be scheduled.
685fb62001-01-31Henrik Grubbström (Grubba)  *! *! Any previous alarms will in any case be canceled. *! *! @returns *! Returns the number of microseconds remaining until any previously *! scheduled alarm was due to be delivered, or zero if there was *! no previously scheduled alarm. *!
45f2a22002-09-10Martin Nilsson  *! @note
27b40e2002-09-10Henrik Grubbström (Grubba)  *! This function is only available on platforms that support
45f2a22002-09-10Martin Nilsson  *! signals. *!
685fb62001-01-31Henrik Grubbström (Grubba)  *! @seealso *! @[alarm()], @[signal()], @[call_out()] */
28119b1996-06-09Fredrik Hübinette (Hubbe) static void f_ualarm(INT32 args) {
d1b8ea1998-09-05Henrik Grubbström (Grubba) #ifndef HAVE_UALARM struct itimerval new, old; #endif /* !HAVE_UALARM */ long useconds;
28119b1996-06-09Fredrik Hübinette (Hubbe)  if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("ualarm", 1);
28119b1996-06-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("ualarm", 1, "int");
28119b1996-06-09Fredrik Hübinette (Hubbe) 
fc68462002-10-31Henrik Grubbström (Grubba)  useconds=Pike_sp[-args].u.integer;
28119b1996-06-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
d1b8ea1998-09-05Henrik Grubbström (Grubba)  #ifdef HAVE_UALARM
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef UALARM_TAKES_TWO_ARGS
d1b8ea1998-09-05Henrik Grubbström (Grubba)  push_int(ualarm(useconds,0));
06983f1996-09-22Fredrik Hübinette (Hubbe) #else
d1b8ea1998-09-05Henrik Grubbström (Grubba)  push_int(ualarm(useconds)); #endif #else /* !HAVE_UALARM */ /* * Use setitimer instead. */ new.it_value.tv_sec = useconds / 1000000; new.it_value.tv_usec = useconds % 1000000; new.it_interval.tv_sec = 0; new.it_interval.tv_usec = 0; if (!setitimer(ITIMER_REAL, &new, &old)) { push_int(old.it_value.tv_usec + old.it_value.tv_sec * 1000000); } else { push_int(-1); } #endif /* HAVE_UALARM */
28119b1996-06-09Fredrik Hübinette (Hubbe) }
d1b8ea1998-09-05Henrik Grubbström (Grubba) #endif /* HAVE_UALARM || HAVE_SETITIMER */
28119b1996-06-09Fredrik Hübinette (Hubbe) 
5f06241999-04-11Fredrik Hübinette (Hubbe) static struct array *atexit_functions;
985a562019-04-16Henrik Grubbström (Grubba) static void run_atexit_functions(struct callback *UNUSED(cb), void *UNUSED(arg), void *UNUSED(arg2))
5f06241999-04-11Fredrik Hübinette (Hubbe) { if(atexit_functions) {
5272b22004-09-22Martin Stjernholm  int i;
77bcee2004-10-15Martin Stjernholm  for (i = atexit_functions->size; i--;) {
5272b22004-09-22Martin Stjernholm  struct svalue *s = ITEM (atexit_functions) + i;
985a562019-04-16Henrik Grubbström (Grubba)  if (callablep(s)) {
5272b22004-09-22Martin Stjernholm  safe_apply_svalue (s, 0, 1); pop_stack(); } }
5207f02004-09-30Martin Stjernholm  free_array (atexit_functions); atexit_functions = 0;
5f06241999-04-11Fredrik Hübinette (Hubbe)  } } static void do_signal_exit(INT32 sig) { push_int(sig); f_exit(1); }
685fb62001-01-31Henrik Grubbström (Grubba) /*! @decl void atexit(function callback) *! *! This function puts the @[callback] in a queue of callbacks to
f6aab22004-09-30Martin Stjernholm  *! call when pike exits. The call order is reversed, i.e. callbacks *! that have been added earlier are called after @[callback].
685fb62001-01-31Henrik Grubbström (Grubba)  *! *! @note *! Please note that @[atexit] callbacks are not called if Pike *! exits abnormally. *! *! @seealso *! @[exit()], @[_exit()] */
5f06241999-04-11Fredrik Hübinette (Hubbe) void f_atexit(INT32 args) {
9a5bb92003-01-04Martin Nilsson  if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("atexit", 1);
9a5bb92003-01-04Martin Nilsson 
5f06241999-04-11Fredrik Hübinette (Hubbe)  if(!atexit_functions) { #ifdef SIGHUP set_default_signal_handler(SIGHUP, do_signal_exit); #endif #ifdef SIGINT set_default_signal_handler(SIGINT, do_signal_exit); #endif
fac1132001-09-28Tomas Nilsson #ifdef SIGBREAK set_default_signal_handler(SIGBREAK, do_signal_exit); #endif
5f06241999-04-11Fredrik Hübinette (Hubbe) #ifdef SIGQUIT set_default_signal_handler(SIGQUIT, do_signal_exit); #endif add_exit_callback(run_atexit_functions,0,0); atexit_functions=low_allocate_array(0,1); }
fc68462002-10-31Henrik Grubbström (Grubba)  atexit_functions=append_array(atexit_functions,Pike_sp-args);
5272b22004-09-22Martin Stjernholm  atexit_functions->flags |= ARRAY_WEAK_FLAG;
58854e1999-04-11Fredrik Hübinette (Hubbe)  pop_n_elems(args);
5f06241999-04-11Fredrik Hübinette (Hubbe) }
a658b72015-10-23Henrik Grubbström (Grubba) /* This function may be called from modules that may have thrashed * the signal handler for a specific signal. eg MariaDB and SIGPIPE.
940a4b2005-05-25Henrik Grubbström (Grubba)  */
a658b72015-10-23Henrik Grubbström (Grubba) PMOD_EXPORT void restore_signal_handler(int sig)
cb22561995-10-11Fredrik Hübinette (Hubbe) {
a658b72015-10-23Henrik Grubbström (Grubba)  if ((TYPEOF(signal_callbacks[sig]) != PIKE_T_INT) || default_signals[sig]) { sigfunctype func = receive_signal;
e51c9b1999-05-03Fredrik Hübinette (Hubbe) #ifdef USE_SIGCHILD
a658b72015-10-23Henrik Grubbström (Grubba)  if (sig == SIGCHLD) { func = receive_sigchild; } #endif my_signal(sig, func); } else { switch(sig) { /* SIGCHLD */ #ifdef SIGCHLD case SIGCHLD: #ifdef USE_SIGCHILD my_signal(sig, receive_sigchild); #else my_signal(sig, SIG_DFL); #endif break; #endif /* SIGFPE */ #ifdef SIGFPE case SIGFPE: #ifdef IGNORE_SIGFPE my_signal(sig, SIG_IGN); #else my_signal(sig, SIG_DFL); #endif break;
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
a658b72015-10-23Henrik Grubbström (Grubba)  /* SIGPIPE */
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef SIGPIPE
a658b72015-10-23Henrik Grubbström (Grubba)  case SIGPIPE: my_signal(sig, SIG_IGN); break;
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
8dd2371995-11-02Fredrik Hübinette (Hubbe) 
1ed6892010-09-22Henrik Grubbström (Grubba)  /* The Java JVM has a tendency to mess with the following... */
cd83521998-02-02Fredrik Hübinette (Hubbe) #ifdef SIGSEGV
a658b72015-10-23Henrik Grubbström (Grubba)  case SIGSEGV: my_signal(sig, SIG_DFL); break;
cd83521998-02-02Fredrik Hübinette (Hubbe) #endif #ifdef SIGBUS
a658b72015-10-23Henrik Grubbström (Grubba)  case SIGBUS: my_signal(sig, SIG_DFL); break;
cd83521998-02-02Fredrik Hübinette (Hubbe) #endif
1ed6892010-09-22Henrik Grubbström (Grubba) #ifdef SIGXFSZ
a658b72015-10-23Henrik Grubbström (Grubba)  case SIGXFSZ: my_signal(sig, SIG_DFL); break;
1ed6892010-09-22Henrik Grubbström (Grubba) #endif #ifdef SIGILL
a658b72015-10-23Henrik Grubbström (Grubba)  case SIGILL: my_signal(SIGILL, SIG_DFL); break;
71b44e1998-06-05Fredrik Hübinette (Hubbe) #endif
a658b72015-10-23Henrik Grubbström (Grubba)  default: break;
a96b282007-05-17Henrik Grubbström (Grubba)  } }
a658b72015-10-23Henrik Grubbström (Grubba) }
a96b282007-05-17Henrik Grubbström (Grubba) 
a658b72015-10-23Henrik Grubbström (Grubba) /* This fuction may be called from modules that may have thrashed * the signal handler state on load. eg the Java module. */ PMOD_EXPORT void low_init_signals(void) { int e;
e974952013-01-01Henrik Grubbström (Grubba)  /* Restore any custom signals if needed. */
940a4b2005-05-25Henrik Grubbström (Grubba)  for(e=0;e<MAX_SIGNALS;e++) {
a658b72015-10-23Henrik Grubbström (Grubba)  restore_signal_handler(e);
940a4b2005-05-25Henrik Grubbström (Grubba)  } } void init_signals(void) { int e; INIT_FIFO(sig, unsigned char); INIT_FIFO(wait,wait_data); #ifdef __NT__ init_interleave_mutex(&handle_protection_mutex); #endif /* __NT__ */
061ca91999-04-01Fredrik Hübinette (Hubbe) 
1ab4ac2008-01-26Martin Stjernholm  for(e=0;e<MAX_SIGNALS;e++) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE(signal_callbacks[e], PIKE_T_INT); SET_SVAL_SUBTYPE(signal_callbacks[e], NUMBER_NUMBER);
1ab4ac2008-01-26Martin Stjernholm  }
cb22561995-10-11Fredrik Hübinette (Hubbe) 
940a4b2005-05-25Henrik Grubbström (Grubba)  low_init_signals(); #ifdef USE_PID_MAPPING pid_mapping=allocate_mapping(2); #endif
b4b3a82015-07-31Martin Nilsson #ifdef USE_WAIT_THREAD co_init(& process_status_change); co_init(& start_wait_thread); mt_init(& wait_thread_mutex); #endif
8a9b652001-08-30Fredrik Hübinette (Hubbe) #if 0
c38ede1999-04-02Fredrik Hübinette (Hubbe)  if(!signal_evaluator_callback) { signal_evaluator_callback=add_to_callback(&evaluator_callbacks, check_signals, 0,0);
424d9c1999-05-02Fredrik Hübinette (Hubbe)  dmalloc_accept_leak(signal_evaluator_callback);
c38ede1999-04-02Fredrik Hübinette (Hubbe)  }
8a9b652001-08-30Fredrik Hübinette (Hubbe) #endif
c38ede1999-04-02Fredrik Hübinette (Hubbe) 
2fc55f2006-12-27Henrik Grubbström (Grubba)  START_NEW_PROGRAM_ID(PROCESS);
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct pid_status);
0995032011-09-08Henrik Grubbström (Grubba)  PIKE_MAP_VARIABLE("__pid", OFFSETOF(pid_status, pid), tInt, T_INT, ID_PROTECTED);
2fc55f2006-12-27Henrik Grubbström (Grubba) #ifndef __NT__
c67a1b2011-09-08Henrik Grubbström (Grubba)  /* Note that several of the fields are renamed to * match closer with the corresponding function. */
0995032011-09-08Henrik Grubbström (Grubba)  PIKE_MAP_VARIABLE("__last_signal", OFFSETOF(pid_status, sig), tInt, T_INT, ID_PROTECTED); PIKE_MAP_VARIABLE("__flags", OFFSETOF(pid_status, flags), tInt, T_INT, ID_PROTECTED|ID_PRIVATE); /* Don't touch! */
c67a1b2011-09-08Henrik Grubbström (Grubba)  PIKE_MAP_VARIABLE("__status", OFFSETOF(pid_status, state),
0995032011-09-08Henrik Grubbström (Grubba)  tInt, T_INT, ID_PROTECTED); PIKE_MAP_VARIABLE("__result", OFFSETOF(pid_status, result), tInt, T_INT, ID_PROTECTED);
2fc55f2006-12-27Henrik Grubbström (Grubba)  PIKE_MAP_VARIABLE("__callback", OFFSETOF(pid_status, callback),
0995032011-09-08Henrik Grubbström (Grubba)  tFunc(tObjIs_PROCESS,tVoid), T_MIXED, ID_PROTECTED);
2fc55f2006-12-27Henrik Grubbström (Grubba) #endif /* !__NT__ */
85f59e1998-01-08Fredrik Hübinette (Hubbe)  set_init_callback(init_pid_status); set_exit_callback(exit_pid_status);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string:int) */
111b1d2014-08-22Martin Nilsson  ADD_FUNCTION("set_priority",f_pid_status_set_priority,tFunc(tStr,tIntPos),0);
b143542003-02-28Henrik Grubbström (Grubba)  /* function(int(0..1)|void:int) */
dad69b2003-03-01Henrik Grubbström (Grubba)  ADD_FUNCTION("wait",f_pid_status_wait,tFunc(tNone,tInt),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:int) */
e64f5a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("status",f_pid_status_status,tFunc(tNone,tInt),0);
b143542003-02-28Henrik Grubbström (Grubba)  /* function(:int) */ ADD_FUNCTION("last_signal", f_pid_status_last_signal,tFunc(tNone,tInt),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:int) */
e64f5a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("pid",f_pid_status_pid,tFunc(tNone,tInt),0);
53acc21999-05-24Henrik Grubbström (Grubba) #ifdef HAVE_KILL /* function(int:int) */
2f70502014-07-10Henrik Grubbström (Grubba)  ADD_FUNCTION("kill", f_pid_status_kill, tFunc(tInt,tInt01), 0);
53acc21999-05-24Henrik Grubbström (Grubba) #endif /* HAVE_KILL */
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(array(string),void|mapping(string:mixed):object) */ ADD_FUNCTION("create",f_create_process,tFunc(tArr(tStr) tOr(tVoid,tMap(tStr,tMix)),tObj),0);
dad69b2003-03-01Henrik Grubbström (Grubba) 
85f59e1998-01-08Fredrik Hübinette (Hubbe)  pid_status_program=end_program(); add_program_constant("create_process",pid_status_program,0);
dad69b2003-03-01Henrik Grubbström (Grubba) #ifdef HAVE_PTRACE start_new_program(); /* NOTE: This inherit MUST be first! */ low_inherit(pid_status_program, NULL, -1, 0, 0, NULL); set_init_callback(init_trace_process); set_exit_callback(exit_trace_process); /* NOTE: Several of the functions inherited from pid_status_program * change behaviour if PROCESS_FLAG_TRACED is set. */ /* function(int|void:void) */ ADD_FUNCTION("cont",f_trace_process_cont, tFunc(tOr(tVoid,tInt),tVoid), 0); /* function(:void) */ ADD_FUNCTION("exit", f_trace_process_exit, tFunc(tNone, tVoid), 0);
4499d52003-03-06Henrik Grubbström (Grubba) #if 0 /* Disabled for now. */ start_new_program(); Pike_compiler->new_program->flags |= PROGRAM_USES_PARENT;
95489a2008-06-29Martin Nilsson  ADD_FUNCTION("`[]", f_proc_reg_index, tFunc(tMix, tInt), ID_PROTECTED);
4499d52003-03-06Henrik Grubbström (Grubba)  end_class("Registers", 0); #endif /* 0 */
dad69b2003-03-01Henrik Grubbström (Grubba)  end_class("TraceProcess", 0); #endif /* HAVE_PTRACE */
13670c2015-05-25Martin Nilsson 
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(string,int|void:int) */ ADD_EFUN("set_priority",f_set_priority,tFunc(tStr tOr(tInt,tVoid),tInt),
72850a1999-02-01Per Hedbor  OPT_SIDE_EFFECT);
13670c2015-05-25Martin Nilsson 
8057a32003-05-10Henrik Grubbström (Grubba)  ADD_EFUN("signal",f_signal, tFunc(tInt tOr(tVoid,tFunc(tOr(tVoid,tInt),tVoid)),tMix),
0220702003-05-10Martin Stjernholm  OPT_SIDE_EFFECT);
45f2a22002-09-10Martin Nilsson 
75920f1997-12-28Fredrik Hübinette (Hubbe) #ifdef HAVE_KILL
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(int|object,int:int) */
2f70502014-07-10Henrik Grubbström (Grubba)  ADD_EFUN("kill", f_kill, tFunc(tOr(tInt,tObj) tInt,tInt01), OPT_SIDE_EFFECT);
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
45f2a22002-09-10Martin Nilsson 
85f59e1998-01-08Fredrik Hübinette (Hubbe) #ifdef HAVE_FORK
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(void:object) */
cfbc2e2000-03-21Fredrik Hübinette (Hubbe)  ADD_EFUN("fork",Pike_f_fork,tFunc(tVoid,tObj),OPT_SIDE_EFFECT);
85f59e1998-01-08Fredrik Hübinette (Hubbe) #endif
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(int:string) */ ADD_EFUN("signame",f_signame,tFunc(tInt,tStr),0);
13670c2015-05-25Martin Nilsson 
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(string:int) */ ADD_EFUN("signum",f_signum,tFunc(tStr,tInt),0);
13670c2015-05-25Martin Nilsson 
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(:int) */
3bda2c2004-01-13Martin Nilsson  ADD_EFUN("getpid",f_getpid,tFunc(tNone,tInt),OPT_EXTERNAL_DEPEND);
45f2a22002-09-10Martin Nilsson 
75920f1997-12-28Fredrik Hübinette (Hubbe) #ifdef HAVE_ALARM
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(int:int) */ ADD_EFUN("alarm",f_alarm,tFunc(tInt,tInt),OPT_SIDE_EFFECT);
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
45f2a22002-09-10Martin Nilsson 
d1b8ea1998-09-05Henrik Grubbström (Grubba) #if defined(HAVE_UALARM) || defined(HAVE_SETITIMER)
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(int:int) */ ADD_EFUN("ualarm",f_ualarm,tFunc(tInt,tInt),OPT_SIDE_EFFECT);
0f87291999-05-07Fredrik Hübinette (Hubbe) #endif
5f06241999-04-11Fredrik Hübinette (Hubbe) 
abe6612000-01-15Fredrik Hübinette (Hubbe)  ADD_EFUN("atexit",f_atexit,tFunc(tMix,tVoid),OPT_SIDE_EFFECT);
cb22561995-10-11Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void exit_signals(void)
cb22561995-10-11Fredrik Hübinette (Hubbe) { int e;
4499d52003-03-06Henrik Grubbström (Grubba) #ifdef USE_PID_MAPPING
85f59e1998-01-08Fredrik Hübinette (Hubbe)  if(pid_mapping) { free_mapping(pid_mapping); pid_mapping=0; } #endif if(pid_status_program) { free_program(pid_status_program); pid_status_program=0; }
cb22561995-10-11Fredrik Hübinette (Hubbe)  for(e=0;e<MAX_SIGNALS;e++) { free_svalue(signal_callbacks+e);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE(signal_callbacks[e], PIKE_T_INT); SET_SVAL_SUBTYPE(signal_callbacks[e], NUMBER_NUMBER);
cb22561995-10-11Fredrik Hübinette (Hubbe)  } }