www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - capturing std out

reply Charles <Charles_member pathlink.com> writes:
Is there any way to capture stdout from an exec/system call into the program ?

In perl I'd do this:

my  output = `ls`; 
print  output;

This above allows me to parse/manipulate the output of the ls command.

How would I do the equiv in D ? 
The following executes the ls command but doesn't give me the output inside the
program.
import std.process;
char * cmd = "/bin/ls"
system(cmd);

any hlp apprec,
Charles
Oct 31 2005
parent reply zwang <nehzgnaw gmail.com> writes:
Charles wrote:
 Is there any way to capture stdout from an exec/system call into the program ?
 
 In perl I'd do this:
 
 my  output = `ls`; 
 print  output;
 
 This above allows me to parse/manipulate the output of the ls command.
 
 How would I do the equiv in D ? 
 The following executes the ls command but doesn't give me the output inside the
 program.
 import std.process;
 char * cmd = "/bin/ls"
 system(cmd);
 
 any hlp apprec,
 Charles
 
 

As far as I know, you have to call platform-specific API to do this in D. In Windows, related functions include CreatePipe, SetHandleInformation, CreateProcess, PeekNamedPipe, WaitForSingleObject, ReadFile, and CloseHandle.
Oct 31 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
------------kG33W7szGlhYWpgXNZKo93
Content-Type: text/plain; format=flowed; delsp=yes; charset=iso-8859-15
Content-Transfer-Encoding: 8bit

On Mon, 31 Oct 2005 22:14:59 +0800, zwang <nehzgnaw gmail.com> wrote:
 Charles wrote:
 Is there any way to capture stdout from an exec/system call into the  
 program ?
  In perl I'd do this:
  my  output = `ls`; print  output;
  This above allows me to parse/manipulate the output of the ls command.
  How would I do the equiv in D ? The following executes the ls command  
 but doesn't give me the output inside the
 program.
 import std.process;
 char * cmd = "/bin/ls"
 system(cmd);
  any hlp apprec,
 Charles

As far as I know, you have to call platform-specific API to do this in D. In Windows, related functions include CreatePipe, SetHandleInformation, CreateProcess, PeekNamedPipe, WaitForSingleObject, ReadFile, and CloseHandle.

