summary refs log tree commit diff stats
path: root/lib/pure/osproc.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/osproc.nim')
-rw-r--r--lib/pure/osproc.nim174
1 files changed, 81 insertions, 93 deletions
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 353713a80..d24740a16 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -32,22 +32,22 @@ when defined(linux):
 
 type
   ProcessOption* = enum ## Options that can be passed to `startProcess proc
-    ## <#startProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
-    poEchoCmd,              ## Echo the command before execution.
-    poUsePath,              ## Asks system to search for executable using PATH environment
-                            ## variable.
-                            ## On Windows, this is the default.
-    poEvalCommand,          ## Pass `command` directly to the shell, without quoting.
-                            ## Use it only if `command` comes from trusted source.
-    poStdErrToStdOut,       ## Merge stdout and stderr to the stdout stream.
-    poParentStreams,        ## Use the parent's streams.
-    poInteractive,          ## Optimize the buffer handling for responsiveness for
-                            ## UI applications. Currently this only affects
-                            ## Windows: Named pipes are used so that you can peek
-                            ## at the process' output streams.
-    poDaemon                ## Windows: The program creates no Window.
-                            ## Unix: Start the program as a daemon. This is still
-                            ## work in progress!
+                        ## <#startProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
+    poEchoCmd,          ## Echo the command before execution.
+    poUsePath,          ## Asks system to search for executable using PATH environment
+                        ## variable.
+                        ## On Windows, this is the default.
+    poEvalCommand,      ## Pass `command` directly to the shell, without quoting.
+                        ## Use it only if `command` comes from trusted source.
+    poStdErrToStdOut,   ## Merge stdout and stderr to the stdout stream.
+    poParentStreams,    ## Use the parent's streams.
+    poInteractive,      ## Optimize the buffer handling for responsiveness for
+                        ## UI applications. Currently this only affects
+                        ## Windows: Named pipes are used so that you can peek
+                        ## at the process' output streams.
+    poDaemon            ## Windows: The program creates no Window.
+                        ## Unix: Start the program as a daemon. This is still
+                        ## work in progress!
 
   ProcessObj = object of RootObj
     when defined(windows):
@@ -66,21 +66,16 @@ type
   Process* = ref ProcessObj ## Represents an operating system process.
 
 const poDemon* {.deprecated.} = poDaemon ## Nim versions before 0.20
-  ## used the wrong spelling ("demon").
-  ## Now `ProcessOption` uses the correct spelling ("daemon"),
-  ## and this is needed just for backward compatibility.
-
-
-proc execProcess*(command: string,
-                  workingDir: string = "",
-                  args: openArray[string] = [],
-                  env: StringTableRef = nil,
-                  options: set[ProcessOption] = {poStdErrToStdOut,
-                                                  poUsePath,
-                                                  poEvalCommand}): TaintedString {.
-                                                  rtl, extern: "nosp$1",
-                                                  tags: [ExecIOEffect, ReadIOEffect,
-                                                  RootEffect].}
+                                         ## used the wrong spelling ("demon").
+                                         ## Now `ProcessOption` uses the correct spelling ("daemon"),
+                                         ## and this is needed just for backward compatibility.
+
+
+proc execProcess*(command: string, workingDir: string = "",
+    args: openArray[string] = [], env: StringTableRef = nil,
+    options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
+  TaintedString {.rtl, extern: "nosp$1",
+                  tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
   ## A convenience procedure that executes ``command`` with ``startProcess``
   ## and returns its output as a string.
   ##
@@ -102,8 +97,8 @@ proc execProcess*(command: string,
   ##  # Note: outp may have an interleave of text from the nim compile
   ##  # and any output from mytestfile when it runs
 
-proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [ExecIOEffect,
-  ReadIOEffect, RootEffect].}
+proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
+    tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
   ## Executes ``command`` and returns its error code.
   ##
   ## Standard input, output, error streams are inherited from the calling process.
@@ -121,13 +116,11 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [ExecIOEffect
   ## .. code-block:: Nim
   ##  let errC = execCmd("nim c -r mytestfile.nim")
 
-proc startProcess*(command: string,
-                   workingDir: string = "",
-                   args: openArray[string] = [],
-                   env: StringTableRef = nil,
-                   options: set[ProcessOption] = {poStdErrToStdOut}):
-              owned(Process) {.rtl, extern: "nosp$1", tags: [ExecIOEffect, ReadEnvEffect,
-              RootEffect].}
+proc startProcess*(command: string, workingDir: string = "",
+    args: openArray[string] = [], env: StringTableRef = nil,
+    options: set[ProcessOption] = {poStdErrToStdOut}):
+  owned(Process) {.rtl, extern: "nosp$1",
+                   tags: [ExecIOEffect, ReadEnvEffect, RootEffect].}
   ## Starts a process. `Command` is the executable file, `workingDir` is the
   ## process's working directory. If ``workingDir == ""`` the current directory
   ## is used (default). `args` are the command line arguments that are passed to the
@@ -216,7 +209,7 @@ proc processID*(p: Process): int {.rtl, extern: "nosp$1".} =
   return p.id
 
 proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
-  extern: "nosp$1", tags: [].}
+    extern: "nosp$1", tags: [].}
   ## Waits for the process to finish and returns `p`'s error code.
   ##
   ## **WARNING**: Be careful when using `waitForExit` for processes created without
@@ -274,7 +267,7 @@ proc inputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
   result = p.inHandle
 
 proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
-  tags: [].} =
+    tags: [].} =
   ## Returns ``p``'s output file handle for reading from.
   ##
   ## **WARNING**: The returned `FileHandle` should not be closed manually as
