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; }
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); }
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; }
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 */
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); }
/* 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; }
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