From 190fb06a3aaade80f7491a43fc6722a1689292d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Sat, 10 May 1997 05:57:39 -0700
Subject: [PATCH] fork() now returns an object thread_id->wait() implemented

Rev: lib/master.pike:1.43.2.1
Rev: lib/modules/Process.pmod:1.7.2.1
Rev: src/backend.c:1.10.2.1
Rev: src/backend.h:1.2.2.1
Rev: src/configure.in:1.93.2.1
Rev: src/language.yacc:1.42.2.1
Rev: src/mapping.c:1.18.2.1
Rev: src/modules/files/efuns.c:1.22.2.1
Rev: src/modules/files/file.c:1.37.2.1
Rev: src/modules/files/socktest.pike:1.2.2.1
Rev: src/modules/readline/readlinemod.c:1.2.2.1
Rev: src/object.c:1.17.2.1
Rev: src/object.h:1.9.2.1
Rev: src/program.c:1.33.2.1
Rev: src/program.h:1.14.2.1
Rev: src/signal_handler.c:1.11.2.1
Rev: src/threads.c:1.23.2.1
---
 lib/master.pike                    |  20 +++
 lib/modules/Process.pmod           |  37 +---
 src/backend.c                      |  50 ++++--
 src/backend.h                      |   3 +
 src/configure.in                   |   4 +-
 src/language.yacc                  |  66 ++++++--
 src/mapping.c                      |  11 +-
 src/modules/files/efuns.c          |  13 --
 src/modules/files/file.c           |   4 +-
 src/modules/files/socktest.pike    |   4 +-
 src/modules/readline/readlinemod.c |  10 ++
 src/object.c                       |   4 +-
 src/object.h                       |   3 +
 src/program.c                      |  47 +++++-
 src/program.h                      |   8 +-
 src/signal_handler.c               | 263 ++++++++++++++++++++++++++---
 src/threads.c                      |  73 +++++++-
 17 files changed, 497 insertions(+), 123 deletions(-)

diff --git a/lib/master.pike b/lib/master.pike
index c56406f582..5aad3438d4 100644
--- a/lib/master.pike
+++ b/lib/master.pike
@@ -9,6 +9,8 @@ string *pike_include_path=({});
 string *pike_module_path=({});
 string *pike_program_path=({});
 
+int want_warnings;
+
 mapping (string:string) environment=([]);
 
 varargs mixed getenv(string s)
