Exemple #1
0
ULONG QueueCreate(
    PUCHAR name,
    ULONG argc,
    PRXSTRING args,
    PSZ queue,
    PRXSTRING result)
{
    PRXSTRING handleVar;
    PSZ qName;
    ULONG algorithm;
    HEV sem;
    PQueue q;
    APIRET rc;
    ULONG cc;

    if (argc < 2 || argc > 4) return QUEUE_BADPARAM;

    if (!RxStringIsPresent(args + 0)) return QUEUE_BADPARAM;
    handleVar = args + 0 ;

    if (!RxStringIsPresent(args + 1)) return QUEUE_BADPARAM;
    qName = args[1].strptr;

    if (argc > 2 && RxStringIsPresent(args + 2)) {
        if (RxStringIsAbbrev(args + 2, "FIFO", 1)) algorithm = QUE_FIFO;
        else if (RxStringIsAbbrev(args + 2, "LIFO", 1)) algorithm = QUE_LIFO;
        else if (RxStringIsAbbrev(args + 2, "Priority", 1)) algorithm = QUE_PRIORITY;
        else return QUEUE_BADPARAM;
    }
    else algorithm = QUE_FIFO;

    if (argc > 3 && RxStringIsPresent(args + 3)) {
        if (!RxStringToUnsigned(args + 3, &sem)) return QUEUE_BADPARAM;
    }
    else sem = 0;

    q = malloc(sizeof(Queue));
    if (q == NULL) return QUEUE_NOMEM;

    rc = DosCreateQueue(&q->handle, algorithm, qName);

    if (rc == NO_ERROR) {
        q->server = Queue_GetPID();
        q->client = q->server;
        q->sem = sem;
        q->event = sem;

        UnsignedToRxVariable((ULONG)q, handleVar);
    }
    else free(q);

    cc = UnsignedToRxResult(rc, result);
    return cc;
}
Exemple #2
0
void ap_mpm_child_main(apr_pool_t *pconf)
{
    ap_listen_rec *lr = NULL;
    int requests_this_child = 0;
    int rv = 0;
    unsigned long ulTimes;
    int my_pid = getpid();
    ULONG rc, c;
    HQUEUE workq;
    apr_pollset_t *pollset;
    int num_listeners;
    TID server_maint_tid;
    void *sb_mem;

    /* Stop Ctrl-C/Ctrl-Break signals going to child processes */
    DosSetSignalExceptionFocus(0, &ulTimes);
    set_signals();

    /* Create pool for child */
    apr_pool_create(&pchild, pconf);

    ap_run_child_init(pchild, ap_server_conf);

    /* Create an event semaphore used to trigger other threads to shutdown */
    rc = DosCreateEventSem(NULL, &shutdown_event, 0, FALSE);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to create shutdown semaphore, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Gain access to the scoreboard. */
    rc = DosGetNamedSharedMem(&sb_mem, ap_scoreboard_fname,
                              PAG_READ|PAG_WRITE);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "scoreboard not readable in child, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_calc_scoreboard_size();
    ap_init_scoreboard(sb_mem);

    /* Gain access to the accpet mutex */
    rc = DosOpenMutexSem(NULL, &ap_mpm_accept_mutex);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "accept mutex couldn't be accessed in child, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Find our pid in the scoreboard so we know what slot our parent allocated us */
    for (child_slot = 0; ap_scoreboard_image->parent[child_slot].pid != my_pid && child_slot < HARD_SERVER_LIMIT; child_slot++);

    if (child_slot == HARD_SERVER_LIMIT) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
                     "child pid not found in scoreboard, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_my_generation = ap_scoreboard_image->parent[child_slot].generation;
    memset(ap_scoreboard_image->servers[child_slot], 0, sizeof(worker_score) * HARD_THREAD_LIMIT);

    /* Set up an OS/2 queue for passing connections & termination requests
     * to worker threads
     */
    rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid));

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to create work queue, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Create initial pool of worker threads */
    for (c = 0; c < ap_min_spare_threads; c++) {
//        ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c);
    }

    /* Start maintenance thread */
    server_maint_tid = _beginthread(server_maintenance, NULL, 32768, NULL);

    /* Set up poll */
    for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
        num_listeners++;
    }

    apr_pollset_create(&pollset, num_listeners, pchild, 0);

    for (lr = ap_listeners; lr != NULL; lr = lr->next) {
        apr_pollfd_t pfd = { 0 };

        pfd.desc_type = APR_POLL_SOCKET;
        pfd.desc.s = lr->sd;
        pfd.reqevents = APR_POLLIN;
        pfd.client_data = lr;
        apr_pollset_add(pollset, &pfd);
    }

    /* Main connection accept loop */
    do {
        apr_pool_t *pconn;
        worker_args_t *worker_args;
        int last_poll_idx = 0;

        apr_pool_create(&pconn, pchild);
        worker_args = apr_palloc(pconn, sizeof(worker_args_t));
        worker_args->pconn = pconn;

        if (num_listeners == 1) {
            rv = apr_socket_accept(&worker_args->conn_sd, ap_listeners->sd, pconn);
        } else {
            const apr_pollfd_t *poll_results;
            apr_int32_t num_poll_results;

            rc = DosRequestMutexSem(ap_mpm_accept_mutex, SEM_INDEFINITE_WAIT);

            if (shutdown_pending) {
                DosReleaseMutexSem(ap_mpm_accept_mutex);
                break;
            }

            rv = APR_FROM_OS_ERROR(rc);

            if (rv == APR_SUCCESS) {
                rv = apr_pollset_poll(pollset, -1, &num_poll_results, &poll_results);
                DosReleaseMutexSem(ap_mpm_accept_mutex);
            }

            if (rv == APR_SUCCESS) {
                if (last_poll_idx >= num_listeners) {
                    last_poll_idx = 0;
                }

                lr = poll_results[last_poll_idx++].client_data;
                rv = apr_socket_accept(&worker_args->conn_sd, lr->sd, pconn);
                last_poll_idx++;
            }
        }

        if (rv != APR_SUCCESS) {
            if (!APR_STATUS_IS_EINTR(rv)) {
                ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
                             "apr_socket_accept");
                clean_child_exit(APEXIT_CHILDFATAL);
            }
        } else {
            DosWriteQueue(workq, WORKTYPE_CONN, sizeof(worker_args_t), worker_args, 0);
            requests_this_child++;
        }

        if (ap_max_requests_per_child != 0 && requests_this_child >= ap_max_requests_per_child)
            break;
    } while (!shutdown_pending && ap_my_generation == ap_scoreboard_image->global->running_generation);

    ap_scoreboard_image->parent[child_slot].quiescing = 1;
    DosPostEventSem(shutdown_event);
    DosWaitThread(&server_maint_tid, DCWW_WAIT);

    if (is_graceful) {
        char someleft;

        /* tell our worker threads to exit */
        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                DosWriteQueue(workq, WORKTYPE_EXIT, 0, NULL, 0);
            }
        }

        do {
            someleft = 0;

            for (c=0; c<HARD_THREAD_LIMIT; c++) {
                if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                    someleft = 1;
                    DosSleep(1000);
                    break;
                }
            }
        } while (someleft);
    } else {
        DosPurgeQueue(workq);

        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                DosKillThread(ap_scoreboard_image->servers[child_slot][c].tid);
            }
        }
    }

    apr_pool_destroy(pchild);
}
Exemple #3
0
int main(USHORT argc, PCHAR argv[]) {



   PSZ         szQueueName  = "\\QUEUES\\OF\\DATA\\WAITING\\FOR\\SERVICE";

   HQUEUE      hqSpecialQue = NULLHANDLE; /* Queue handle                   */

   REQUESTDATA Request      = {0};        /* Reques */

   PID         pidOwner     = 0;

   APIRET      rc           = NO_ERROR;   /* Return code                    */



   rc = DosCreateQueue(&hqSpecialQue,    /* Queue handle                    */

             QUE_FIFO |                  /* First-In First-Out order        */

             QUE_CONVERT_ADDRESS,        /* Convert 16-bit addresses to 32  */

             szQueueName);               /* Name of the queue to create     */



   if (rc!= NO_ERROR) {

      printf ("DosCreateQueue error: return code = %u\n", rc);

      return 1;       }



   rc = DosOpenQueue (&pidOwner,         /* PID of queue owner              */

                      &hqSpecialQue,     /* Handle for created queue        */

                      szQueueName);      /* Name of the queue to open       */



   if (rc!= NO_ERROR) {

      printf ("DosOpenQueue error: return code = %u\n", rc);

      return 1;       }



           /* Kill the queue owner (which is us) */



   rc = DosKillProcess(0, pidOwner);

   if (rc != NO_ERROR) {

      printf("DosKillProcess error: return code = %u\n", rc);

      return 1;

   }



   rc = DosSleep(45000L);    /* Dead code */



   return NO_ERROR;

}
Exemple #4
0
static int executeAsync( const char *command,
                         const char *parameters,
                         const KWBoolean synchronous,
                         const KWBoolean foreground )
{
   STARTDATA sd;
   PID   childPID;
   static int instance = 0;      /* Number of program we've invoke   */

   char  queueName[FILENAME_MAX];
   PVOID queueDataAddress;
   BYTE  queueElementPriority;
   HQUEUE queueHandle;

#ifdef __OS2__
   APIRET rc;
   REQUESTDATA  queueRequest;
   ULONG sessID;
   ULONG queueDataLength;
#else
   USHORT rc;
   QUEUERESULT  queueRequest;
   USHORT sessID;
   USHORT queueDataLength;

#ifndef SSF_RELATED_CHILD

   #define SSF_RELATED_INDEPENDENT 0
   #define SSF_RELATED_CHILD       1

   #define SSF_FGBG_FORE           0
   #define SSF_FGBG_BACK           1

   #define SSF_TRACEOPT_NONE       0

   #define SSF_INHERTOPT_PARENT    1

   #define SSF_TYPE_DEFAULT        0

   #define SSF_CONTROL_MAXIMIZE    0x0002
   #define SSF_CONTROL_MINIMIZE    0x0004

#endif  /* SSF_RELATED_CHILD */
#endif

/*--------------------------------------------------------------------*/
/*       Special case foreground synchronous commands; this           */
/*       insures redirected input is processed properly.              */
/*--------------------------------------------------------------------*/

   if ( synchronous )
   {
      int result = spawnl(  P_WAIT,
                            (char *) command,
                            (char *) command,
                            (char *) parameters,
                            NULL);

      if (result == -1)       /* Did spawn fail?                   */
         printerr(command);   /* Yes --> Report error              */

      return result;

   } /*  */

/*--------------------------------------------------------------------*/
/*              Initialize the start session parameters               */
/*--------------------------------------------------------------------*/

   memset( (void *) &sd, 0, sizeof sd );

   sd.Length      = 32;          /* Just basic info + InheritOpt     */

   sd.FgBg        = (USHORT) (foreground ? SSF_FGBG_FORE : SSF_FGBG_BACK);
   sd.TraceOpt    = SSF_TRACEOPT_NONE;
   sd.PgmName     = (PSZ) command;
   sd.PgmInputs   = (PSZ) parameters;
   sd.Environment = 0;           /* Just use our own envionment      */
   sd.InheritOpt  = SSF_INHERTOPT_PARENT; /* Pass it to child        */
   sd.SessionType = SSF_TYPE_DEFAULT;     /* Let the system pick
                                             session type            */
   sd.PgmControl  = (USHORT) (foreground ?
                        SSF_CONTROL_MAXIMIZE : SSF_CONTROL_MINIMIZE);

/*--------------------------------------------------------------------*/
/*       Build the queue to listen for the subtask ending.  This      */
/*       code is actually correct, but ignored since we returned      */
/*       after spawn() above.                                         */
/*--------------------------------------------------------------------*/

   if ( synchronous )
   {
      sprintf(queueName,
              "\\queues\\pid%d\\pgm%d",
              (int) getpid(),
              instance++);

      rc = DosCreateQueue( &queueHandle,
#ifdef __OS2__
                           QUE_FIFO | QUE_CONVERT_ADDRESS,
#else
                           QUE_FIFO,
#endif
                           (PSZ) queueName );

      if ( rc )
      {
         printOS2error( queueName, rc );
         return -4;                 /* Report command never was run     */
      }

      sd.TermQ       = (PSZ) queueName;
      sd.Related     = SSF_RELATED_CHILD;       /* Child session        */

   } /* if ( synchronous ) */
   else {

      sd.TermQ       = (PSZ) 0;     /* Don't wait for session end       */
      sd.Related     = SSF_RELATED_INDEPENDENT; /* Not a child session  */

   } /* else */

   rc = DosStartSession( &sd,
                         &sessID,
                         &childPID );

   if ( rc )
   {
      printOS2error( command ? command : parameters, rc );
      return -5;
   }

/*--------------------------------------------------------------------*/
/*      If the command is running asynchonously return to caller      */
/*--------------------------------------------------------------------*/

   if ( ! synchronous )
      return 0;

/*--------------------------------------------------------------------*/
/*                   Wait for the child to complete                   */
/*--------------------------------------------------------------------*/

   memset( (void *) &queueRequest, 0, sizeof queueRequest );

   rc = DosReadQueue( queueHandle,
                      &queueRequest,
                      &queueDataLength,
                      &queueDataAddress,
                      0,            /* First element in the queue    */
                      0,            /* Wait for queue to be ready    */
                      &queueElementPriority,
                      0);           /* Semaphore handle -- not used  */

   if ( rc )
   {
      printOS2error( queueName, rc );
      panic();
   }

   rc = ((unsigned short FAR*) queueDataAddress)[1];

#ifdef __OS2__
   DosFreeMem( queueDataAddress );
#else
   DosFreeSeg( SELECTOROF(queueDataAddress) );
#endif

   return (int) rc;

} /* executeAsync */
Exemple #5
0
void fly_launch (char *command, int wait, int pause)
{
    char    failbuf[512], *cmd, *p, que_name[64], *w;
    int     rc;
    PID     pid;
    ULONG   sess_id, datalen;
    void    *data;
    
    STARTDATA    sdata;
    HQUEUE       hq;
    REQUESTDATA  rd;
    BYTE         prty;

    if (wait)
    {
        debug_tools ("entered fly_launch(%s)\n", command);
        w = get_window_name ();
        set_window_name (command);
        snprintf1 (que_name, sizeof(que_name), "\\QUEUES\\FLY\\%u\\LAUNCH", getpid ());
        rc = DosCreateQueue (&hq, QUE_FIFO, que_name);
        debug_tools ("rc = %d after DosCreateQueue\n", rc);
        if (rc != 0)
        {
            set_window_name (w);
            return;
        }
        
        cmd = strdup (command);
        p = strchr (cmd, ' ');
        if (p != NULL) *p = '\0';

        sdata.Length = sizeof (STARTDATA);
        sdata.Related = SSF_RELATED_CHILD;
        sdata.FgBg = SSF_FGBG_FORE;
        sdata.TraceOpt = SSF_TRACEOPT_NONE;
        sdata.PgmTitle = NULL;
        sdata.PgmName = cmd;
        sdata.PgmInputs = (p == NULL) ? NULL : p+1;
        sdata.TermQ = que_name;
        sdata.Environment = NULL;
        sdata.InheritOpt = SSF_INHERTOPT_SHELL;
        sdata.SessionType = SSF_TYPE_DEFAULT;
        sdata.IconFile = NULL;
        sdata.PgmHandle = 0;
        sdata.PgmControl = 0;
        sdata.InitXPos = 0;
        sdata.InitYPos = 0;
        sdata.InitXSize = 100;
        sdata.InitYSize = 100;
        sdata.Reserved = 0;
        sdata.ObjectBuffer = failbuf;
        sdata.ObjectBuffLen = sizeof (failbuf);

        debug_tools ("going for DosStartSession()\n");
        rc = DosStartSession (&sdata, &sess_id, &pid);
        
        debug_tools ("rc = %d, failbuf: [%s]\n", rc, failbuf);

        if (rc == 0)
        {
            datalen = sizeof (rd);
            prty = 0;
            DosReadQueue (hq, &rd, &datalen, &data, 0, DCWW_WAIT, &prty, 0);
        }
        DosCloseQueue (hq);
        
        free (cmd);
        set_window_name (w);
    }
    else
    {
        cmd = malloc (strlen (command)+32);
        snprintf1 (cmd, strlen (command)+32, "detach %s >nul 2>&1", command);
        str_translate (cmd, '/', '\\');
        debug_tools ("detaching [%s]\n", cmd);
        system (cmd);
        free (cmd);
    }
}
void os2KbdMonitorThread(void* arg)
{
	struct KeyPacket packet;
	APIRET rc;
	USHORT length,print_flag;
	ULONG queueParam;
	HMONITOR hKbdMonitor;
	MONIN monInbuf;
	MONOUT monOutbuf;
	char queueName[128];

#if 0
	monInbuf=(MONIN *)_tmalloc(2*sizeof(MONIN));
	if (monInbuf==NULL) {
		xf86Msg(X_ERROR,
			"Could not allocate memory in kbd monitor thread!\n");
		exit(1);
	}
	monOutbuf=(MONOUT *) &monInbuf[1];
#endif

	monInbuf.cb=sizeof(MONIN);
	monOutbuf.cb=sizeof(MONOUT);

	rc = DosMonOpen("KBD$",&hKbdMonitor);
	xf86Msg(X_INFO,"Opened kbd monitor, rc=%d\n",rc);
 	rc = DosMonReg(hKbdMonitor,
		       (PBYTE)&monInbuf,(PBYTE)&monOutbuf,(USHORT)2,(USHORT)-1);
	xf86Msg(X_INFO,"Kbd monitor registered, rc=%d\n",rc);
	if (rc) {
		DosMonClose(hKbdMonitor);
		exit(1);
	}

	/* create a queue */
	sprintf(queueName,"\\QUEUES\\XF86KBD\\%d",getpid());
	rc = DosCreateQueue(&hKbdQueue,0L,queueName);
	xf86Msg(X_INFO,"Kbd Queue created, rc=%d\n",rc);
	(void)DosPurgeQueue(hKbdQueue);

	while (1) {
		length = sizeof(packet);
		rc = DosMonRead((PBYTE)&monInbuf,0,(PBYTE)&packet,&length);
		if (rc)	{
			xf86Msg(X_ERROR,
				"DosMonRead returned bad RC! rc=%d\n",rc);
			DosMonClose(hKbdMonitor);
			exit(1);
		}
		queueParam = packet.mnflags+(packet.ddflags<<16);
		if (packet.mnflags&0x7F00)
			DosWriteQueue(hKbdQueue,queueParam,0L,NULL,0L);
			/*xf86Msg(X_INFO,"Wrote a char to queue, rc=%d\n",rc); */
		print_flag = packet.ddflags & 0x1F;

		/*xf86Msg(X_INFO,"Kbd Monitor: Key press %d, scan code %d, ddflags %d\n",
			  packet.mnflags&0x8000,(packet.mnflags&0x7F00)>>8,packet.ddflags); 
		*/

		/* This line will swallow print-screen keypresses */
		if (print_flag == 0x13 || print_flag == 0x14 || 
		    print_flag == 0x15 || print_flag == 0x16)
			rc = 0;
		else
			rc = DosMonWrite((PBYTE)&monOutbuf,(PBYTE)&packet,length); 
		if (rc) {
			xf86Msg(X_ERROR,
				"DosMonWrite returned bad RC! rc=%d\n",rc);
			DosMonClose(hKbdMonitor);
			exit(1);
		}
	}

	DosCloseQueue(hKbdQueue);
	DosMonClose(hKbdMonitor);
}
Exemple #7
0
/* Launch program `name' (searched via the PATH environment variable)
   passing `argv' as the parameters, wait for it to exit and return its
   exit status. If `stdout_redir' or `stderr_redir' are != NULL,
   redirect stdout or stderr to the corresponding file.  */