Yep. Here are some examples, they may even work ;) Regan ------------kG33W7szGlhYWpgXNZKo93 Content-Disposition: attachment; filename=process.d Content-Type: application/octet-stream; name=process.d Content-Transfer-Encoding: 8bit /* * Copyright (c) 2005 * Regan Heath * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Author makes no representations about * the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. */ module lib.process; private import std.c.stdlib; import lib.pipestream; extern(C) char* strdup(char*); version(Windows) { import std.c.windows.windows; import std.windows.syserror; extern(Windows) { struct PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } alias PROCESS_INFORMATION* PPROCESS_INFORMATION, LPPROCESS_INFORMATION; struct STARTUPINFOA { DWORD cb; LPSTR lpReserved; LPSTR lpDesktop; LPSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } alias STARTUPINFOA* LPSTARTUPINFOA; struct STARTUPINFOW { DWORD cb; LPWSTR lpReserved; LPWSTR lpDesktop; LPWSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } alias STARTUPINFOW* LPSTARTUPINFOW; VOID GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo); VOID GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo); uint STARTF_USESHOWWINDOW = 0x00000001; uint STARTF_USESIZE = 0x00000002; uint STARTF_USEPOSITION = 0x00000004; uint STARTF_USECOUNTCHARS = 0x00000008; uint STARTF_USEFILLATTRIBUTE = 0x00000010; uint STARTF_RUNFULLSCREEN = 0x00000020; uint STARTF_FORCEONFEEDBACK = 0x00000040; uint STARTF_FORCEOFFFEEDBACK = 0x00000080; uint STARTF_USESTDHANDLES = 0x00000100; /+#if(WINVER >= 0x0400) #define STARTF_USEHOTKEY 0x00000200 #endif /* WINVER >= 0x0400 */ +/ BOOL CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); BOOL CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); // // dwCreationFlag values // uint DEBUG_PROCESS = 0x00000001; uint DEBUG_ONLY_THIS_PROCESS = 0x00000002; uint CREATE_SUSPENDED = 0x00000004; uint DETACHED_PROCESS = 0x00000008; uint CREATE_NEW_CONSOLE = 0x00000010; uint NORMAL_PRIORITY_CLASS = 0x00000020; uint IDLE_PRIORITY_CLASS = 0x00000040; uint HIGH_PRIORITY_CLASS = 0x00000080; uint REALTIME_PRIORITY_CLASS = 0x00000100; uint CREATE_NEW_PROCESS_GROUP = 0x00000200; uint CREATE_UNICODE_ENVIRONMENT = 0x00000400; uint CREATE_SEPARATE_WOW_VDM = 0x00000800; uint CREATE_SHARED_WOW_VDM = 0x00001000; uint CREATE_FORCEDOS = 0x00002000; uint CREATE_DEFAULT_ERROR_MODE = 0x04000000; uint CREATE_NO_WINDOW = 0x08000000; uint PROFILE_USER = 0x10000000; uint PROFILE_KERNEL = 0x20000000; uint PROFILE_SERVER = 0x40000000; BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode); } } version(linux) { extern (C) char* strerror(int); } class ProcessException : Exception { version(Windows) { this(char[] msg) { super(msg ~ ": " ~ sysErrorString(GetLastError())); } } version(linux) { //for some reason getErrno does not link for me? this(char[] msg) { super(msg ~ ": " ~ std.string.toString(strerror(getErrno()))); } } } class Process { this() { } this(char[] command) { this(); execute(command); } void execute(char[] command) { if (running) kill(); startProcess(command); } void kill() { if (!running) return; stopProcess(0); } void addEnv(char[] label, char[] value) { addEnv(label~"="~value); } void addEnv(char[] value) { enviroment ~= value; } private: char[][] enviroment = null; bool running = false; PipeStream pout = null; PipeStream perr = null; PipeStream pin = null; char[] readLine() { return pout.readLine(); } char[] readError() { return perr.readLine(); } void writeLine(char[] line) { pin.writeLine(line); } version(Windows) { PROCESS_INFORMATION *info = null; char* makeBlock(char[][] from) { char* result = null; uint length = 0; uint upto = 0; foreach(char[] s; from) length += s.length; //total length of strings length += from.length; //add space for a \0 for each string length++; //add space for final terminating \0 result = cast(char*)calloc(0,length); foreach(char[] s; from) { result[upto..upto+s.length] = s[0..s.length]; upto += s.length+1; } return result; } void freeBlock(char* data) { free(data); } void startProcess(char[] command) { STARTUPINFOA startup; char* env = null; try { pout = new PipeStream(); perr = new PipeStream(); pin = new PipeStream(); GetStartupInfoA(&startup); startup.hStdInput = pin.readHandle; startup.hStdOutput = pout.writeHandle; startup.hStdError = perr.writeHandle; startup.dwFlags = STARTF_USESTDHANDLES; info = new PROCESS_INFORMATION(); env = makeBlock(enviroment); if (!CreateProcessA(null,std.string.toStringz(command),null,null,true,DETACHED_PROCESS,env,null,&startup,info)) throw new ProcessException("CreateProcess"); running = true; } finally { if (env) freeBlock(env); if (running) { CloseHandle(info.hThread); pin.closeRead(); pout.closeWrite(); perr.closeWrite(); } else { if (info) info = null; pout = null; perr = null; pin = null; } } } void stopProcess(uint exitCode) { if (!TerminateProcess(info.hProcess,exitCode)) throw new ProcessException("TerminateProcess"); running = false; CloseHandle(info.hProcess); info = null; pout = null; perr = null; pin = null; } } version(linux) { int pid; char** makeBlock(char[][] from) { char** result = null; result = cast(char**)calloc(0,(enviroment.length+1) * typeid(char*).sizeof); foreach(uint i, char[] s; from) result[i] = strdup(toStringz(s)); return result; } void freeBlock(char** block) { for(uint i = 0; block[i]; i++) free(block[i]); free(block); } char[][] splitArgs(char[] string, char[] delims) { char[] delims = " \t\r\n"; char[][] results = null; bool isquot = false; int start = -1; for(int i = 0; i < string.length; i++) { if (string[i] == '\"') isquot = !isquot; if (isquot) continue; if (delims.find(string[i]) != -1) { if (start == -1) continue; results ~= string[start..i]; start = -1; continue; } if (start == -1) start = i; } return results; } void startProcess(char[] command) { try { pin = new PipeStream(); pout = new PipeStream(); perr = new PipeStream(); if (fcntl(pin.writeHandle, F_SETFD, 1) == -1) throw new ProcessException("fcntl(pin.writeHandle)"); if (fcntl(pout.readHandle, F_SETFD, 1) == -1) throw new ProcessException("fcntl(pout.readHandle)"); if (fcntl(perr.readHandle, F_SETFD, 1) == -1) throw new ProcessException("fcntl(perr.readHandle)"); if (fcntl(fileno(stdin), F_SETFD, 1) == -1) throw new ProcessException("fcntl(stdin)"); if (fcntl(fileno(stdout), F_SETFD, 1) == -1) throw new ProcessException("fcntl(stdout)"); if (fcntl(fileno(stderr), F_SETFD, 1) == -1) throw new ProcessException("fcntl(stderr)"); pid = fork(); if (pid == 0) { /* child */ //not sure if we can even throw here? if (dup2(pout.writeHandle,STDOUT_FILENO) == -1) {} //throw new ProcessException("dup2(xwrite[1])"); if (dup2(perr.writeHandle,STDERR_FILENO) == -1) {} //throw new ProcessException("dup2(xread[0])"); if (dup2(pin.readHandle,STDIN_FILENO) == -1) {} //throw new ProcessException("dup2(xread[0])"); pout.closeWrite(); perr.closeWrite(); pin.closeRead(); /* set child uid/gid here */ //if (setuid(uid) == -1) throw new ProcessException("setuid"); //if (setgid(gid) == -1) throw new ProcessException("setgid"); execve(args[0],makeBlock(splitArgs(command)),makeBlock(enviroment)); //this does not return on success //can we throw? how to notify parent of failure? exit(1); } /* parent */ running = true; } finally { if (running) { pout.closeWrite(); perr.closeWrite(); pin.closeRead(); } else { pin = null; pout = null; perr = null; } } } void stopProcess(uint dummy) { int r; if (pid == 0) return; if (kill(pid, SIGTERM) == -1) throw new ProcessException("kill"); for(uint i = 0; i < 100; i++) { r = waitpid(pid,null,WNOHANG|WUNTRACED); if (r == -1) throw new ProcessException("waitpid"); if (r == pid) break; usleep(50000); } running = false; close(output); close(input); pid = 0; } } } /+ void main() { auto Process p = new Process("cmd /c dir"); printf("%.*s",p.readLine()); } +/ ------------kG33W7szGlhYWpgXNZKo93 Content-Disposition: attachment; filename=pipestream.d Content-Type: application/octet-stream; name=pipestream.d Content-Transfer-Encoding: 8bit /* * Copyright (c) 2005 * Regan Heath * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Author makes no representations about * the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. */ module lib.pipestream; import std.stream; extern(C) char* strdup(char*); version(Windows) { import std.c.windows.windows; import std.windows.syserror; extern(Windows) { alias HANDLE* PHANDLE; BOOL CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize ); BOOL PeekNamedPipe( HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage ); } } version(linux) { private import std.c.stdlib; extern (C) char* strerror(int); } version(Windows) { class PipeException : Exception { this(char[] msg) { super(msg ~ ": " ~ sysErrorString(GetLastError())); } } class PipeStream : Stream { this(uint bufferSize = 0) { SECURITY_ATTRIBUTES security; security.nLength = security.sizeof; security.lpSecurityDescriptor = null; security.bInheritHandle = true; if (!CreatePipe(&read,&write,&security,bufferSize)) throw new PipeException("CreatePipe"); writeable = true; readable = true; seekable = false; isopen = true; } HANDLE readHandle() { return read; } HANDLE writeHandle() { return write; } void closeRead() { CloseHandle(readHandle); read = INVALID_HANDLE_VALUE; readable = false; if (!writeable) isopen = false; } void closeWrite() { CloseHandle(writeHandle); write = INVALID_HANDLE_VALUE; writeable = false; if (!readable) isopen = false; } override void close() { closeRead(); closeWrite(); } override ulong seek(long offset, SeekPos whence) { assertSeekable(); } override size_t readBlock(void* buffer, size_t size) { size_t bytes = 0; assertReadable(); if (!ReadFile(readHandle,buffer,size,&bytes,null)) throw new PipeException("ReadFile"); return bytes; } override size_t available() { size_t bytes = 0; assertReadable(); if (!PeekNamedPipe(readHandle,null,0,null,&bytes,null)) throw new PipeException("PeekNamedPipe"); return bytes; } override size_t writeBlock(void* buffer, size_t size) { size_t bytes = 0; assertWriteable(); if (!WriteFile(writeHandle,buffer,size,&bytes,null)) throw new PipeException("WriteFile"); return bytes; } override void flush() { assertWriteable(); FlushFileBuffers(writeHandle); } private: HANDLE write = INVALID_HANDLE_VALUE; HANDLE read = INVALID_HANDLE_VALUE; } } version(linux) { class PipeException : Exception { //for some reason getErrno does not link for me? this(char[] msg) { super(msg ~ ": " ~ std.string.toString(strerror(getErrno()))); } } class PipeStream : Stream { this(uint dummy = 0) { if (pipe(handle) == -1) throw new PipeException("pipe(handle)"); writeable = true; readable = true; seekable = false; isopen = true; } int readHandle() { return handle[0]; } int writeHandle() { return handle[1]; } void closeRead() { close(readHandle); readable = false; if (!writeable) isopen = false; } void closeWrite() { close(writeHandle); writeable = false; if (!readable) isopen = false; } override void close() { closeRead(); closeWrite(); } override ulong seek(long offset, SeekPos whence) { assertSeekable(); } override size_t readBlock(void* buffer, size_t size) { size_t bytes; assertReadable(); bytes = read(readHandle,buffer,size); if (bytes == -1) throw new PipeException("read(handle[0])"); return bytes; } override size_t available() { size_t bytes; assertReadable(); if (ioctl(readHandle,FIONREAD,&bytes) == -1) throw new PipeException("ioctl(handle[0])"); return bytes; } override size_t writeBlock(void* buffer, size_t size) { size_t bytes; assertWriteable(); bytes = write(writeHandle,buffer,size); if (bytes == -1) throw new PipeException("write(handle[1])"); return bytes; } override void flush() { assertWriteable(); //writeHandle } private: int handle[2]; } } /+ class Process : Stream { alias std.stdio.writefln debugf; this() { super(); seekable = false; readable = true; writeable = true; isopen = false; } this(char[] command) { this(); open(command); } ~this() { close(); } void addEnv(char[] label, char[] value) { addEnv(label~"="~value); } void addEnv(char[] value) { enviroment ~= value; } void open(char[] command) { if (isopen) close(); startProcess(command); } override void close() { if (!isopen) return ; flush(); stopProcess(0); isopen = false; } override ulong seek(long offset, SeekPos whence) { assertSeekable(); } version(Windows) { override size_t readBlock(void* buffer, size_t size) { size_t bytes = 0; if (!isopen) return 0; if (!ReadFile(output,buffer,size,&bytes,null)) throw new ProcessException("ReadFile"); return bytes; } override size_t writeBlock(void* buffer, size_t size) { size_t bytes = 0; if (!isopen) return 0; if (!WriteFile(input,buffer,size,&bytes,null)) throw new ProcessException("WriteFile"); return bytes; } override size_t available() { size_t bytes = 0; if (!isopen) return 0; if (!PeekNamedPipe(output,null,0,null,&bytes,null)) throw new ProcessException("PeekNamedPipe"); return bytes; } override void flush() { if (!isopen) return ; FlushFileBuffers(output); } } version(linux) { override size_t readBlock(void* buffer, size_t size) { size_t bytes; bytes = read(output,buffer,size); if (bytes == -1) throw new ProcessException("read"); return bytes; } override size_t writeBlock(void* buffer, size_t size) { size_t bytes; bytes = write(output,buffer,size); if (bytes == -1) throw new ProcessException("write"); return bytes; } override size_t available() { size_t bytes; if (ioctl(output,FIONREAD,&bytes) == -1) throw new ProcessException("ioctl"); return bytes; } } private: char[][] enviroment = null; version(Windows) { HANDLE output = INVALID_HANDLE_VALUE; HANDLE input = INVALID_HANDLE_VALUE; PROCESS_INFORMATION* info = null; int bufferSize = 0; char* makeBlock(char[][] from) { char* result = null; uint length = 0; uint upto = 0; foreach(char[] s; from) length += s.length; //total length of strings length += from.length; //add space for a \0 for each string length++; //add space for final terminating \0 result = cast(char*)calloc(0,length); foreach(char[] s; from) { result[upto..upto+s.length] = s[0..s.length]; upto += s.length+1; } return result; } void freeBlock(char* data) { free(data); } void startProcess(char[] command) { HANDLE read1,read2,read3,write1,write2,write3; SECURITY_ATTRIBUTES security; STARTUPINFOA startup; char* env; read1 = read2 = read3 = write1 = write2 = write2 = INVALID_HANDLE_VALUE; security.nLength = security.sizeof; security.lpSecurityDescriptor = null; security.bInheritHandle = true; env = null; try { if (!CreatePipe(&read1,&write1,&security,bufferSize)) throw new ProcessException("CreatePipe"); if (!CreatePipe(&read2,&write2,&security,bufferSize)) throw new ProcessException("CreatePipe"); if (!CreatePipe(&read3,&write3,&security,bufferSize)) throw new ProcessException("CreatePipe"); GetStartupInfoA(&startup); startup.hStdInput = read1; startup.hStdOutput = write2; startup.hStdError = write3; startup.dwFlags = STARTF_USESTDHANDLES; info = new PROCESS_INFORMATION(); env = makeBlock(enviroment); if (!CreateProcessA(null,toStringz(command),null,null,true,DETACHED_PROCESS,env,null,&startup,info)) throw new ProcessException("CreateProcess"); input = write1; output = read2; isopen = true; } finally { if (!isopen && read2 != INVALID_HANDLE_VALUE) CloseHandle(read2); if (!isopen && write1 != INVALID_HANDLE_VALUE) CloseHandle(write1); if (read1 != INVALID_HANDLE_VALUE) CloseHandle(read1); if (read3 != INVALID_HANDLE_VALUE) CloseHandle(read3); if (write2 != INVALID_HANDLE_VALUE) CloseHandle(write2); if (write3 != INVALID_HANDLE_VALUE) CloseHandle(write3); if (info) CloseHandle(info.hThread); if (env) freeBlock(env); } } void stopProcess(uint exitCode) { if (!TerminateProcess(info.hProcess,exitCode)) throw new ProcessException("TerminateProcess"); isopen = false; CloseHandle(info.hProcess); delete info; info = null; CloseHandle(output); output = INVALID_HANDLE_VALUE; CloseHandle(input); input = INVALID_HANDLE_VALUE; } } version(linux) { int output = 0; int input = 0; int pid = 0; char** makeBlock(char[][] from) { char** result = null; result = cast(char**)calloc(0,(enviroment.length+1) * typeid(char*).sizeof); foreach(uint i, char[] s; from) result[i] = strdup(toStringz(s)); return result; } void freeBlock(char** block) { for(uint i = 0; block[i]; i++) free(block[i]); free(block); } char[][] splitArgs(char[] string, char[] delims) { char[] delims = " \t\r\n"; char[][] results = null; bool isquot = false; int start = -1; for(int i = 0; i < string.length; i++) { if (string[i] == '\"') isquot = !isquot; if (isquot) continue; if (delims.find(string[i]) != -1) { if (start == -1) continue; results ~= string[start..i]; start = -1; continue; } if (start == -1) start = i; } return results; } void startProcess(char[] command) { int xwrite[2]; int xread[2]; try { if (pipe(xwrite) == -1) throw new ProcessException("pipe(xwrite)"); if (pipe(xread) == -1) throw new ProcessException("pipe(xread)"); if (fcntl(input, F_SETFD, 1) == -1) throw new ProcessException("fcntl(input)"); if (fcntl(output, F_SETFD, 1) == -1) throw new ProcessException("fcntl(output)"); if (fcntl(fileno(stdin), F_SETFD, 1) == -1) throw new ProcessException("fcntl(stdin)"); if (fcntl(fileno(stdout), F_SETFD, 1) == -1) throw new ProcessException("fcntl(stdout)"); if (fcntl(fileno(stderr), F_SETFD, 1) == -1) throw new ProcessException("fcntl(stderr)"); pid = fork(); if (pid == 0) { /* child */ char** args = null; char** env = null; //not sure if we can even throw here? if (dup2(xwrite[1],STDOUT_FILENO) == -1) {} //throw new ProcessException("dup2(xwrite[1])"); if (dup2(xread[0], STDIN_FILENO) == -1) {} //throw new ProcessException("dup2(xread[0])"); close(xwrite[1]); close(xread[0]); /* set child uid/gid here */ //if (setuid(uid) == -1) throw new ProcessException("setuid"); //if (setgid(gid) == -1) throw new ProcessException("setgid"); args = makeBlock(splitArgs(command)); env = makeBlock(enviroment); execve(args[0],args,env); //this does not return on success //can we throw? how to notify parent of failure? exit(1); } /* parent */ isopen = true; } finally { close(xwrite[1]); close(xread[0]); } } void stopProcess(uint dummy) { int r; if (pid == 0) return; if (kill(pid, SIGTERM) == -1) throw new ProcessException("kill"); for(uint i = 0; i < 100; i++) { r = waitpid(pid,null,WNOHANG|WUNTRACED); if (r == -1) throw new ProcessException("waitpid"); if (r == pid) break; usleep(50000); } isopen = false; close(output); close(input); pid = 0; } } } +/ ------------kG33W7szGlhYWpgXNZKo93--
Oct 31 2005
parent Georg Wrede <georg.wrede nospam.org> writes:
Regan Heath wrote:
 On Mon, 31 Oct 2005 22:14:59 +0800, zwang <nehzgnaw gmail.com> wrote:
 
 Charles wrote:

 Is there any way to capture stdout from an exec/system call into the  
 program ?
  In perl I'd do this:
  my  output = `ls`; print  output;
  This above allows me to parse/manipulate the output of the ls command.
  How would I do the equiv in D ? The following executes the ls 
 command  but doesn't give me the output inside the
 program.
 import std.process;
 char * cmd = "/bin/ls"
 system(cmd);
  any hlp apprec,
 Charles



For debugging or quick-and-dirty purposes one might also do something like this: system("ls -l /root /home >/tmp/lsout 2>/tmp/lserr "); Whereafter you can the read the files into your program. This has the advantage of separating error and standard output from each other. For example, on my machine the files end up containing: lsout: /home: total 4 drwxr-xr-x 24 georg georg 4096 Nov 1 00:34 georg and lserr: ls: /root: Permission denied
 As far as I know, you have to call platform-specific API to do this 
 in  D. In Windows, related functions include CreatePipe,  
 SetHandleInformation, CreateProcess, PeekNamedPipe, 
 WaitForSingleObject,  ReadFile, and CloseHandle.

Yep. Here are some examples, they may even work ;)

Cool!
Oct 31 2005