pike.git / lib / modules / Process.pmod

version» Context lines:

pike.git/lib/modules/Process.pmod:1:   #pike __REAL_VERSION__      constant create_process = __builtin.create_process;      #if constant(__builtin.TraceProcess)   constant TraceProcess = __builtin.TraceProcess;   #endif    + #if defined(__NT__) || defined(__amigaos__) || defined(__OS2__) + constant path_separator = ";"; + #else + constant path_separator = ":"; + #endif +    #if constant(Stdio.__HAVE_SEND_FD__)   protected Stdio.File forkd_pipe;   protected create_process forkd_pid;      //! Encoder for data to be sent to @[Tools.Standalone.forkd].   //!   //! @seealso   //! @[ForkdDecoder]   class ForkdEncoder(Stdio.File remote_fd)   {
pike.git/lib/modules/Process.pmod:407:   // FIXME: Should probably be located elsewhere.   string locate_binary(array(string) path, string name)   {   #ifdef __NT__    if( !has_suffix(lower_case(name), ".exe") )    name += ".exe";   #endif       foreach(path, string dir)    { - #ifdef __NT__ -  // Windows doesn't seem to strip quotation marks from PATH -  // components that contain them so we need to do that here, -  // otherwise we'll end up with a bogus path to stat on. -  if(sizeof(dir) && dir[0] == '"' && dir[-1] == '"') -  dir = dir[1..<1]; - #endif /* __NT__ */ -  +     string fname = combine_path(dir, name);    Stdio.Stat info = file_stat(fname);    if (info && (info->mode & 0111))    return fname;    }    return 0;   }      protected array(string) runpike;   
pike.git/lib/modules/Process.pmod:451:    array(string) res = ({    master()->_pike_file_name,    });    if (master()->_master_file_name)    res+=({"-m"+master()->_master_file_name});    foreach (master()->pike_module_path;;string path)    res+=({"-M" + path});    if(options && options->add_predefines)    {    foreach (master()->predefines; string key; string value) +  if( stringp( value ) )    res+=({"-D" + key + "=" + value}); -  +  else if( intp( value ) ) +  res+=({"-D" + key });    }    if(options && options->add_program_path)    {    foreach (master()->pike_program_path;; string value)    res+=({"-P" + value});    }    if(options && options->add_include_path)    {    foreach (master()->pike_include_path;; string value)    res+=({"-I" + value});    }       if (sizeof(res) && !has_value(res[0],"/")   #ifdef __NT__    && !has_value(res[0], "\\")   #endif /* __NT__ */    ) -  res[0] = locate_binary(getenv("PATH")/ - #if defined(__NT__) || defined(__amigaos__) -  ";" - #else -  ":" - #endif -  ,res[0]); +  res[0] = search_path(res[0]);    runpike = res;    }    return Process(runpike + argv, options);   }      //! Easy and lazy way of using @[Process.Process] that runs a process   //! and returns a mapping with the output and exit code without   //! having to make sure you read nonblocking yourself.   //!   //! @param args
pike.git/lib/modules/Process.pmod:640: Inside #if constant(exece)
   path=[string]getenv("PATH");       foreach(path ? path/":" : ({}) , path)    if(file_stat(path=combine_path(path,file)))    return exece(path, foo, [mapping(string:string)]getenv());    }    return 69;   }   #endif    + protected string search_path_raw;   protected array(string) search_path_entries=0;    -  + //! Search for the path to an executable.   //! -  + //! @param command + //! Executable to search for. + //! + //! Searches for @[command] in the directories listed in the + //! environment variable @tt{$PATH@}. + //! + //! @returns + //! Returns the path to @[command] if found, and + //! @expr{0@} (zero) on failure. + //! + //! @note + //! This function is NOT thread safe if the environment + //! variable @tt{$PATH@} is being changed concurrently. + //! + //! @note + //! In Pike 7.8.752 and earlier the environment + //! variable @tt{$PATH@} was only read once.   string search_path(string command)   {    if (command=="" || command[0]=='/') return command;    -  if (!search_path_entries) +  string path = getenv("PATH")||""; +  if ((path != search_path_raw) || !search_path_entries)    { -  +  string raw_path = path;   #ifdef __NT__ -  array(string) e=replace(getenv("PATH")||"", "\\", "/")/";"-({""}); - #elif defined(__amigaos__) -  array(string) e=(getenv("PATH")||"")/";"-({""}); - #else -  array(string) e=(getenv("PATH")||"")/":"-({""}); +  path = replace(path, "\\", "/");   #endif -  +  array(string) e = path/path_separator - ({""});       multiset(string) filter=(<>); -  search_path_entries=({}); +  array(string) entries=({});    foreach (e,string s)    {    string t;    if (s[0]=='~') // some shells allow ~-expansion in PATH    {    if (s[0..1]=="~/" && (t=System.get_home()))    s=t+s[1..];    else    {    // expand user?    } -  + #ifdef __NT__ +  } else if (sizeof(s) && (s[0] == '"') && s[-1] == '"') { +  // Windows doesn't seem to strip quotation marks from PATH +  // components that contain them so we need to do that here, +  // otherwise we'll end up with a bogus path to stat on. +  s = s[1..<1]; + #endif /* __NT__ */    }    if (!filter[s] /* && directory exist */ )    { -  search_path_entries+=({s}); +  entries += ({s});    filter[s]=1;    }    } -  +  // FIXME: This is NOT thread safe! +  search_path_entries = entries; +  search_path_raw = raw_path;    } -  foreach (search_path_entries, string path) -  { -  string p=combine_path(path,command); -  Stdio.Stat s=file_stat(p); -  if (s && s->mode&0111) return p; +  return locate_binary(search_path_entries, command);   } -  return 0; - } +       //!   string sh_quote(string s)   {    return replace(s,    ({"\\", "'", "\"", " "}),    ({"\\\\", "\\'", "\\\"","\\ "}));   }      array(string) split_quoted_string(string s, int(0..1)|void nt_mode)
