Help with pipe io
- Posted by jbrown1050 at yahoo.com Mar 28, 2002
- 349 views
--fdj2RfSjLxBAspz7 I'm working on pipes for linux which are full duplex. However, there is a bug, as shown in demo1.exu - uncomment out the line which opens "/bin/echo", and you'll see that echo outputs a bunch of garbage instead of "Hello World!" Can anyone please explain why this happens and how to fix it? Thanks in advance. -- "Is there peace in heaven, or is that merely an illusion?" - Someone "May peace find its way through the heavens to the world of men and women before the fires of the damned consume them." - Someone Linux User:190064 Linux Machine:84163 --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="cpipe.e" include dll.e include machine.e constant STDLIB = open_dll("") constant PIPE = define_c_func(STDLIB, "pipe", {C_POINTER}, C_INT) constant READ = define_c_func(STDLIB, "read", {C_INT, C_POINTER, C_INT}, C_INT) constant WRITE = define_c_func(STDLIB, "write", {C_INT, C_POINTER, C_INT}, C_INT) constant CLOSE = define_c_func(STDLIB, "close", {C_INT}, C_INT) constant DUP2 = define_c_func(STDLIB, "dup2", {C_INT, C_INT}, C_INT) constant KILL = define_c_func(STDLIB, "kill", {C_INT, C_INT}, C_INT) constant FORK = define_c_func(STDLIB, "fork", {}, C_INT) constant EXECV = define_c_func(STDLIB, "execv", {C_POINTER, C_POINTER}, C_INT) constant SIGNAL = define_c_func(STDLIB, "signal", {C_INT, C_POINTER}, C_POINTER) constant ERRNO = define_c_var(STDLIB, "errno") global constant os_stdin = 0 global constant os_stdout = 1 global constant os_stderr = 2 global constant os_sig_dfl = 0 global constant os_sig_ign = 1 global atom os_errno os_errno = 0 global object VOID VOID = {} global function os_pipe() atom cmd, r, in, out cmd = allocate(8) r = c_func(PIPE,{cmd}) if r = -1 then os_errno = peek4u(ERRNO) return -1 end if in = peek4u(cmd) out = peek4u(cmd+4) free(cmd) return {in, out} end function global function os_read(atom fd, integer bytes) atom buf, r sequence data buf = allocate(bytes) r = c_func(READ, {fd, buf, bytes}) if r = -1 then os_errno = peek4u(ERRNO) return -1 end if if r = 0 then free(buf) return "" end if data = "" for i = 1 to r do data &= peek(buf+i-1) end for return data end function global function os_write(atom fd, sequence str) atom buf, r buf = allocate_string(str) r = c_func(WRITE, {fd, buf, length(str)}) if r = -1 then os_errno = peek4u(ERRNO) return -1 end if return r end function global function os_close(atom fd) atom r r = c_func(CLOSE, {fd}) if r = -1 then os_errno = peek4u(ERRNO) return -1 end if return 0 end function global function os_dup2(atom oldfd, atom newfd) atom r r = c_func(DUP2, {oldfd, newfd}) if r = -1 then os_errno = peek4u(ERRNO) return -1 end if return r end function global function os_kill(atom pid, atom signal) atom r r = c_func(KILL, {pid, signal}) if r = -1 then os_errno = peek4u(ERRNO) return -1 end if return r end function global function os_fork() atom pid pid = c_func(FORK, {}) if pid = -1 then os_errno = peek4u(ERRNO) return -1 end if return pid end function global function os_execv(sequence s, sequence v) atom sbuf atom vbuf atom vbufstr atom r sbuf = allocate_string(s) vbuf = allocate((length(v)+1)*4) for i = 1 to length(v) do vbufstr = allocate_string(v[i]) poke4(vbuf+((i-1)*4), vbufstr) end for poke4(vbuf+((length(v)+1)*4), 0) r = c_func(EXECV, {sbuf, vbuf}) -- execv() should never return os_errno = peek4u(ERRNO) return r end function global function os_signal(integer signal, atom handler) return c_func(SIGNAL, {signal, handler}) end function --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pipeio.e" include cpipe.e procedure error() crash_message(sprintf("Errno = %d", os_errno)) ? 1/0 end procedure global function popen(sequence command, sequence args) atom pid sequence ipipe, opipe, epipe ipipe = {os_pipe()} opipe = {os_pipe()} epipe = {os_pipe()} if atom(ipipe[1]) then error() end if if atom(opipe[1]) then error() end if if atom(epipe[1]) then error() end if ipipe = ipipe[1] opipe = opipe[1] epipe = epipe[1] pid = os_fork() if pid = 0 then VOID = os_signal(15, os_sig_dfl) --15 = sigterm if os_dup2(ipipe[1], os_stdin) = -1 then error() end if if os_dup2(opipe[2], os_stdout) = -1 then error() end if if os_dup2(epipe[2], os_stderr) = -1 then error() end if if os_execv(command, args) then error() end if elsif pid = -1 then error() end if return {pid, ipipe[2], opipe[1], epipe[1]} end function --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="demo1.exu" with trace include pipeio.e sequence data --data = popen("/opt/euphoria/bin/exu", {"subprocess1.exu"}) -- eu programs dont work w/ pipes, so use echo to test instead --data = popen("/bin/echo", {"Hello World!"}) -- interesting bug, some strange garbage is printed instead of the message. data = popen("/bin/arch", {}) -- this seems to work fine integer pid, pin, pout, perr pid = data[1] pin = data[2] pout = data[3] perr = data[4] object c c = os_read(pout, 256) if atom(c) then printf(1, "Failed on read with error %x", os_errno) abort(1) end if puts(1, c) VOID = os_kill(pid, 15) --pclose(pipe) --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="demo2.exu" with trace include pipeio.e sequence data --data = popen("/opt/euphoria/bin/exu", {"subprocess2.exu"}) -- eu programs dont work w/ pipes, so use cat to test instead data = popen("/bin/cat", {}) integer pid, pin, pout, perr pid = data[1] pin = data[2] pout = data[3] perr = data[4] object c c = os_write(pin, "Hello, World!\n") if c = -1 then printf(1, "Failed on write with error %x", os_errno) abort(1) end if c = os_read(pout, 256) if atom(c) then printf(1, "Failed on read with error %x", os_errno) abort(1) end if puts(1, c) VOID = os_kill(pid, 15) --pclose(pipe) --fdj2RfSjLxBAspz7--