🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.amiga.tech
Article #2574

Using PIP:

#2574
From: Michael Richardson
Date: Thu, 07 Dec 1989 13:07
268 lines
8449 bytes

  When I finally got annoyed at the silliness of command line
passing, program launching (with exit codes) and the pr_CLI structure
in general [this was at least 6 months ago] I began to build an
alternate launching scheme, much more similar to the way the
workbench startup message works. I based it on Leo Shwab's wblaunch
code. (I'm not sure if Peter, Leo or myself that had this thought
first. I think we all came up with it independently...)

  In order deal with who closes file descriptors, etc.. I wound
up passing a bitmap to the sub-process telling it which file handles
it can close. [Actually, I can also pass the `ToolWindow' field,
and although I haven't done it yet, I always put 0 in the place
where the Workbench message's `number of arguments' is so I could
in fact be launched from Workbench...] I'd like this field eventually
to be $ffffffff. (I can pass any number of FileHandles though.
They are installed in the Manx `_devtab' structure.)

  The point: I want a Popen call that works properly, and for which
each end has it's own filehandle. PIP: seemed to be the thing, except
that I can't seem to get it work. [My popen call takes an argv/argv
rather than a string. My `RogueStart' (there is a book named Rogue
Star by Frederik Pohl) shell is too simple at present to bother
feeding it through that.]

  I tried a simple test program:

 #include <stdio.h>
 #include <fcntl.h>
 #include <exec/memory.h>
 #include <libraries/dos.h>
 #include <libraries/dosextens.h>
 #include "bcpl.h"

 extern void *AllocMem();
 extern struct FileHandle *Open();
 extern FILE *fdopen();
 extern void *CreatePort();
 extern void *GetMsg();

 main()
 {
   struct FileHandle *pin,*pout,*ret,*temp;
   int i;
   char buf[100],buf2[100];

   if((pin=AllocMem(sizeof(struct FileHandle),MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
     return(NULL);
   }
   if((pout=Open("PIP:4096",2000L))==NULL) {
     FreeMem(pin,sizeof(struct FileHandle));
     return(NULL);
   }
   temp=(struct FileHandle*)BTOC(pout);
   (*pin)=(*temp);
   pin=(struct FileHandle*)CTOB(pin);

   printf("Created two handles: %08x and %08x\n",pin,pout);
   printf("Please type a line: ");
   fgets(buf,100,stdin);
   printf("Got %s\n",buf);

   i=Write(pin,buf,strlen(buf));
   printf("Wrote string (%d)\n",i);

   i=Read(pout,buf2,100);
   buf2[i]='\0';
   printf("Read (%d) %s\n",i,buf2);

   Close(pin);
   i=Read(pout,buf2,100);
   buf2[i]='\0';
   printf("Read (%d) %s\n",i,buf2);
   Close(pout);

 }

  While this seemed to work --- it didn't always work twice, it seemed
that I could crash it by allocating pout, and opening pin rather than
the reverse. I can understand this.
  It also seemed that the order in which I closed them was significant.
I haven't run this program in awhile (I've been procrastinating
this posting for at least a couple of months... But today I'm
home sick, and don't feel like bashing any of my other projects...)
so I'm sorry if I am a bit vague --- but there is no way that I can
guarantee that the two ends of the pipe will be closed by the two
processes in the right order. Processes are quite asynchronous
in nature...
  I pretty sure that it is the order in which I close them
that is causing the guru --- sometimes when I run a little test it
crashes. Sometimes not. If I run two of them sequencially or
concurrently, I get the same results...

FILE * popenv(ac,av,mode,pp)
int ac;
char *av[];
char *mode;
struct MsgPort **pp;
{
  struct FileHandle *in,*out,*err;
  struct FileHandle *pin,*pout,*ret,*temp;
  struct MsgPort *p;
  struct RogueStartup *r;
  FILE   *rf;
  int code;
  long mask;
  int i;

  in=RogueInput();
  out=RogueOutput();
  err=RogueError();

  if(mode[0]!='r' && mode[0]!='w') return(NULL);

  if((pin=AllocMem(sizeof(struct FileHandle),MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
    return(NULL);
  }
  if((pout=Open("PIP:4096",2000L))==NULL) {
    FreeMem(pin,sizeof(struct FileHandle));
    return(NULL);
  }
  temp=(struct FileHandle*)BTOC(pout);
  (*pin)=(*temp);
  pin=(struct FileHandle*)CTOB(pin);

  if(mode[0]='r') {
    out=pin;
    ret=pout;
    mask=(1L << 1);
  }
  else {
    in=pout;
    ret=pin;
    mask=(1L << 0);
  }

  /* Now set up the _devtab structure. */
  for(i=0; i<_numdev; i++) {
    if(_devtab[i].fd==NULL) {
      break;
    }
  }

  if(i==_numdev) {
    Close(pin);
    Close(pout);
    return(NULL);
  }
  _devtab[i].fd=(long)ret;
  _devtab[i].mode=(mode[0]=='r' ? O_RDONLY : O_WRONLY);

  if((rf=(FILE *)fdopen(i,mode))==NULL) {
    _devtab[i].fd=NULL;
    Close(pin);
    Close(pout);
    return(NULL);
  }

  if((p=(struct MsgPort *)CreatePort(NULL,NULL))==NULL) {
    if(ret==pin) Close(pout);
    else Close(pin);
    fclose(rf);
    return(NULL);
  }
  if((r=RogueLaunch(p,av[0],av,ac,NULL,0,NULL,10000,in,out,err,mask))==NULL) {
/* RogueLaunch(rport, name, argv, argc, env, pri, win, stack, in, out, err) --
 *                                               launch a program.
 *
 * RogueLaunch builds a startup message, loads a program, and launches it.
 *
 * Arguments:
 *      rport -- reply port to receive startup message back when the program
 *               finishes.
 *      name  -- File name for the program to load.
 *      argv  -- list of filenames to pass to loaded program.
 *      argc  -- length of argument list.
 *      env   -- list of environment variables (local)
 *      pri   -- priority of the new process.
 *      win   -- ToolWindow for the new process, or NULL.
 *      stack -- Stack size for the new process.
 *      in    -- Where to find Standard input \ Only taking
 *      out   -- Where to find Standard output > three is
 *      err   -- Where to find Standard error / arbitrary.
 *      mask  -- bitmap of file descriptors to close.
 *
 * argv[0] should be the same as the program. pri should normally be 0.
 * stack should normally be at least 4K.
 */


    if(ret==pin) Close(pout);
    else Close(pin);
    fclose(rf);
    DeletePort(p);
    return(NULL);
  }
  *pp=p;

  return(rf);

}

int pclose(f,pp)
FILE *f;
struct MsgPort **pp;
{
  struct MsgPort *p;
  struct RogueStart *rs;
  int code;

  if(f==NULL||pp==NULL) return(-1);

  p=*pp;

  if(p==NULL) return(-2);

  WaitPort(p);
  rs=GetMsg(p);
  if(rs) {
    code=RogueFreeStartup(rs);
  }
  fclose(f);     /* Close our end of the pipe */

  return(code);
}

  I also somewhat suspect the fclose() call, but I believe I
have tried converting everything to FileHandle level...


  BTW: Programs compiled with the Rogue Startup code can continue to run
from CLI, and if I ever make the WorkBench modification from the workbench
as well.
  Many parts of the uucp system that this is being posted with runs
via RogueLaunch. Specifially I've rewritten uux/uuxqt/unbatchfc/rmail.
Rmail has also be modified a large amount -- it adds Received:, collapses
From_ [yuck], and adds a Message-Id: if there isn't one. I called
it smail because I'll eventually add `smart-host' to it. It also
calls uux with the `-a' option (however, I haven't figured out
what uux should really do with it in terms of the X. file.).

  [Lots more to say -- but mail me. An AmigaNet (not to me
confused with FidoNet despite that we run software that seems
to be compatible :-)) /AmigaUUCP mailing list has existed for
about year as amiga-mailer@doe.carleton.ca and amiga-mailer@fts1.UUCP
(doe doesn't like .UUCP addresses that much...). The list is fairly
dead right now, due in part because much of the activity has moved
to an echo called AMIGASTAND.]

  The rewrite of the rest [and the posting to Bob Page] awaits pipes
so that I can get rid of some of the temporary files. I don't like
temporary files.







--

  :!mcr!:
  Michael Richardson
                    Amiga
             v--------+
 HOME: mcr@julie.UUCP | SCHOOL: mcr@doe.carleton.ca
 Fido: 1:163/109.10<--+ WORK: michael@fts1.UUCP
Technical Details
Message-ID: <1610.AA1610@julie>
Path: arc1-ca.pugleaf.net!utzoo!dciem!nrcaer!fts1!julie!mcr

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!dciem!nrcaer!fts1!julie!mcr
From: mcr@julie.UUCP (Michael Richardson)
Newsgroups: comp.sys.amiga.tech
Subject: Using PIP:
Keywords: dupping closing pipes
Message-ID: <1610.AA1610@julie>
Date: 7 Dec 89 13:07:06 GMT
Followup-To: comp.sys.amiga.tech
Organization: Sandleman Software Works' Debugging Department, Ottawa, ON
Lines: 268