home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff290.lzh / IPC / Sources / Broker.c < prev    next >
C/C++ Source or Header  |  1989-12-11  |  8KB  |  310 lines

  1. /* Initial cut at a "Port Broker" for the LoadIPCPort function */
  2. /* version 89:11:26 */
  3.  
  4. /*************************************************************
  5.  *
  6.  *  This is a simple broker program that determines which
  7.  *  program should be loaded to service a requested IPCPort
  8.  *  name.  When running, it is sent a message whenever a
  9.  *  LoadIPCPort call in another program cannot find a served
  10.  *  port of that name already active.  The broker looks the
  11.  *  name up in its list (created at startup time for now);
  12.  *  if it is found, there will be a CLI command associated
  13.  *  with it, which the broker executes.  At the same time,
  14.  *  the port is marked as "LOADING", so that it can accept
  15.  *  messages.
  16.  *
  17.  *  The list pairing port names with commands is created
  18.  *  from a file read when the broker starts.  (This simple
  19.  *  version has no mechanism for adding or changing entries
  20.  *  later, but such wouldn't be hard to add.)
  21.  *  If the broker is run from the CLI, you can specify the
  22.  *  file as an argument; if it is started from the WorkBench,
  23.  *  you can put a tooltype 'FILE=filename' in the icon.
  24.  *  If no file at all is specified, it will look for
  25.  *  "IPC_Port_List" in 'S:'.  If it can't find a file, or it
  26.  *  is empty, the broker will abort.
  27.  *
  28.  *  The file format is simply a series of single-line entries,
  29.  *  each beginning with a port name ENCLOSED IN QUOTES, followed
  30.  *  by a space and then the CLI command to be executed that will
  31.  *  result in that port being served. (A full command pathname is
  32.  *  generally required -- unless the command is in 'C:'; full
  33.  *  paths are always required for argument files.) Any line
  34.  *  that doesn't begin with a quote (") is simply skipped,
  35.  *  so you can include comments if you want.
  36.  *  [This format was chosen simply  because it was easy to
  37.  *  implement -- other brokers might define quite a different
  38.  *  one.  Multiple line commands, or wild card matching, might
  39.  *  be allowed, for instance.]
  40.  *
  41.  *  Note that -- because of Execute()'s limitations -- there
  42.  *  is NO way for the broker to know if the command has actually
  43.  *  been successfully launched or not.  So it is possible that
  44.  *  a LOADING port might never actually do so!
  45.  *
  46.  *  Note also that -- for similar reasons -- all command output
  47.  *  is directed to NIL: when the broker is started from an icon.
  48.  *  It should be possible to direct it to the window Lattice
  49.  *  kindly opens for us, but this is not straightforward.
  50.  *  (To terminate the broker, type ctrl-C to its window.)
  51.  *
  52.  *                         * * * *
  53.  *
  54.  *  [This program has only been compiled under Lattice 5.04]
  55.  *
  56.  *************************************************************/
  57.  
  58. #include "IPCPorts.h"
  59. #include "IPC_proto.h"
  60. #include "IPC.h"
  61.  
  62. #include <proto/exec.h>
  63. #include <proto/dos.h>
  64.  
  65. #include <exec/types.h>
  66. #include <exec/exec.h>
  67. #include <workbench/startup.h>
  68. #include <workbench/workbench.h>
  69. #include <workbench/icon.h>
  70.  
  71. #include <stdio.h>
  72.  
  73. #include <exec/memory.h>
  74. #include <exec/tasks.h>
  75. #include <libraries/DOS.h>
  76.  
  77. #define  SOL(s)  ((LONG)sizeof(s))
  78.  
  79. #define IPPL MAKE_ID('I','P','P','L')
  80. #define PORT MAKE_ID('P','O','R','T')
  81.  
  82. ULONG IPCBase = NULL;
  83.  
  84. struct IPCPort *brokerport;
  85. struct IPCMessage *imsg=NULL;
  86.  
  87. void baditem(struct IPCItem *, ULONG);
  88. void outputstr(char *);
  89.  
  90. struct Task * FindTask(char *);
  91.  
  92. void Cleanup();
  93.  
  94. struct portref {
  95.     struct portref * next;
  96.     int flags;
  97.     char * portname;
  98.     char * command;
  99. } * portlist, * endlist;
  100.  
  101. ULONG bportsig = 0;  /* signal masks for port */
  102.  
  103. int active = TRUE;
  104.  
  105. char * bfilename = "S:IPC_Port_List";
  106.  
  107.  
  108. int newportref(char * line)
  109. {
  110.     char * cp;
  111.     struct portref * ref;
  112.     if (*line != '"') return TRUE; /* required for now (just skip if not)*/
  113.     for (cp=line+1; *cp && *cp != '"'; cp++) {/* loop*/};
  114.     if (!*cp) return TRUE; /* just skip a bad line... */
  115.     *cp = '\0'; /* cut the line in two */
  116.     while (*++cp == ' ' || *cp == '\t') {/*loop*/};
  117.     if (!(ref = calloc(1, sizeof(struct portref)))) return FALSE;
  118.     if (!(ref->portname = malloc(strlen(line+1)+1))) return FALSE;
  119.     if (!(ref->command = malloc(strlen(cp)+1))) return FALSE;
  120.     strcpy(ref->portname, line+1);
  121.     strcpy(ref->command, cp);
  122.     if (endlist) endlist->next = ref;
  123.     else portlist = ref;
  124.     endlist = ref;
  125.     return TRUE;
  126. }
  127.  
  128.  
  129. int getportlist(char * filename)
  130. {
  131.     FILE * bfile;
  132.     char line[256];
  133.     line[255] = '\0';   /* just in case...*/
  134.     bfile = fopen(filename, "r");
  135.     if (!bfile) return FALSE;
  136.     while (fgets(line, 255, bfile) && newportref(line)) {/*loop*/};
  137.     fclose(bfile);
  138.     return portlist ? TRUE : FALSE; /* reading nothing regarded as error */
  139. }
  140.  
  141. ULONG dosout;
  142.  
  143. /**************************/
  144.  
  145. LONG IconBase;
  146.  
  147. extern struct WBStartup *WBenchMsg;
  148. struct DiskObject *iconobj, *GetDiskObject();
  149.  
  150. int readWB()
  151. {
  152.     char **toolarray, *FindToolType();
  153.     char * portliststring;
  154.     struct WBArg *argptr;
  155.  
  156.     dosout = Open("NIL:", MODE_OLDFILE);    /* redirect to black hole */
  157.  
  158.     if (!WBenchMsg)
  159.       return FALSE;
  160.  
  161.     IconBase = OpenLibrary(ICONNAME,1);
  162.     if (!IconBase)
  163.       return FALSE; /* just soldier on...*/
  164.  
  165.     argptr = WBenchMsg->sm_ArgList;
  166.  
  167.     if (!(iconobj = GetDiskObject(argptr->wa_Name)))
  168.       return FALSE;
  169.  
  170.     toolarray = iconobj->do_ToolTypes;
  171.  
  172.     if (portliststring = FindToolType(toolarray,"FILE"))
  173.         bfilename = portliststring;
  174.  
  175.     return TRUE;
  176. }
  177.  
  178. /**************************/
  179.  
  180.  
  181.  
  182.  
  183. void main(int argc, char ** argv)
  184. {
  185.     ULONG sigset;
  186.  
  187.     dosout = Output(); /* unless WorkBench */
  188.  
  189.     if (!argc) readWB();
  190.     else if (argc > 1)  /* use passed filename */
  191.         bfilename = argv[1];
  192.  
  193.     IPCBase = OpenLibrary("ppipc.library",0);
  194.     if (!IPCBase) {
  195.         outputstr("couldn't find IPC Library -- TTFN...\n");
  196.         exit(20);
  197.     }
  198.  
  199.     if (!getportlist(bfilename)) {
  200.         outputstr("couldn't read the port list\n");
  201.         Cleanup();
  202.         exit(20);
  203.     }
  204.  
  205.     brokerport = ServeIPCPort("PortBrokerPort");
  206.     if (!brokerport) {Cleanup(); _exit(11);}
  207.     bportsig = 1<<brokerport->ipp_Port.mp_SigBit;
  208.     outputstr("Opened 'PortBrokerPort'\n");
  209.  
  210.  
  211.     do {
  212.         while ( procimsg() ) ;    /* loop */
  213.         if (active) {
  214.             sigset = Wait(bportsig | SIGBREAKF_CTRL_C);
  215.             if (sigset & SIGBREAKF_CTRL_C) {
  216.                 active = FALSE;
  217.                 ShutIPCPort(brokerport);
  218.                 continue; /* so we clear out any messages that sneak in */
  219.             }
  220.         }
  221.     } while (active);
  222.     outputstr("Broker terminating...\n");
  223.  
  224.     Cleanup();
  225. }
  226.  
  227.  
  228. void cleanportlist()
  229. {
  230.     struct portref * ref;
  231.     while (portlist) {
  232.         ref = portlist;
  233.         portlist = ref->next;
  234.         free(ref->portname);
  235.         free(ref->command);
  236.         free(ref);
  237.     }
  238.     portlist = endlist = NULL;  /* in case of future developments */
  239. }
  240.  
  241. void Cleanup()
  242. {
  243.     cleanportlist();
  244.     if (brokerport) LeaveIPCPort(brokerport);
  245.     if (iconobj) FreeDiskObject(iconobj);
  246.     if (IconBase) CloseLibrary(IconBase);
  247.     CloseLibrary(IPCBase);
  248.     if (dosout && dosout != Output()) Close(dosout);
  249. }
  250.  
  251.  
  252. procimsg()
  253. {
  254.     struct IPCItem *item;
  255.     if (!(imsg = (struct IPCMessage *) GetMsg(brokerport))) return FALSE;
  256.     item = imsg->ipc_Items;
  257.     if (imsg->ipc_Id == IPPL && item->ii_Id == PORT
  258.         && loadport(item->ii_Ptr)) /* everything OK */;
  259.     else imsg->ipc_Flags |= IPC_NOTKNOWN;
  260.     ReplyMsg(imsg);
  261.     return TRUE;
  262. }
  263.  
  264.  
  265. void baditem(item, extraflags)
  266.     struct IPCItem *item;
  267.     ULONG extraflags;
  268. {
  269.     imsg->ipc_Flags |= IPC_CHECKITEM;
  270.     item->ii_Flags |= IPC_NOTKNOWN | extraflags;
  271. }
  272.  
  273. void outputstr(str) char *str;
  274. {
  275.     Write(dosout, str, strlen(str));
  276. }
  277.  
  278.  
  279. /*
  280.  *  loadport(portptr)
  281.  *
  282.  *  -- actually initiates the loading procedure.
  283.  *      returns TRUE if successful, otherwise FALSE.
  284.  */
  285.  
  286. loadport(port) struct IPCPort *port;
  287. {
  288.     struct portref * pr = portlist;
  289.     char * pname = port->ipp_Name;
  290.     outputstr("Looking up server for port '");
  291.     outputstr(pname);
  292.     for (pr=portlist; pr && strcmp(pr->portname, pname); pr = pr->next)
  293.          {/*loop*/};
  294.     if (pr) {   /* we have a match */
  295.         port->ipp_Flags |= IPP_LOADING;
  296.         Execute(pr->command, 0, dosout);    /* out to NIL: if WB */
  297.         outputstr(" -- OK\n");
  298.         return TRUE;
  299.     }
  300.     else {
  301.         outputstr(" -- Not Found!\n");
  302.         return FALSE;
  303.     }
  304. }
  305.  
  306.  
  307. /****************************************************************/
  308.  
  309.  
  310.