@@ -362,6 +364,7 @@ void _main(string *argv, string *env)
   q=tmp->find_all_options(argv,({
     ({"version",tmp->NO_ARG,({"-v","--version"})}),
       ({"help",tmp->NO_ARG,({"-h","--help"})}),
+	({"warnings",tmp->NO_ARG,({"-w","--warnings"})}),
 	({"execute",tmp->HAS_ARG,({"-e","--execute"})}),
 	  ({"modpath",tmp->HAS_ARG,({"-M","--module-path"})}),
 	    ({"ipath",tmp->HAS_ARG,({"-I","--include-path"})}),
@@ -392,6 +395,10 @@ void _main(string *argv, string *env)
     {
       switch(opts[0])
       {
+      case "warnings":
+	want_warnings++;
+	break;
+
       case "version":
 	werror(version() + " Copyright (C) 1994-1997 Fredrik H�binette\n"
 	       "Pike comes with ABSOLUTELY NO WARRANTY; This is free software and you are\n"
@@ -497,6 +504,19 @@ void compile_error(string file,int line,string err)
   }
 }
 
+void compile_warning(string file,int line,string err)
+{
+  if(!inhibit_compile_errors)
+  {
+    if(want_warnings)
+      werror(sprintf("%s:%d:%s\n",trim_file_name(file),line,err));
+  }
+  else if(functionp(inhibit_compile_errors))
+  {
+    inhibit_compile_errors(file,line,err);
+  }
+}
+
 /* This function is called whenever an #include directive is encountered
  * it receives the argument for #include and should return the file name
  * of the file to include
diff --git a/lib/modules/Process.pmod b/lib/modules/Process.pmod
index 7b7e61294b..18759713dd 100644
--- a/lib/modules/Process.pmod
+++ b/lib/modules/Process.pmod
@@ -19,18 +19,11 @@ varargs int exec(string file,string ... foo)
   return 69;
 }
 
-varargs int spawn(string s,object stdin,object stdout,object stderr)
+varargs object spawn(string s,object stdin,object stdout,object stderr)
 {
-  int pid;
-
-  pid=fork();
-  
-  if(pid==-1)
-    error("No more processes.\n");
-
-  if(pid)
+  if(object proc=fork())
   {
-    return pid;
+    return proc;
   }else{
     if(stdin) {
       stdin->dup2(File("stdin"));
@@ -63,7 +56,7 @@ string popen(string s)
   p->close();
   destruct(p);
 
-  t=read(0x7fffffff);
+  t=read();
   if(!t)
   {
     int e;
@@ -76,27 +69,7 @@ string popen(string s)
   return t;
 }
 
-void system(string s)
-{
-  object p;
-  int pid;
-  string t;
-
-  p=file::pipe();
-  if(!p) error("System() failed.\n");
-  p->set_close_on_exec(0);
-  if(pid=fork())
-  {
-    destruct(p);
-    /* Nothing will ever be written here, we are just waiting for it
-     * to close
-     */
-    file::read(1);
-  }else{
-    exec("/bin/sh","-c",s);
-    exit(69);
-  }
-}
+int system(string s) { return spawn(s)->wait(); }
  
 constant fork = predef::fork;
 constant exece = predef::exece;
diff --git a/src/backend.c b/src/backend.c
index c73a46fcd3..588f28bde2 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: backend.c,v 1.10 1997/03/01 01:43:01 hubbe Exp $");
+RCSID("$Id: backend.c,v 1.10.2.1 1997/05/10 12:56:54 hubbe Exp $");
 #include "backend.h"
 #include <errno.h>
 #ifdef HAVE_SYS_TYPES_H
@@ -72,6 +72,28 @@ void wake_up_backend(void)
     write(wakeup_pipe[1], &foo ,1);
 }
 
+void init_signal_wait()
+{
+  may_need_wakeup=1;
+}
+
+void exit_signal_wait()
+{
+  may_need_wakeup=0;
+}
+
+void wait_for_signal()
+{
+  fd_set rset;
+  may_need_wakeup=1;
+  FD_ZERO(&rset);
+  FD_SET(wakeup_pipe[0], &rset);
+  THREADS_ALLOW();
+  select(wakeup_pipe[0]+1, &rset, 0, 0, 0);
+  THREADS_DISALLOW();
+  wakeup_callback(wakeup_pipe[0], 0);
+}
+
 void init_backend()
 {
   FD_ZERO(&selectors.read);
@@ -221,21 +243,21 @@ void backend()
     next_timeout.tv_usec = 0;
     next_timeout.tv_sec = 7 * 24 * 60 * 60;  /* See you in a week */
     my_add_timeval(&next_timeout, &current_time);
-
+    
     may_need_wakeup=1;
     call_callback(& backend_callbacks, (void *)0);
-
+    
     check_threads_etc();
-
-    sets=selectors;
-
     alloca(0);			/* Do garbage collect */
+    
+    sets=selectors;
+    
 #ifdef DEBUG
     if(d_flag > 1) do_debug();
 #endif
-
+    
     GETTIMEOFDAY(&current_time);
-
+    
     if(my_timercmp(&next_timeout, > , &current_time))
     {
       my_subtract_timeval(&next_timeout, &current_time);
@@ -243,20 +265,20 @@ void backend()
       next_timeout.tv_usec = 0;
       next_timeout.tv_sec = 0;
     }
-
+    
     THREADS_ALLOW();
     i=select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout);
     GETTIMEOFDAY(&current_time);
     THREADS_DISALLOW();
     may_need_wakeup=0;
-
+    
     if(i>=0)
     {
       for(i=0; i<max_fd+1; i++)
       {
 	if(FD_ISSET(i, &sets.read) && read_callback[i])
 	  (*(read_callback[i]))(i,read_callback_data[i]);
-
+	
 	if(FD_ISSET(i, &sets.write) && write_callback[i])
 	  (*(write_callback[i]))(i,write_callback_data[i]);
       }
@@ -266,10 +288,10 @@ void backend()
       case EINVAL:
 	fatal("Invalid timeout to select().\n");
 	break;
-
+	
       case EINTR:		/* ignore */
 	break;
-
+	
       case EBADF:
 	sets=selectors;
 	next_timeout.tv_usec=0;
@@ -279,7 +301,7 @@ void backend()
 	  fatal("Bad filedescriptor to select().\n");
 	}
 	break;
-
+	
       }
     }
     call_callback(& backend_callbacks, (void *)1);
diff --git a/src/backend.h b/src/backend.h
index f571718588..464c45b916 100644
--- a/src/backend.h
+++ b/src/backend.h
@@ -20,6 +20,9 @@ struct callback *add_backend_callback(callback_func call,
 				      void *arg,
 				      callback_func free_func);
 void wake_up_backend(void);
+void init_signal_wait();
+void exit_signal_wait();
+void wait_for_signal();
 void init_backend();
 void set_read_callback(int fd,file_callback cb,void *data);
 void set_write_callback(int fd,file_callback cb,void *data);
