Hi,

The appended patch to Hugs98 (to be applied in the src subdirectory)
might be of some help for those who want to do shell scripting in
Haskell. It modifies IO.openFile as follows:

- If the name of a file opened in ReadMode ends in "|", then the part
  before the "|" is considered a program and its standard output is
  read.

- If the name of a file opened in WriteMode begins with "|", then the
  part after the "|" is considered a program and it is written to its
  standard input.

Several Unix programs have such a behaviour.

With the patch applied, you can do things like this:

  do h <- openFile "cat /etc/group|" ReadMode
     h' <- openFile "|tr aeiou '*'" WriteMode
     hGetContents h >>= hPutStr h'
     hClose h
     hClose h'

Now for the disclaimers.

The patched program is in no way meant to be elegant. I rather tried to
keep the patch itself as small as possible. I also have not tested it on
any environment other than my Linux machine. And to be honest, I didn't
completely understand what I was doing. (What are, e.g., `ap' and
`HANDCELL'?)

The patch is also not a complete solution to the needs of script
programmers because you can only access the standard input *or* the
standard output of a program. A cleaner solution would be based on the
`pipe', `fork' and `execve' system calls made available as Haskell
primitives. But I don't understand enough of the hugs internals to
implement that.

Heribert.

----------------------------------------------------------------------
*** storage.c.orig      Fri Aug 20 18:34:05 1999
--- storage.c   Sat Aug 21 09:33:34 1999
***************
*** 2441,2446 ****
--- 2441,2460 ----
        ERRMSG(0) "Too many handles open; cannot open \"%s\"", s
        EEND;
      }
+     else if (hmode&HREAD && s[strlen(s)-1]=='|') {
+       s[strlen(s)-1] = (char) 0;
+       /* Is this side effect harmless? */
+       if (handles[i].hfp=popen(s,"r")) {
+           handles[i].hmode = hmode;
+           return (handles[i].hcell = ap(HANDCELL,i));
+       }
+     }
+     else if (hmode&HWRITE && s[0]=='|') {
+       if (handles[i].hfp=popen(s+1,"w")) {
+           handles[i].hmode = hmode;
+           return (handles[i].hcell = ap(HANDCELL,i));
+       }
+     }
      else {                                      /* prepare to open file    */
        String stmode;
        if (binary) {
***************
*** 2464,2470 ****
  Int n; {                                /* heap references to it remain    */
      if (0<=n && n<NUM_HANDLES && nonNull(handles[n].hcell)) {
        if (n>HSTDERR && handles[n].hmode!=HCLOSED && handles[n].hfp) {
!           fclose(handles[n].hfp);
            handles[n].hfp = 0;
        }
        fst(handles[n].hcell) = snd(handles[n].hcell) = NIL;
--- 2478,2488 ----
  Int n; {                                /* heap references to it remain    */
      if (0<=n && n<NUM_HANDLES && nonNull(handles[n].hcell)) {
        if (n>HSTDERR && handles[n].hmode!=HCLOSED && handles[n].hfp) {
!           if (pclose(handles[n].hfp) == -1) {
!               /* Is there a more elegant way to find out whether a
!                    FILE is actually a pipe? */
!               fclose(handles[n].hfp);
!           }
            handles[n].hfp = 0;
        }
        fst(handles[n].hcell) = snd(handles[n].hcell) = NIL;


Reply via email to