int archdep_spawn(const char *name, char **argv, char **pstdout_redir, const char *stderr_redir)
{
    // how to redirect stdout & stderr??
    typedef struct _CHILDINFO {  /* Define a structure for the queue data */
        USHORT usSessionID;
        USHORT usReturn;
    } CHILDINFO;

    UCHAR fqName[256] = ""; /* Result of PATH search             */
    HQUEUE hqQueue;         /* Queue handle                      */
    REQUESTDATA rdRequest;  /* Request data for the queue        */
    ULONG ulSzData;         /* Size of the queue data            */
    BYTE bPriority;         /* For the queue                     */
    PVOID pvData;           /* Pointer to the queue data         */
    STARTDATA sd;           /* Start Data for DosStartSession    */
    PID pid;                /* PID for the started child session */
    ULONG ulSession;        /* Session ID for the child session  */
    APIRET rc;              /* Return code from API's            */
    char *cmdline;
    char *stdout_redir = NULL;

    if (pstdout_redir != NULL) {
        if (*pstdout_redir == NULL) {
            *pstdout_redir = archdep_tmpnam();
        }
        stdout_redir = *pstdout_redir;
    }

    if (archdep_search_path(name, fqName, sizeof(fqName))) {
        return -1;
    }

    // Make the needed command string
    cmdline = archdep_cmdline(fqName, argv, stdout_redir, stderr_redir);

    memset(&sd, 0, sizeof(STARTDATA));
    sd.Length = sizeof(STARTDATA);
    sd.FgBg = SSF_FGBG_BACK;      /* Start session in background */
    sd.Related = SSF_RELATED_CHILD;  /* Start a child session       */
    sd.PgmName = "cmd.exe";
    sd.PgmInputs = cmdline;
    sd.PgmControl = SSF_CONTROL_INVISIBLE;
    sd.TermQ = "\\QUEUES\\VICE2\\CHILD.QUE";
    sd.InheritOpt = SSF_INHERTOPT_SHELL;

    /* Start a child process and return it's session ID.
     Wait for the session to end and get it's session ID
     from the termination queue */

    // this prevents you from closing Vice while a child is running
    if (DosRequestMutexSem(hmtxSpawn, SEM_INDEFINITE_WAIT)) {
        return 0;
    }

    if (!(rc = DosCreateQueue(&hqQueue, QUE_FIFO|QUE_CONVERT_ADDRESS, sd.TermQ))) {
        if (!(rc = DosStartSession(&sd, &ulSession, &pid)))  {
            if (!(rc = DosReadQueue(hqQueue, &rdRequest, &ulSzData, &pvData, 0, DCWW_WAIT, &bPriority, 0))) {
                rc = ((CHILDINFO*)pvData)->usReturn;

                DosFreeMem(pvData); /* Free the memory of the queue data element read */
            }
        }
        DosCloseQueue(hqQueue);
    }

    DosReleaseMutexSem(hmtxSpawn);

    lib_free(cmdline);
    return rc;
}
Exemple #8
0
int main (int argc, char *argv[])
{
  HQUEUE hq_server, hq_client;
  ULONG rc, len;
  PID owner_pid;
  PVOID data;
  REQUESTDATA request;
  BYTE priority;
  char buffer[1024], name[512], *p;
  long client_pid;

  if (argc == 1)
    {
      if (spawnl (P_NOWAIT, argv[0], argv[0], "-r", NULL) < 0)
	  {
	  perror ("spawn");
	  return (1);
	  }
      for (;;)
	{
	  if (fgets (buffer, sizeof (buffer), stdin) == 0)
	    return (0);
	  p = buffer;
	  while (*p != 0 && !(*p >= '0' && *p <= '9'))
	    ++p;
	  client_pid = strtol (p, NULL, 10);
	  (void)sprintf (name, "/queues/emacs/clients/%ld", client_pid);
	  rc = DosOpenQueue (&owner_pid, &hq_client, name);
	  if (rc == 0)
	    {
	      len = strlen (buffer) + 1;
	      rc = DosAllocSharedMem (&data, 0, len,
				      PAG_COMMIT | OBJ_GIVEABLE | PAG_READ
				      | PAG_WRITE);
	      ERROR ("DosAllocSharedMem");
	      rc = DosGiveSharedMem (data, client_pid, PAG_READ);
	      ERROR ("DosGiveSharedMem");
	      (void)memcpy (data, buffer, len);
	      rc = DosWriteQueue (hq_client, 0, len, data, 0);
	      ERROR ("DosWriteQueue");
	      rc = DosFreeMem (data);
	      ERROR ("DosFreeMem");
	      rc = DosCloseQueue (hq_client);
	      ERROR ("DosCloseQueue");
	    }
	}
    }
  else if (argc == 2 && strcmp (argv[1], "-r") == 0)
    {
      rc = DosCreateQueue (&hq_server, QUE_FIFO | QUE_CONVERT_ADDRESS,
			   "/queues/emacs/server");
      ERROR ("DosCreateQueue");
      for (;;)
	{
	  rc = DosReadQueue (hq_server, &request, &len, &data, 0,
			     DCWW_WAIT, &priority, 0);
	  ERROR ("DosReadQueue");
	  (void)printf ("Client: %d ", (int)request.pid);
	  (void)fputs (data, stdout);
	  (void)fflush (stdout);
	  rc = DosFreeMem (data);
	  ERROR ("DosFreeMem");
	}
    }
  else
    {
      (void)fprintf (stderr, "Usage: %s\n", argv[0]);
      return (1);
    }
}
int spawnve(int mode, const char *name, char * const argv[],
            char * const envp[])
{
  int i, j, l, n, prefix_len = 0;
  char *ext, *tmp, *arg1, *execname, *p_arg, *p_env, *prefix = NULL;
  char runtype, freeexec = 0, hswValid = 0, quoteargs = 1;
  ULONG appflags;
  const char * const *p;
  unsigned int runflags = 0;
  int retcode = -1;
  char errbuf[MAXNAMLEN + 1], queue[MAXNAMLEN + 1];
  SWCNTRL swc;
  HSWITCH vioHSW;

  errno = ENOENT;

  /* EMX crashes on very long filenames... */
  if (strlen (name) > MAXNAMLEN - 4)
  {
   errno = ENAMETOOLONG;
   return -1;
  }

  /* Find extension ordinal in exec_ext array */
  ext = _getext2(name);
  for (i = 0; i < EXEC_EXT_COUNT; i++)
  {
   if (strcmp(ext, exec_ext[i]) == 0)
    goto found;
  }
  if (access(name, F_OK) == 0)
   errno = ENOEXEC;
  return -1;

found:
 {
  PTIB tb;
  PPIB pb;

  /* Determine our session type */
  if ((DosGetInfoBlocks(&tb, &pb) == NO_ERROR) &&
      (vioHSW = WinQuerySwitchHandle(NULLHANDLE, pb->pib_ulpid)) &&
      (WinQuerySwitchEntry(vioHSW, &swc) == NO_ERROR))
   hswValid = 1;
 }

 switch (mode & 0xFF)
 {
  case P_WAIT:
   runflags |= spawn_WAIT; break;
  case P_PM:
   runflags |= spawn_SESSION | spawn_TYPE_PM; break;
  case P_OVERLAY:
   runflags |= spawn_WAIT | spawn_OVERLAY; break;
  case P_DETACH:
   runflags |= spawn_DETACH; break;
 }

 if (((runtype = exec_run[i]) == 0) &&
     (DosQueryAppType((PSZ)name, &appflags) == NO_ERROR) &&
     ((runflags & spawn_DETACH) == 0) &&
     (hswValid))
 {
  /* Compare to application type */
  switch (appflags & 7)
  {
   case FAPPTYP_NOTSPEC:  /* Methinks its a DOS proggy */
   {
    if (appflags & FAPPTYP_DOS)
     if (swc.bProgType == PROG_FULLSCREEN)
      runflags |= (spawn_SESSION | spawn_TYPE_VDM);
     else
      runflags |= (spawn_SESSION | spawn_TYPE_WINDOWEDVDM);
    else
     runflags |= (spawn_SESSION | spawn_TYPE_DEFAULT);
    break;
   }
   case FAPPTYP_NOTWINDOWCOMPAT:
   {
    if (swc.bProgType != PROG_FULLSCREEN)
     runflags |= (spawn_SESSION | spawn_TYPE_FULLSCREEN);
    break;
   }
   case FAPPTYP_WINDOWCOMPAT:
   {
    /* That'll do it */
    break;
   }
   case FAPPTYP_WINDOWAPI:
   {
    runflags |= (spawn_SESSION | spawn_TYPE_PM);
    break;
   }
   default:
   {
    runtype = 1; /* Let $COMSPEC decide what to do */
    break;
   }
  }
 }

fallback:
 switch (runtype)
 {
  case 0:
directrun:
   if ((runflags & spawn_SESSION) &&
       (((runflags & spawn_TYPE) == spawn_TYPE_VDM) ||
        ((runflags & spawn_TYPE) == spawn_TYPE_WINDOWEDVDM)))
   {
    /* DOS command interpreter does not understand '/'s */
    execname = savestring((char *)name);
    freeexec = 1;
    for (tmp = execname; *tmp; tmp++)
     if (*tmp == '/') *tmp = '\\';
   } else
    execname = (char *)name;
   break;
  case 1:
   execname = get_string_value ("COMSPEC");
   if (!execname)
   {
    internal_error("COMSPEC variable not defined");
    errno = EACCES;
    return -1;
   }
   prefix_len = strlen(execname) + 1;
   prefix = alloca(prefix_len + 2 + 1 + strlen(name) + 1);
   strcpy(prefix, execname);
   emx_deunixify(prefix);
   strcpy((char *)&prefix[prefix_len - 1], " /c ");
   prefix_len += 2 + 1;
   strcpy((char *)&prefix[prefix_len], name);
   prefix_len += strlen(name) + 1;
   break;
  case 2:
  default:
  {
   /* We must define HAVE_HASH_BANG_EXEC since we`re processing #! here */
   FILE *f;
   char line[MAXNAMLEN + 3];
   line[0] = 0;
   if (!(f = fopen(name, "rt")))
   {
    errno = ENOENT;
    return -1;
   };
   fgets((char *)&line, sizeof(line), f);
   fclose(f);
   if (line[0] != '#')
    /* Try to run as regular executable */
    goto directrun;
   if (line[1] != '!')
   {
    /* Run script using current shell */
    strcpy((char *)&line, "#! ");
    strcat((char *)&line, shell_name);
   }
   n = strlen(line);
   while ((n > 0) && ((line[n - 1] < ' ') || (whitespace(line[n])))) n--;
   for (i = 2; whitespace(line[i]) && i < n; i++)
    ;
   for (j = i; (!whitespace(line[j])) && j < n; j++)
    ;
   l = i; j++;
   tmp = xmalloc(j - i);
   _strncpy(tmp, (char *)&line[i], j - i);

   execname = find_user_command(tmp);
   free(tmp);
   freeexec = 1;

   prefix_len = n - l + 1 + 1 + strlen(name);
   prefix = alloca(prefix_len + 1);
   _strncpy(prefix, (char *)&line[l], n - l + 1);
   strcat(prefix, " ");
   strcat(prefix, name);
   break;
  }
 }

 if ((execname == NULL) || (access(execname, F_OK) != 0))
 {
  if (execname == NULL)
  {
   errno = ENOEXEC;
   return -1;
  }
  execname = savestring(execname);
  freeexec = 1;
  if ((ext_file_status(&execname) & FS_EXISTS) == 0)
  {
   free(execname);
   errno = ENOENT;
   return -1;
  }
 }

 {
  char *qlist = get_string_value ("BASH_NOQUOTEARGS");
  char *tmp, *name = _getname (execname);
  int namelen;

  tmp = _getext (name);
  namelen = (tmp ? (int) (tmp - name) : strlen (name));

  while (qlist)
  {
   tmp = strchr (qlist, ';');
   if (!(j = tmp ? (int) (tmp - qlist) : strlen (qlist)))
    break;
   if ((namelen == j) &&
       (memicmp (qlist, name, namelen) == 0))
   {
    quoteargs = 0;
    break;
   }
   qlist += j;
   while (qlist[0] == ';')
    qlist++;
  }
 }

 /* Prepare command-line string */
 j = prefix_len + 2;
 for (i = 0; i <= 1; i++)
 {
  for (p = (const char **)argv; *p != NULL; ++p)
  {
   if (p != (const char **)argv)
    if (i == 0)			// Add a space before args starting from 1
     j++;
    else
     strcat(p_arg, " ");
   else
    if (prefix_len)
     continue;			// Prefix already contains argv[0]

   // If argv[i] contains a space or tab, we should put it in quotes
   if (strchr(*p, ' ') || strchr(*p, '\t'))
    if (i == 0)
     j += 1 + (quoteargs ? q_strlen(*p) : strlen(*p)) + 1;
    else
    {
     strcat(p_arg, "\"");
     if (quoteargs)
      q_strcat (p_arg, *p);
     else
      strcat (p_arg, *p);
     strcat(p_arg, "\"");
    }
   else
    // If we`re running a EMX program, we should backquote all '"'s in argv[i]
    if (i == 0)
     j += (quoteargs ? q_strlen(*p) : strlen(*p));
    else
     if (quoteargs)
      q_strcat(p_arg, *p);
     else
      strcat(p_arg, *p);
  }
  if (i == 0)
  {
   p_arg = alloca(j);
   if (prefix_len)
   {
    memcpy(p_arg, prefix, prefix_len);
    p_arg[prefix_len] = ' ';
    p_arg[prefix_len + 1] = 0;
   } else
    *p_arg = 0;
  }
 }
 p_arg[strlen(p_arg) + 1] = 0;

#if 0
 printf("quoteargs = %d\n", quoteargs);
 printf("exec{%s}\n", execname);
 printf("args{%s}\n", p_arg);
#endif

 for (arg1 = p_arg; !whitespace(*arg1) && *arg1; arg1++) ;
 *arg1++ = 0;

 /* Prepare environment */
 j = 1;
 for (p = (const char * const *)envp; *p != NULL; ++p)
  j += strlen (*p) + 1;
 p_env = tmp = alloca(j);
 for (p = (const char * const *)envp; *p != NULL; ++p)
 {
  i = strlen (*p);
  memcpy(tmp, *p, i+1);
  tmp += i+1;
 }
 *tmp = 0;

 if (runflags & spawn_SESSION) /* Use DosStartSession */
 {
  HQUEUE hq;

  /* Termination queue management */
  sprintf((char *)&queue, "\\QUEUES\\bash%d", getpid());
  if (DosCreateQueue(&hq, QUE_FIFO | QUE_CONVERT_ADDRESS, (PSZ)queue) == NO_ERROR)
  {
   STARTDATA sd;
   ULONG sid,pid;
   APIRET r;

   memset(&sd, 0, sizeof(sd));
   sd.Length = sizeof(sd);
   sd.Related = (runflags & spawn_WAIT ? SSF_RELATED_CHILD : SSF_RELATED_INDEPENDENT);
   sd.FgBg = SSF_FGBG_FORE;
   sd.PgmName = execname;
   sd.PgmInputs = arg1;
   sd.TermQ = (PBYTE)&queue;
   sd.Environment = p_env;
   sd.InheritOpt = SSF_INHERTOPT_PARENT;
   sd.SessionType = (runflags & spawn_TYPE) >> 16;
   sd.ObjectBuffer = (PSZ)&errbuf;
   sd.ObjectBuffLen = sizeof(errbuf);
#if 0
   sd.PgmControl = SSF_CONTROL_NOAUTOCLOSE;
#endif

   r = DosStartSession(&sd, &sid, &pid);

   if (r == NO_ERROR || r == ERROR_SMG_START_IN_BACKGROUND)
   {
    if (runflags & spawn_WAIT)
    {
     REQUESTDATA rd;
     ULONG Length;
     PUSHORT Info = NULL;
     BYTE Priority;
     ULONG oldVis, oldJump;
     SWP oldpos;

     if (hswValid)
     {
      /* Exclude session from task list */
      oldVis = swc.uchVisibility; swc.uchVisibility = SWL_INVISIBLE;
      oldJump = swc.fbJump; swc.fbJump = SWL_NOTJUMPABLE;
      WinChangeSwitchEntry(vioHSW, &swc);

      /* Minimize session */
      WinQueryWindowPos(swc.hwnd, &oldpos);
      if ((oldpos.fl & SWP_MINIMIZE) == 0)
       WinPostMsg(swc.hwnd, WM_SYSCOMMAND, (MPARAM)SC_MINIMIZE, MPFROM2SHORT(CMDSRC_MENU, FALSE));
     }

     DosReadQueue(hq, &rd, &Length, (PPVOID)&Info, 0,
                  DCWW_WAIT, &Priority, 0);

     if (hswValid)
     {
      /* Restore jumpable & visible status */
      swc.uchVisibility = oldVis;
      swc.fbJump = oldJump;
      WinChangeSwitchEntry(vioHSW, &swc);

      /* Restore session */
      if ((oldpos.fl & SWP_MINIMIZE) == 0)
      {
       WinPostMsg(swc.hwnd, WM_SYSCOMMAND, (MPARAM)SC_RESTORE, MPFROM2SHORT(CMDSRC_MENU, FALSE));
       WinSetWindowPos(swc.hwnd, oldpos.hwndInsertBehind, oldpos.x, oldpos.y,
                       oldpos.cx, oldpos.cy, oldpos.fl);
      }
     }

     retcode = Info[1];
    } else
     retcode = pid;
   } else
    internal_error("Execution failed because of module \"%s\"", (char *)&errbuf);
   DosCloseQueue(hq);
  } else