@@ -286,7 +279,7 @@ proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
   result = p.outHandle
 
 proc errorHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
-  tags: [].} =
+    tags: [].} =
   ## Returns ``p``'s error file handle for reading from.
   ##
   ## **WARNING**: The returned `FileHandle` should not be closed manually as
@@ -303,12 +296,11 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
   result = cpuinfo.countProcessors()
 
 proc execProcesses*(cmds: openArray[string],
-                    options = {poStdErrToStdOut, poParentStreams},
-                    n = countProcessors(),
-                    beforeRunEvent: proc(idx: int) = nil,
-                    afterRunEvent: proc(idx: int, p: Process) = nil): int
-                    {.rtl, extern: "nosp$1",
-                    tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
+    options = {poStdErrToStdOut, poParentStreams}, n = countProcessors(),
+    beforeRunEvent: proc(idx: int) = nil,
+    afterRunEvent: proc(idx: int, p: Process) = nil):
+  int {.rtl, extern: "nosp$1",
+        tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
   ## Executes the commands `cmds` in parallel.
   ## Creates `n` processes that execute in parallel.
   ##
@@ -413,20 +405,20 @@ proc execProcesses*(cmds: openArray[string],
     for i in 0..high(cmds):
       if beforeRunEvent != nil:
         beforeRunEvent(i)
-      var p = startProcess(cmds[i], options=options + {poEvalCommand})
+      var p = startProcess(cmds[i], options = options + {poEvalCommand})
       result = max(abs(waitForExit(p)), result)
       if afterRunEvent != nil: afterRunEvent(i, p)
       close(p)
 
 when not defined(useNimRtl):
-  proc execProcess(command: string,
-                   workingDir: string = "",
-                   args: openArray[string] = [],
-                   env: StringTableRef = nil,
-                   options: set[ProcessOption] = {poStdErrToStdOut,
-                                                   poUsePath,
-                                                   poEvalCommand}): TaintedString =
-    var p = startProcess(command, workingDir=workingDir, args=args, env=env, options=options)
+  proc execProcess(command: string, workingDir: string = "",
+      args: openArray[string] = [], env: StringTableRef = nil,
+      options: set[ProcessOption] = {poStdErrToStdOut, poUsePath,
+          poEvalCommand}):
+    TaintedString =
+
+    var p = startProcess(command, workingDir = workingDir, args = args,
+        env = env, options = options)
     var outp = outputStream(p)
     result = TaintedString""
     var line = newStringOfCap(120).TaintedString
@@ -501,16 +493,14 @@ when defined(Windows) and not defined(useNimRtl):
   #var
   #  O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
   #  O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
-  proc myDup(h: Handle; inherit: WINBOOL=1): Handle =
+  proc myDup(h: Handle; inherit: WINBOOL = 1): Handle =
     let thisProc = getCurrentProcess()
-    if duplicateHandle(thisProc, h,
-                       thisProc, addr result,0,inherit,
+    if duplicateHandle(thisProc, h, thisProc, addr result, 0, inherit,
                        DUPLICATE_SAME_ACCESS) == 0:
       raiseOSError(osLastError())
 
   proc createAllPipeHandles(si: var STARTUPINFO;
-                            stdin, stdout, stderr: var Handle;
-                            hash: int) =
+                            stdin, stdout, stderr: var Handle; hash: int) =
     var sa: SECURITY_ATTRIBUTES
     sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
     sa.lpSecurityDescriptor = nil
@@ -518,37 +508,37 @@ when defined(Windows) and not defined(useNimRtl):
     let pipeOutName = newWideCString(r"\\.\pipe\stdout" & $hash)
     let pipeInName = newWideCString(r"\\.\pipe\stdin" & $hash)
     let pipeOut = createNamedPipe(pipeOutName,
-      dwOpenMode=PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
-      dwPipeMode=PIPE_NOWAIT,
-      nMaxInstances=1,
-      nOutBufferSize=1024, nInBufferSize=1024,
-      nDefaultTimeOut=0,addr sa)
+      dwOpenMode = PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
+      dwPipeMode = PIPE_NOWAIT,
+      nMaxInstances = 1,
+      nOutBufferSize = 1024, nInBufferSize = 1024,
+      nDefaultTimeOut = 0, addr sa)
     if pipeOut == INVALID_HANDLE_VALUE:
       raiseOSError(osLastError())
     let pipeIn = createNamedPipe(pipeInName,
-      dwOpenMode=PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
-      dwPipeMode=PIPE_NOWAIT,
-      nMaxInstances=1,
-      nOutBufferSize=1024, nInBufferSize=1024,
-      nDefaultTimeOut=0,addr sa)
+      dwOpenMode = PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
+      dwPipeMode = PIPE_NOWAIT,
+      nMaxInstances = 1,
+      nOutBufferSize = 1024, nInBufferSize = 1024,
+      nDefaultTimeOut = 0, addr sa)
     if pipeIn == INVALID_HANDLE_VALUE:
       raiseOSError(osLastError())
 
     si.hStdOutput = createFileW(pipeOutName,
         FILE_WRITE_DATA or SYNCHRONIZE, 0, addr sa,
         OPEN_EXISTING, # very important flag!
-        FILE_ATTRIBUTE_NORMAL,
-        0 # no template file for OPEN_EXISTING
-      )
+      FILE_ATTRIBUTE_NORMAL,
+      0 # no template file for OPEN_EXISTING
+    )
     if si.hStdOutput == INVALID_HANDLE_VALUE:
       raiseOSError(osLastError())
     si.hStdError = myDup(si.hStdOutput)
     si.hStdInput = createFileW(pipeInName,
         FILE_READ_DATA or SYNCHRONIZE, 0, addr sa,
         OPEN_EXISTING, # very important flag!
-        FILE_ATTRIBUTE_NORMAL,
-        0 # no template file for OPEN_EXISTING
-      )
+      FILE_ATTRIBUTE_NORMAL,
+      0 # no template file for OPEN_EXISTING
+    )
     if si.hStdOutput == INVALID_HANDLE_VALUE:
       raiseOSError(osLastError())
 