pike.git/lib/modules/Process.pmod:906:   //! Open for reading. Data written by the process to stdout   //! is available for read.   //! @value "w"   //! Open for writing. Data written to the file is available   //! to the process on stdin.   //! @endstring   //!   //! @seealso   //! @[system], @[spawn]    - Stdio.FILE|string popen(string s, string|void mode) { -  if(mode) -  return fpopen(s,mode); -  else + variant string popen(string s) {    return fpopen(s)->read();   }    -  + variant Stdio.FILE popen(string s, string mode) { +  return fpopen(s,mode); + } +    protected Stdio.FILE fpopen(string s, string|void mode)   {    Stdio.FILE f = Stdio.FILE();    if (!f) error("Popen failed. (couldn't create file)\n");       Stdio.File p = f->pipe();    if(!p) error("Popen failed. (couldn't create pipe)\n");       if (mode == "w")    spawn(s, p, 0, 0, /*destruct, f*/);
pike.git/lib/modules/Process.pmod:1078: Inside #if undefined(__NT__) and #if constant(fork) && constant(exece)
   {    return pid->wait();    }       // void set_done_callback(function foo,mixed ... args);    // int result();    // array rusage();   }   #endif   #endif +  + #if constant(fork) || constant(System.daemon) + private int low_daemon(int nochdir, int noclose) + { + #if constant(System.daemon) +  return System.daemon(nochdir, noclose); + #else +  if (fork()) +  exit(0); +  + #if constant(System.setsid) +  System.setsid(); + #endif /* System.setsid */ +  +  if (!nochdir) +  cd("/"); +  +  Stdio.File fd; +  if (!noclose && (fd = Stdio.File("/dev/null", "rw"))) +  { +  fd->dup2(Stdio.stdin); +  fd->dup2(Stdio.stdout); +  fd->dup2(Stdio.stderr); +  if (fd->query_fd() > 2) +  fd->close(); +  } +  return 0; + #endif /* !System.daemon */ + } +  + void daemon(int nochdir, int noclose, +  void|mapping(string:string|Stdio.File) modifiers) + //! A function to run current program in the background. + //! + //! @param nochdir + //! If 0 the process will continue to run in / or the directory + //! dictadet by modifiers. + //! @param noclose + //! If this is not 0 the process will keep current file descriptors + //! open. + //! @param modifiers + //! Optional extra arguments. The parameters passed in this mapping + //! will override the arguments nochdir and noclose. + //! @mapping + //! @member string "cwd" + //! Change current working directory to this directory. + //! @member string|Stdio.File "stdin" + //! If this is a string this will be interpreted as a filename + //! pointing out a file to be used as stdandard input to the process. + //! If this is a Stdio.File object the process will use this as + //! standard input. + //! @member string|Stdio.File "stdout" + //! If this is a string this will be interpreted as a filename + //! pointing out a file to be used as stdandard output to the process. + //! If this is a Stdio.File object the process will use this as + //! standard output. + //! @member string|Stdio.File "stderr" + //! If this is a string this will be interpreted as a filename + //! pointing out a file to be used as stdandard error to the process. + //! If this is a Stdio.File object the process will use this as + //! standard error. + //! @endmapping + //! + //! @seealso + //! @[System.daemon] + //! + //! @note + //! This function only works on UNIX-like operating systems. + //! + //! @example + //! /* close all fd:s and cd to '/' */ + //! Process.daemon(0, 0); + //! + //! /* Do not change working directory. Write stdout to a file called + //! access.log and stderr to error.log. */ + //! Process.daemon(1, 0, ([ "stdout": "access.log", "stderr": "error.log" ]) ); + { +  array(Stdio.File) opened = ({}); +  Stdio.File getfd(string|object f) +  { +  if (stringp(f)) +  { +  Stdio.File ret = Stdio.File(f, "crw"); +  opened += ({ ret }); +  return ret; +  } +  else if (objectp(f)) +  return f; +  else +  return 0; +  }; +  +  if (low_daemon(nochdir, noclose) == -1) +  error("Failed to daemonize: " + strerror(errno())+"\n"); +  if (!modifiers) +  return; +  +  if (modifiers["cwd"]) +  cd(modifiers["cwd"]); +  +  if (modifiers["stdin"]) +  getfd(modifiers["stdin"])->dup2(Stdio.stdin); +  +  if (modifiers["stdout"]) +  getfd(modifiers["stdout"])->dup2(Stdio.stdout); +  +  if (modifiers["stderr"]) +  getfd(modifiers["stderr"])->dup2(Stdio.stderr); +  +  opened->close(); + } + #endif