diff --git a/src/configure.in b/src/configure.in
index c56aee0cbc..5026e7077f 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1,4 +1,4 @@
-AC_REVISION("$Id: configure.in,v 1.93 1997/05/07 06:27:30 per Exp $")
+AC_REVISION("$Id: configure.in,v 1.93.2.1 1997/05/10 12:56:54 hubbe Exp $")
 AC_INIT(interpret.c)
 AC_CONFIG_HEADER(machine.h)
 
@@ -679,6 +679,8 @@ AC_CHECK_FUNCS(
  strtod \
  strtok \
  strtol \
+ sigprocmask \
+ sigblock \
  times \
  vfprintf \
  vsprintf \
diff --git a/src/language.yacc b/src/language.yacc
index 74aab449be..cf53c114e4 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -156,7 +156,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.42 1997/05/07 06:25:35 per Exp $");
+RCSID("$Id: language.yacc,v 1.42.2.1 1997/05/10 12:56:55 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -205,6 +205,17 @@ void fix_comp_stack(int sp)
   }
 }
 
+void pop_local_variables(int level)
+{
+  while(local_variables->current_number_of_locals > level)
+  {
+    int e;
+    e=--(local_variables->current_number_of_locals);
+    free_string(local_variables->variable[e].name);
+    free_string(local_variables->variable[e].type);
+  }
+}
+
 %}
 
 %union
@@ -795,13 +806,7 @@ block:'{'
   } 
   statements '}'
   {
-    while(local_variables->current_number_of_locals > $<number>2)
-    {
-      int e;
-      e=--(local_variables->current_number_of_locals);
-      free_string(local_variables->variable[e].name);
-      free_string(local_variables->variable[e].type);
-    }
+    pop_local_variables($<number>2);
     $$=$3;
   }
   ;
@@ -932,12 +937,17 @@ class: modifiers F_CLASS optional_identifier
   }
   ;
 
-cond: F_IF '(' comma_expr ')' statement optional_else_part
+cond: F_IF
+  {
+    $<number>$=local_variables->current_number_of_locals;
+  }
+  '(' comma_expr ')' statement optional_else_part
   {
-    $$=mknode('?',$3,mknode(':',$5,$6));
+    $$=mknode('?',$4,mknode(':',$6,$7));
     $$->line_number=$1;
     $$=mkcastnode(void_type_string,$$);
     $$->line_number=$1;
+    pop_local_variables($<number>2);
   }
   ;
 
@@ -945,10 +955,15 @@ optional_else_part: { $$=0; }
   | F_ELSE statement { $$=$2; }
   ;      
 
-foreach: F_FOREACH '(' expr0 ',' lvalue ')' statement
+foreach: F_FOREACH
   {
-    $$=mknode(F_FOREACH,mknode(F_VAL_LVAL,$3,$5),$7);
+    $<number>$=local_variables->current_number_of_locals;
+  }
+  '(' expr0 ',' lvalue ')' statement
+  {
+    $$=mknode(F_FOREACH, mknode(F_VAL_LVAL,$4,$6),$8);
     $$->line_number=$1;
+    pop_local_variables($<number>2);
   }
   ;
 
@@ -959,22 +974,32 @@ do: F_DO statement F_WHILE '(' comma_expr ')' ';'
   }
   ;
 
-for: F_FOR '(' unused  ';' for_expr ';' unused ')' statement
+for: F_FOR
+  {
+    $<number>$=local_variables->current_number_of_locals;
+  }
+  '(' unused  ';' for_expr ';' unused ')' statement
   {
     int i=current_line;
     current_line=$1;
-    $$=mknode(F_ARG_LIST,mkcastnode(void_type_string,$3),mknode(F_FOR,$5,mknode(':',$9,$7)));
+    $$=mknode(F_ARG_LIST,mkcastnode(void_type_string,$4),mknode(F_FOR,$6,mknode(':',$10,$8)));
     current_line=i;
+    pop_local_variables($<number>2);
   }
   ;
 
 
-while:  F_WHILE '(' comma_expr ')' statement
+while:  F_WHILE
+  {
+    $<number>$=local_variables->current_number_of_locals;
+  }
+  '(' comma_expr ')' statement
   {
     int i=current_line;
     current_line=$1;
-    $$=mknode(F_FOR,$3,mknode(':',$5,NULL));
+    $$=mknode(F_FOR,$4,mknode(':',$6,NULL));
     current_line=i;
+    pop_local_variables($<number>2);
   }
   ;
 
@@ -982,10 +1007,15 @@ for_expr: /* EMPTY */ { $$=mkintnode(1); }
   | comma_expr
   ;
 
-switch:	F_SWITCH '(' comma_expr ')' statement
+switch:	F_SWITCH
+  {
+    $<number>$=local_variables->current_number_of_locals;
+  }
+  '(' comma_expr ')' statement
   {
-    $$=mknode(F_SWITCH,$3,$5);
+    $$=mknode(F_SWITCH,$4,$6);
     $$->line_number=$1;
+    pop_local_variables($<number>2);
   }
   ;
 
