c2a4061997-02-06Fredrik Hübinette (Hubbe) #define error(X) throw( ({ (X), backtrace()[0..sizeof(backtrace())-2] }) )
d5190b1997-02-10Fredrik Hübinette (Hubbe) import Stdio;
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
8392231998-01-08Fredrik Hübinette (Hubbe) program create_process = _static_modules.Builtin()->create_process;
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
8d49101998-01-21Fredrik Hübinette (Hubbe) int exec(string file,string ... foo)
c2a4061997-02-06Fredrik Hübinette (Hubbe) {
bcfe4f1997-06-09John W. Pierce  if (sizeof(file)) { string path;
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
bcfe4f1997-06-09John W. Pierce  if(search(file,"/") >= 0) return exece(combine_path(getcwd(),file),foo,getenv());
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
b6277d1997-06-10Fredrik Hübinette (Hubbe)  path=getenv("PATH");
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
b6277d1997-06-10Fredrik Hübinette (Hubbe)  foreach(path ? path/":" : ({}) , path)
bcfe4f1997-06-09John W. Pierce  if(file_stat(path=combine_path(path,file))) return exece(path, foo,getenv()); }
c2a4061997-02-06Fredrik Hübinette (Hubbe)  return 69; }
8392231998-01-08Fredrik Hübinette (Hubbe) string *split_quoted_string(string s)
c2a4061997-02-06Fredrik Hübinette (Hubbe) {
8392231998-01-08Fredrik Hübinette (Hubbe)  s=replace(s, ({"\"","'","\\"," "}), ({"\0\"","\0'","\0\\","\0 "})); string *x=s/"\0"; string *ret=({x[0]}); for(int e=1;e<sizeof(x);e++) { switch(x[e][0]) { case '"': ret[-1]+=x[e][1..]; while(x[++e][0]!='"') ret[-1]+=x[e]; ret[-1]+=x[e][1..]; break; case '\'': ret[-1]+=x[e][1..]; while(x[++e][0]!='\'') ret[-1]+=x[e]; ret[-1]+=x[e][1..]; break; case '\\': if(strlen(x[e])>1) { ret[-1]+=x[e][1..]; }else{ ret[-1]+=x[++e]; } break; case ' ': if(strlen(x[e]) > 1 || sizeof(x)==e+1 || x[e+1][0]!=' ') ret+=({x[e][1..]}); break; default: ret[-1]+="\0"+x[e]; break; } } return ret; }
8d49101998-01-21Fredrik Hübinette (Hubbe) object spawn(string s,object|void stdin,object|void stdout,object|void stderr, function|void cleanup, mixed ... args)
8392231998-01-08Fredrik Hübinette (Hubbe) { #if 1 mapping data=([]); if(stdin) data->stdin=stdin; if(stdout) data->stdout=stdout; if(stderr) data->stderr=stderr; return create_process(split_quoted_string(s),data); #else object pid;
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
04c34c1998-01-01Fredrik Hübinette (Hubbe) #if constant(fork)
c2a4061997-02-06Fredrik Hübinette (Hubbe)  pid=fork();
04c34c1998-01-01Fredrik Hübinette (Hubbe) #endif
c2a4061997-02-06Fredrik Hübinette (Hubbe)  if(pid) { return pid; }else{
f95b701997-05-21Fredrik Hübinette (Hubbe)  if(stdin ) stdin ->dup2(File("stdin")); if(stdout) stdout->dup2(File("stdout")); if(stderr) stderr->dup2(File("stderr")); if(stdin ) destruct(stdin); if(stdout) destruct(stdout); if(stderr) destruct(stderr);
dc50841997-11-05Henrik Grubbström (Grubba)  if (cleanup) { cleanup(@args); }
c2a4061997-02-06Fredrik Hübinette (Hubbe)  exec("/bin/sh","-c",s); exit(69); }
8392231998-01-08Fredrik Hübinette (Hubbe) #endif
c2a4061997-02-06Fredrik Hübinette (Hubbe) } string popen(string s) { object p; string t;
dc50841997-11-05Henrik Grubbström (Grubba)  object f = File(); if (!f) error("Popen failed. (couldn't create pipe)\n");
c2a4061997-02-06Fredrik Hübinette (Hubbe) 
bcf9461998-01-27Fredrik Hübinette (Hubbe)  p=f->pipe(Stdio.PROP_IPC);
c2a4061997-02-06Fredrik Hübinette (Hubbe)  if(!p) error("Popen failed. (couldn't create pipe)\n");
dc50841997-11-05Henrik Grubbström (Grubba)  spawn(s,0,p,0, destruct, f);
ef293f1997-05-07Henrik Grubbström (Grubba)  p->close();
c2a4061997-02-06Fredrik Hübinette (Hubbe)  destruct(p);
dc50841997-11-05Henrik Grubbström (Grubba)  t=f->read(0x7fffffff);
c2a4061997-02-06Fredrik Hübinette (Hubbe)  if(!t) { int e;
dc50841997-11-05Henrik Grubbström (Grubba)  e=f->errno(); f->close(); destruct(f);
c2a4061997-02-06Fredrik Hübinette (Hubbe)  error("Popen failed with error "+e+".\n");
dc50841997-11-05Henrik Grubbström (Grubba)  } else { f->close(); destruct(f);
c2a4061997-02-06Fredrik Hübinette (Hubbe)  } return t; }
8392231998-01-08Fredrik Hübinette (Hubbe) int system(string s)
c2a4061997-02-06Fredrik Hübinette (Hubbe) {
8392231998-01-08Fredrik Hübinette (Hubbe)  return spawn(s)->wait();
c2a4061997-02-06Fredrik Hübinette (Hubbe) }
cb119a1997-04-07Fredrik Hübinette (Hubbe) 
8392231998-01-08Fredrik Hübinette (Hubbe) #if constant(fork)
04c34c1998-01-01Fredrik Hübinette (Hubbe) constant fork = predef::fork; #endif
cb119a1997-04-07Fredrik Hübinette (Hubbe) 
04c34c1998-01-01Fredrik Hübinette (Hubbe) #if constant(exece) constant exece = predef::exece; #endif
df67f71997-12-14Mirar (Pontus Hagland) 
04c34c1998-01-01Fredrik Hübinette (Hubbe) #if constant(fork)
df67f71997-12-14Mirar (Pontus Hagland) class Spawn { object stdin; object stdout; object stderr; array(object) fd;
8392231998-01-08Fredrik Hübinette (Hubbe)  object pid;
df67f71997-12-14Mirar (Pontus Hagland) 
8392231998-01-08Fredrik Hübinette (Hubbe)  private object low_spawn(array(void|object(Stdio.File)) fdp, array(void|object(Stdio.File)) fd_to_close, string cmd, void|string *args, void|mapping(string:string) env, string|void cwd)
df67f71997-12-14Mirar (Pontus Hagland)  { object(Stdio.File) pie,pied; /* interprocess communication */
8392231998-01-08Fredrik Hübinette (Hubbe)  object pid;
df67f71997-12-14Mirar (Pontus Hagland)  pie=Stdio.File(); pied=pie->pipe(); if(!(pid=fork())) { mixed err=catch { if(cwd && !cd(cwd)) { throw(({"pike: cannot change cwd to "+cwd+ ": "+strerror(errno())+"\n", backtrace()})); } if (sizeof(fdp)>0 && fdp[0]) fdp[0]->dup2(Stdio.File("stdin")); if (sizeof(fdp)>1 && fdp[1]) fdp[1]->dup2(Stdio.File("stdout")); if (sizeof(fdp)>2 && fdp[2]) fdp[2]->dup2(Stdio.File("stderr")); /* dup2 fdd[3..] here FIXME FIXME */ foreach (fd_to_close,object f) if (objectp(f)) { f->close(); destruct(f); } pie->close(); destruct(pie); pied->set_close_on_exec(1); if (env) exece(cmd,args||({}),env); else exece(cmd,args||({})); throw(({"pike: failed to exece "+cmd+ ": "+strerror(errno())+"\n", backtrace()})); }; pied->write(encode_value(err)); exit(1); } foreach (fdp,object f) if (objectp(f)) { f->close(); destruct(f); } pied->close(); destruct(pied); mixed err=pie->read(); if (err && err!="") throw(decode_value(err)); pie->close(); destruct(pie); return pid; } void create(string cmd, void|array(string) args, void|mapping(string:string) env, string|void cwd, void|array(object(Stdio.File)|void) ownpipes, void|array(object(Stdio.File)|void) fds_to_close) { if (!ownpipes) { stdin=Stdio.File(); stdout=Stdio.File(); stderr=Stdio.File(); fd=({stdin->pipe(),stdout->pipe(),stderr->pipe()}); fds_to_close=({stdin,stdout,stderr}); } else { fd=ownpipes; if (sizeof(fd)>0) stdin=fd[0]; else stdin=0; if (sizeof(fd)>1) stdout=fd[1]; else stdout=0; if (sizeof(fd)>2) stderr=fd[2]; else stderr=0; } pid=low_spawn(fd,fds_to_close||({}),cmd,args,env,cwd); }
8392231998-01-08Fredrik Hübinette (Hubbe) #if constant(kill)
df67f71997-12-14Mirar (Pontus Hagland)  int kill(int signal) { return predef::kill(pid,signal); }
8392231998-01-08Fredrik Hübinette (Hubbe) #endif
df67f71997-12-14Mirar (Pontus Hagland) 
8392231998-01-08Fredrik Hübinette (Hubbe)  int wait()
df67f71997-12-14Mirar (Pontus Hagland)  {
8392231998-01-08Fredrik Hübinette (Hubbe)  return pid->wait();
df67f71997-12-14Mirar (Pontus Hagland)  } // void set_done_callback(function foo,mixed ... args); // int result(); // array rusage(); }
04c34c1998-01-01Fredrik Hübinette (Hubbe) #endif