@@ -569,11 +559,10 @@ when defined(Windows) and not defined(useNimRtl):
   proc fileClose(h: Handle) {.inline.} =
     if h > 4: discard closeHandle(h)
 
-  proc startProcess(command: string,
-                 workingDir: string = "",
-                 args: openArray[string] = [],
-                 env: StringTableRef = nil,
-                 options: set[ProcessOption] = {poStdErrToStdOut}): owned Process =
+  proc startProcess(command: string, workingDir: string = "",
+      args: openArray[string] = [], env: StringTableRef = nil,
+      options: set[ProcessOption] = {poStdErrToStdOut}):
+    owned Process =
     var
       si: STARTUPINFO
       procInfo: PROCESS_INFORMATION
@@ -789,7 +778,7 @@ when defined(Windows) and not defined(useNimRtl):
 
   proc hasData*(p: Process): bool =
     var x: int32
-    if peekNamedPipe(p.outHandle, lpTotalBytesAvail=addr x):
+    if peekNamedPipe(p.outHandle, lpTotalBytesAvail = addr x):
       result = x > 0
 
 elif not defined(useNimRtl):
@@ -842,11 +831,10 @@ elif not defined(useNimRtl):
     tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
   {.pop.}
 
-  proc startProcess(command: string,
-                 workingDir: string = "",
-                 args: openArray[string] = [],
-                 env: StringTableRef = nil,
-                 options: set[ProcessOption] = {poStdErrToStdOut}): owned Process =
+  proc startProcess(command: string, workingDir: string = "",
+      args: openArray[string] = [], env: StringTableRef = nil,
+      options: set[ProcessOption] = {poStdErrToStdOut}):
+    owned Process =
     var
       pStdin, pStdout, pStderr: array[0..1, cint]
     new(result)
@@ -1013,7 +1001,7 @@ elif not defined(useNimRtl):
       if sizeRead == sizeof(error):
         raiseOSError(osLastError(),
                      "Could not find command: '$1'. OS error: $2" %
-                     [$data.sysCommand, $strerror(error)])
+                      [$data.sysCommand, $strerror(error)])
 
       return pid
 
@@ -1066,7 +1054,7 @@ elif not defined(useNimRtl):
       discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
 
     startProcessFail(data)
-  {.pop}
+  {.pop.}
 
   proc close(p: Process) =
     if poParentStreams notin p.options:
@@ -1401,7 +1389,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
   ## .. code-block:: Nim
   ##  let (outp, errC) = execCmdEx("nim c -r mytestfile.nim")
 
-  var p = startProcess(command, options=options + {poEvalCommand})
+  var p = startProcess(command, options = options + {poEvalCommand})
   var outp = outputStream(p)
 
   # There is no way to provide input for the child process