diff --git a/src/mapping.c b/src/mapping.c
index 82a95a0f3f..80ae947486 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.18 1997/04/23 23:06:16 hubbe Exp $");
+RCSID("$Id: mapping.c,v 1.18.2.1 1997/05/10 12:56:55 hubbe Exp $");
 #include "main.h"
 #include "types.h"
 #include "object.h"
@@ -495,6 +495,15 @@ struct svalue *low_mapping_string_lookup(struct mapping *m,
   return low_mapping_lookup(m, &tmp);
 }
 
+struct svalue *low_mapping_int_lookup(struct mapping *m,
+				      INT32 p)
+{
+  struct svalue tmp;
+  tmp.type=T_INT;
+  tmp.u.integer=p;
+  return low_mapping_lookup(m, &tmp);
+}
+
 void mapping_index_no_free(struct svalue *dest,
 			   struct mapping *m,
 			   struct svalue *key)
diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index a0b34014d3..b190fd0c97 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -357,18 +357,6 @@ void f_getcwd(INT32 args)
   free(e);
 }
 
-void f_fork(INT32 args)
-{
-  do_set_close_on_exec();
-  pop_n_elems(args);
-#if defined(HAVE_FORK1) && defined(_REENTRANT)
-  push_int(fork1());
-#else
-  push_int(fork());
-#endif
-}
-
-
 void f_exece(INT32 args)
 {
   INT32 e;
@@ -526,7 +514,6 @@ void init_files_efuns()
   add_efun("get_dir",f_get_dir,"function(string:string *)",OPT_EXTERNAL_DEPEND);
   add_efun("cd",f_cd,"function(string:int)",OPT_SIDE_EFFECT);
   add_efun("getcwd",f_getcwd,"function(:string)",OPT_EXTERNAL_DEPEND);
-  add_efun("fork",f_fork,"function(:int)",OPT_SIDE_EFFECT);
   add_efun("exece",f_exece,"function(string,mixed*,void|mapping(string:string):int)",OPT_SIDE_EFFECT); 
 
 #ifdef HAVE_STRERROR
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index c1cba2ced7..a31053a664 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 #define READ_BUFFER 8192
 
 #include "global.h"
-RCSID("$Id: file.c,v 1.37 1997/05/05 05:29:37 nisse Exp $");
+RCSID("$Id: file.c,v 1.37.2.1 1997/05/10 12:57:28 hubbe Exp $");
 #include "types.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -1465,7 +1465,7 @@ void pike_module_init()
 
   add_function("open",file_open,"function(string,string:int)",0);
   add_function("close",file_close,"function(string|void:int)",0);
-  add_function("read",file_read,"function(int,int|void:int|string)",0);
+  add_function("read",file_read,"function(int|void,int|void:int|string)",0);
   add_function("write",file_write,"function(string:int)",0);
 
   add_function("seek",file_seek,"function(int:int)",0);
diff --git a/src/modules/files/socktest.pike b/src/modules/files/socktest.pike
index 6952a7caa0..354457746b 100755
--- a/src/modules/files/socktest.pike
+++ b/src/modules/files/socktest.pike
@@ -232,7 +232,7 @@ void finish()
     case 22:
       werror("Testing accept. ");
       string data1=strmult("foobar",4711);
-      for(e=0;e<10;e++)
+      for(int e=0;e<10;e++)
       {
 	sock1=Socket();
 	sock1->connect("127.0.0.1",portno1);
@@ -243,7 +243,7 @@ void finish()
     case 23..45:
       tests=(_tests-22)*2;
       werror("Testing "+(tests*2)+" sockets. ");
-      for(e=0;e<tests;e++) stdtest();
+      for(int e=0;e<tests;e++) stdtest();
       break;
 
     case 46:
diff --git a/src/modules/readline/readlinemod.c b/src/modules/readline/readlinemod.c
index 6aa2001375..35e07b41f1 100644
--- a/src/modules/readline/readlinemod.c
+++ b/src/modules/readline/readlinemod.c
@@ -59,10 +59,20 @@ static void f_readline(INT32 args)
     error("Bad argument 1 to readline()\n");
 
   str=sp[-args].u.string;
+retry:
   THREADS_ALLOW();
   r=readline(str->str);
   THREADS_DISALLOW();
 
+#ifdef _REENTRANT
+  /* This kluge might fix some problems with readline and threads */
+  if(!r && errno==EINTR)
+  {
+    check_threads_etc();
+    goto retry;
+  }
+#endif
+
   pop_n_elems(args);
   if(r)
   {
diff --git a/src/object.c b/src/object.c
index 93cd6cac8c..af163ae754 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: object.c,v 1.17 1997/04/16 03:09:14 hubbe Exp $");
+RCSID("$Id: object.c,v 1.17.2.1 1997/05/10 12:56:56 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -416,7 +416,7 @@ void object_index_no_free(struct svalue *to,
 }
 
 
-static void object_low_set_index(struct object *o,
+void object_low_set_index(struct object *o,
 				 int f,
 				 struct svalue *from)
 {
diff --git a/src/object.h b/src/object.h
index 28f4d91878..5ac6bae012 100644
--- a/src/object.h
+++ b/src/object.h
@@ -54,6 +54,9 @@ void object_index_no_free2(struct svalue *to,
 void object_index_no_free(struct svalue *to,
 			   struct object *o,
 			   struct svalue *index);
+void object_low_set_index(struct object *o,
+				 int f,
+				 struct svalue *from);
 void object_set_index2(struct object *o,
 		      struct svalue *index,
 		      struct svalue *from);
diff --git a/src/program.c b/src/program.c
index c1020557eb..edb83e8c18 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.33 1997/04/16 03:09:16 hubbe Exp $");
+RCSID("$Id: program.c,v 1.33.2.1 1997/05/10 12:56:56 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -28,6 +28,11 @@ RCSID("$Id: program.c,v 1.33 1997/04/16 03:09:16 hubbe Exp $");
 #include <errno.h>
 #include <fcntl.h>
 
+
+#undef ATTRIBUTE
+#define ATTRIBUTE(X)
+
+
 /*
  * Define the size of the cache that is used for method lookup.
  */
@@ -962,6 +967,21 @@ int define_variable(struct pike_string *name,
   return n;
 }
 
+int simple_add_variable(char *name,
+			char *type,
+			INT32 flags)
+{
+  INT32 ret;
+  struct pike_string *name_s, *type_s;
+  name_s=make_shared_string(name);
+  type_s=parse_type(type);
+  
+  ret=define_variable(name_s, type_s, flags);
+  free_string(name_s);
+  free_string(type_s);
+  return ret;
+}
+
 int add_constant(struct pike_string *name,
 		 struct svalue *c,
 		 INT32 flags)
@@ -1455,10 +1475,10 @@ char *get_line(unsigned char *pc,struct program *prog,INT32 *linep)
   return file;
 }
 
-void my_yyerror(char *fmt,...)
+void my_yyerror(char *fmt,...)  ATTRIBUTE((format(printf,1,2)))
 {
   va_list args;
-  char buf[1000];
+  char buf[8192];
   va_start(args,fmt);
   VSPRINTF(buf,fmt,args);
 
@@ -1756,3 +1776,24 @@ char *get_storage(struct object *o, struct program *p)
   if(offset == -1) return 0;
   return o->storage + offset;
 }
+
+void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2)))
+{
+  char buf[4711];
+  va_list args;
+  va_start(args,fmt);
+  VSPRINTF(buf, fmt, args);
+  va_end(args);
+
+  if(strlen(buf)>sizeof(buf))
+    fatal("Buffer overfloat in yywarning!\n");
+
+  if(get_master())
+  {
+    ref_push_string(current_file);
+    push_int(current_line);
+    push_text(buf);
+    SAFE_APPLY_MASTER("compile_warning",3);
+    pop_stack();
+  }
+}
diff --git a/src/program.h b/src/program.h
index 900c03156d..6444becb75 100644
--- a/src/program.h
+++ b/src/program.h
@@ -202,6 +202,9 @@ int isidentifier(struct pike_string *s);
 int define_variable(struct pike_string *name,
 		    struct pike_string *type,
 		    INT32 flags);
+int simple_add_variable(char *name,
+			char *type,
+			INT32 flags);
 int add_constant(struct pike_string *name,
 		 struct svalue *c,
 		 INT32 flags);
@@ -236,7 +239,7 @@ int store_constant(struct svalue *foo, int equal);
 void start_line_numbering(void);
 void store_linenumber(INT32 current_line, struct pike_string *current_file);
 char *get_line(unsigned char *pc,struct program *prog,INT32 *linep);
-void my_yyerror(char *fmt,...);
+void my_yyerror(char *fmt,...)  ATTRIBUTE((format(printf,1,2)));
 void compile();
 struct program *compile_file(struct pike_string *file_name);
 struct program *compile_string(struct pike_string *prog,
@@ -252,11 +255,10 @@ void count_memory_in_programs(INT32 *num_, INT32 *size_);
 void push_locals();
 void pop_locals();
 char *get_storage(struct object *o, struct program *p);
+void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2)));
 /* Prototypes end here */
 
 
-void my_yyerror(char *fmt,...) ATTRIBUTE((format (printf, 1, 2)));
-
 #endif
 
 
diff --git a/src/signal_handler.c b/src/signal_handler.c
index dbcf0020d3..11072365f1 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.c
@@ -12,6 +12,8 @@
 #include "backend.h"
 #include "error.h"
 #include "callback.h"
+#include "mapping.h"
+#include "object.h"
 #include <signal.h>
 #include <sys/wait.h>
 
@@ -32,6 +34,7 @@ static struct svalue signal_callbacks[MAX_SIGNALS];
 static unsigned char sigbuf[SIGNAL_BUFFER];
 static int firstsig, lastsig;
 static struct callback *signal_evaluator_callback =0;
+static int sigchild_arrived=0;
 
 
 struct sigdesc
@@ -192,30 +195,6 @@ static void my_signal(int sig, sigfunctype fun)
 #endif
 }
 
-static RETSIGTYPE sig_child(int arg)
-{
-  /* We carefully reap what we saw */
-#ifdef HAVE_WAITPID
-  while(waitpid(-1,0,WNOHANG) > 0); 
-#else
-#ifdef HAVE_WAIT3
-  while( wait3(0,WNOHANG,0) > 0);
-#else
-#ifdef HAVE_WAIT4
-  while( wait4(-1,0,WNOHANG,0) > 0);
-#else
-
-  /* Leave'em hanging */
-
-#endif /* HAVE_WAIT4 */
-#endif /* HAVE_WAIT3 */
-#endif /* HAVE_WAITPID */
-
-#ifdef SIGNAL_ONESHOT
-  my_signal(SIGCHLD, sig_child);
-#endif
-}
-
 static RETSIGTYPE receive_signal(int signum)
 {
   int tmp;
@@ -225,7 +204,8 @@ static RETSIGTYPE receive_signal(int signum)
   if(tmp != lastsig)
     sigbuf[firstsig=tmp]=signum;
 
-  if(signum==SIGCHLD) sig_child(signum);
+  if(signum==SIGCHLD)
+    sigchild_arrived++;
 
   wake_up_backend();
 
@@ -268,6 +248,193 @@ void check_signals(struct callback *foo, void *bar, void *gazonk)
   }
 }
 
+#define PROCESS_UNKNOWN 0
+#define PROCESS_RUNNING 1
+#define PROCESS_EXITED 2
+
+#define THIS ((struct pid_status *)fp->current_storage)
+
+static struct callback *children_evaluator_callback =0;
+struct mapping *pid_mapping=0;;
+struct program *pid_status_program=0;
+
+struct pid_status
+{
+  int pid;
+  int state;
+  int result;
+};
+
+static void init_pid_status(struct object *o)
+{
+  THIS->pid=-1;
+  THIS->state=PROCESS_UNKNOWN;
+  THIS->result=-1;
+}
+
+static void exit_pid_status(struct object *o)
+{
+  if(pid_mapping)
+  {
+    struct svalue key;
+    key.type=T_INT;
+    key.u.integer=THIS->pid;
+    map_delete(pid_mapping, &key);
+  }
+}
+
+static RETSIGTYPE sig_child(int arg)
+{
+  wake_up_backend();
+  fprintf(stderr,"Got sigchild %d\n",sigchild_arrived);
+  sigchild_arrived++;
+
+#ifdef SIGNAL_ONESHOT
+  my_signal(SIGCHLD, sig_child);
+#endif
+}
+
+static void check_children(struct callback *foo, void *bar, void *gazonk)
+{
+  if(sigchild_arrived)
+  {
+#ifdef HAVE_SIGPROCMASK
+    sigset_t set, oset;
+    sigemptyset(&set);
+    sigaddset(&set, SIGCHLD);
+    sigprocmask(SIG_BLOCK, &set, &oset);
+#else
+#ifdef HAVE_SIGBLOCK
+    int oset;
+    oset=siggetmask();
+    sigblock(sigmask(SIGCHLD));
+#endif
+#endif
+    while(sigchild_arrived>0)
+    {
+      sigchild_arrived--;
+      while(1)
+      {
+	pid_t pid;
+	int status;
+	fprintf(stderr,"Waitpid...\n");
+      /* We carefully reap what we saw */
+#ifdef HAVE_WAITPID
+	pid=waitpid(-1,& status,WNOHANG);
+#else
+#ifdef HAVE_WAIT3
+	pid=wait3(&status,WNOHANG,0);
+#else
+#ifdef HAVE_WAIT4
+	pid=wait4(-1,&status,WNOHANG,0);
+#else
+	pid=-1;
+#endif
+#endif
+#endif
+	fprintf(stderr,"Done...\n");
+	if(pid>0)
+	{
+	  if(pid_mapping)
+	  {
+	    struct svalue *s, key;
+	    key.type=T_INT;
+	    key.u.integer=pid;
+	    if((s=low_mapping_lookup(pid_mapping, &key)))
+	    {
+	      if(s->type == T_OBJECT)
+	      {
+		struct pid_status *p;
+		if((p=(struct pid_status *)get_storage(s->u.object,
+						      pid_status_program)))
+		{
+		  p->state = PROCESS_EXITED;
+		  p->result = WEXITSTATUS(status);
+		}
+	      }
+	      map_delete(pid_mapping, &key);
+	    }
+	  }
+	}else{
+	  break;
+	}
+      }
+    }
+
+#ifdef HAVE_SIGPROCMASK
+    sigprocmask(SIG_SETMASK, &oset, 0);
+#else
+#ifdef HAVE_SIGBLOCk
+    sigsetmask(oset);
+#endif
+#endif
+  }
+}
+
+static void f_pid_status_wait(INT32 args)
+{
+  pop_n_elems(args);
+  init_signal_wait();
+  printf("Init wait\n");
+  while(THIS->state == PROCESS_RUNNING)
+  {
+    printf("Waiting...\n");
+    wait_for_signal();
+    printf("Woke up! %d\n",sigchild_arrived);
+    check_threads_etc();
+  }
+  printf("Done!\n");
+  exit_signal_wait();
+  push_int(THIS->result);
+}
+
+static void f_pid_status_status(INT32 args)
+{
+  pop_n_elems(args);
+  push_int(THIS->state);
+}
+
+static void f_pid_status_pid(INT32 args)
+{
+  pop_n_elems(args);
+  push_int(THIS->pid);
+}
+
+void f_fork(INT32 args)
+{
+  struct object *o;
+  pid_t pid;
+  pop_n_elems(args);
+#if defined(HAVE_FORK1) && defined(_REENTRANT)
+  pid=fork1();
+#else
+  pid=fork();
+#endif
+  if(pid==-1) error("Fork failed\n");
+
+  if(pid)
+  {
+    struct pid_status *p;
+    if(!children_evaluator_callback)
+    {
+      children_evaluator_callback=add_to_callback(&evaluator_callbacks,
+						  check_children,
+						  0,0);
+    }
+    o=clone_object(pid_status_program,0);
+    p=(struct pid_status *)get_storage(o,pid_status_program);
+    p->pid=pid;
+    p->state=PROCESS_RUNNING;
+    push_object(o);
+    push_int(pid);
+    mapping_insert(pid_mapping,sp-1, sp-2);
+    pop_stack();
+  }else{
+    push_int(0);
+  }
+}
+
+
 /* Get the name of a signal given the number */
 static char *signame(int sig)
 {
@@ -385,10 +552,30 @@ static void f_signame(int args)
 
 static void f_kill(INT32 args)
 {
+  pid_t pid;
   if(args < 2)
     error("Too few arguments to kill().\n");
-  if(sp[-args].type != T_INT)
+  switch(sp[-args].type)
+  {
+  case T_INT:
+    pid=sp[-args].u.integer;
+    break;
+
+  case T_OBJECT:
+  {
+    struct pid_status *p;
+    if((p=(struct pid_status *)get_storage(sp[-args].u.object,
+					  pid_status_program)))
+    {
+      pid=p->pid;
+      break;
+    }
+  }
+  default:
     error("Bad argument 1 to kill().\n");
+  }
+    
+  if(sp[-args].type != T_INT)
   if(sp[1-args].type != T_INT)
     error("Bad argument 1 to kill().\n");
 
@@ -452,12 +639,23 @@ void init_signals()
 
   firstsig=lastsig=0;
 
+  pid_mapping=allocate_mapping(2);
+  start_new_program();
+  add_storage(sizeof(struct pid_status));
+  set_init_callback(init_pid_status);
+  set_init_callback(exit_pid_status);
+  add_function("wait",f_pid_status_wait,"function(:int)",0);
+  add_function("status",f_pid_status_status,"function(:int)",0);
+  add_function("pid",f_pid_status_pid,"function(:int)",0);
+  pid_status_program=end_program();
+
   add_efun("signal",f_signal,"function(int,mixed|void:void)",OPT_SIDE_EFFECT);
-  add_efun("kill",f_kill,"function(int,int:int)",OPT_SIDE_EFFECT);
+  add_efun("kill",f_kill,"function(int|object,int:int)",OPT_SIDE_EFFECT);
   add_efun("signame",f_signame,"function(int:string)",0);
   add_efun("signum",f_signum,"function(string:int)",0);
   add_efun("getpid",f_getpid,"function(:int)",0);
   add_efun("alarm",f_alarm,"function(int:int)",OPT_SIDE_EFFECT);
+  add_efun("fork",f_fork,"function(:object)",OPT_SIDE_EFFECT);
 #ifdef HAVE_UALARM
   add_efun("ualarm",f_ualarm,"function(int:int)",OPT_SIDE_EFFECT);
 #endif
@@ -466,6 +664,17 @@ void init_signals()
 void exit_signals()
 {
   int e;
+  if(pid_mapping)
+  {
+    free_mapping(pid_mapping);
+    pid_mapping=0;
+  }
+
+  if(pid_status_program)
+  {
+    free_program(pid_status_program);
+    pid_status_program=0;
+  }
   for(e=0;e<MAX_SIGNALS;e++)
   {
     free_svalue(signal_callbacks+e);
diff --git a/src/threads.c b/src/threads.c
index b87be89dc3..0f1af7aa4d 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.23 1997/04/20 03:53:35 grubba Exp $");
+RCSID("$Id: threads.c,v 1.23.2.1 1997/05/10 12:56:57 hubbe Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -30,6 +30,19 @@ struct thread_starter
   struct array *args;
 };
 
+struct thread_id {
+  int status;
+  COND_T status_change;
+};
+
+static int thread_id_result_variable;
+
+static MUTEX_T thread_id_kluge = PTHREAD_MUTEX_INITIALIZER;
+
+#define THREAD_UNKNOWN 0
+#define THREAD_RUNNING 1
+#define THREAD_EXITED 2
+
 static void check_threads(struct callback *cb, void *arg, void * arg2)
 {
   THREADS_ALLOW();
@@ -39,6 +52,42 @@ static void check_threads(struct callback *cb, void *arg, void * arg2)
   THREADS_DISALLOW();
 }
 
+#define THIS_THREAD ((struct thread_id *)fp->current_storage)
+#define THREAD_INFO ((struct thread_id *)thread_id->storage)
+
+static void init_thread_id(struct object *o)
+{
+  THIS_THREAD->status=THREAD_UNKNOWN;
+  co_init(& THIS_THREAD->status_change);
+}
+
+static void exit_thread_id(struct object *o)
+{
+  co_destroy(& THIS_THREAD->status_change);
+}
+
+static void f_thread_id_status(INT32 args)
+{
+  pop_n_elems(args);
+  push_int(THIS_THREAD->status);
+}
+
+static void f_thread_id_result(INT32 args)
+{
+  struct thread_id *th=THIS_THREAD;
+  THREADS_ALLOW();
+  mt_lock(&thread_id_kluge);
+  while(th->status != THREAD_EXITED)
+    co_wait(&th->status_change, &thread_id_kluge);
+  mt_unlock(&thread_id_kluge);
+  THREADS_DISALLOW();
+
+  low_object_index_no_free(sp,
+			   fp->current_object, 
+			   thread_id_result_variable);
+  sp++;
+}
+
 void *new_thread_func(void * data)
 {
 /*  static int dbt;*/
@@ -54,6 +103,7 @@ void *new_thread_func(void * data)
   init_interpreter();
 
   thread_id=arg.id;
+  THREAD_INFO->status=THREAD_RUNNING;
 
   if(SETJMP(back))
   {
@@ -68,12 +118,19 @@ void *new_thread_func(void * data)
     push_array_items(arg.args);
     arg.args=0;
     f_call_function(args);
-    pop_stack(); /* Discard the return value. /Per */
+
+    fprintf(stderr,"Done ");
+    /* copy return value to the thread_id here */
+    object_low_set_index(thread_id,
+			 thread_id_result_variable,
+			 sp-1);
+    pop_stack();
   }
 
   UNSETJMP(back);
 
-  destruct(thread_id);
+  THREAD_INFO->status=THREAD_EXITED;
+  co_signal(& THREAD_INFO->status_change);
 
   free_object(thread_id);
   thread_id=0;
@@ -104,6 +161,7 @@ void f_thread_create(INT32 args)
   arg=ALLOC_STRUCT(thread_starter);
   arg->args=aggregate_array(args);
   arg->id=clone_object(thread_id_prog,0);
+  arg->id->refs++;
 
   tmp=th_create(&dummy,new_thread_func,arg);
 
@@ -121,8 +179,8 @@ void f_thread_create(INT32 args)
       th_setconcurrency(++num_lwps);
 #endif
     push_object(arg->id);
-    arg->id->refs++;
   } else {
+    free_object(arg->id);
     free_object(arg->id);
     free_array(arg->args);
     free((char *)arg);
@@ -365,6 +423,12 @@ void th_init()
   end_class("condition", 0);
 
   start_new_program();
+  add_storage(sizeof(struct thread_id));
+  thread_id_result_variable=simple_add_variable("result","mixed",0);
+  add_function("wait",f_thread_id_result,"function(:int)",0);
+  add_function("status",f_thread_id_status,"function(:int)",0);
+  set_init_callback(init_thread_id);
+  set_exit_callback(exit_thread_id);
   thread_id_prog=end_program();
   if(!mutex_key)
     fatal("Failed to initialize thread program!\n");
@@ -388,7 +452,6 @@ void th_cleanup()
 
   if(thread_id)
   {
-    destruct(thread_id);
     free_object(thread_id);
     thread_id=0;
   }
-- 
GitLab