Esempio n. 1
0
File: sehll.c Progetto: simon-eh/hw9
int execute(const char *file, char * const*args) {
	
	if(strcmp(file, "exit") == 0) {
	    kill(getpid(), SIGINT);
	    exit(0);
	}

	pid_t childProc = fork();
	int saved_stdout = dup(STDOUT_FILENO);
	int saved_stdin = dup(STDIN_FILENO);


	if(childProc >= 0) {
		if(childProc == 0) {
			if(!fix_fds()) {
			    exit(0);
			}
			execvp(file, args);
			fprintf(stderr, "Error: %s\n", strerror(errno));
			exit(0);
		}
		else {	
			if(!background) {
			    children[nchildren++] = childProc;
			}
			int status;
			if(!background) {
			    waitpid(childProc, &status, 0);
			    nchildren--;
			}
			else {
			    int pid;
			    while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
			        printf("PID %d exited.\n", pid);
			    }
			}

			restore_fds(saved_stdin, saved_stdout);

			return status;
		}
	}
	else {
		fprintf(stderr, "Error: %s\n", strerror(errno));
	}
	return -1;
}
Esempio n. 2
0
int fork(void) {

	size_t rc;
	size_t stacksize;
	char modname[512];/*FIXBUF*/
	HANDLE  hProc,hThread, hArray[2];
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	SECURITY_ATTRIBUTES sa;
	DWORD dwCreationflags;
	unsigned int priority;
	HANDLE h64Parent,h64Child;

#ifndef _M_ALPHA
	unsigned long fork_stack_end;
#endif _M_ALPHA

	__fork_stack_begin =GETSTACKBASE();

#ifndef _M_ALPHA
	__fork_stack_end = &fork_stack_end;
#else
	__fork_stack_end = (unsigned long *)__asm("mov $sp, $0");
#endif /*_M_ALPHA*/

	h64Parent = h64Child = NULL;
	//
	// Create two inheritable events
	//
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor =0;
	sa.bInheritHandle = TRUE;
	if (!__hforkchild)
		__hforkchild = CreateEvent(&sa,TRUE,FALSE,NULL);
	if (!__hforkparent)
		__hforkparent = CreateEvent(&sa,TRUE,FALSE,NULL);

	rc = setjmp(__fork_context);

	if (rc) { // child
#ifdef  _M_IX86
		//
		// Restore old registration
		// -amol 2/2/97
		GETEXCEPTIONREGIST() = (struct _EXCEPTION_REGISTRATION_RECORD*)_old_exr;
#endif // _M_ALPHA
		SetEvent(__hforkchild);

		dprintf("Child ready to rumble\n");
		if(WaitForSingleObject(__hforkparent,FORK_TIMEOUT) != WAIT_OBJECT_0)
			ExitProcess(0xFFFF);

		CloseHandle(__hforkchild);
		CloseHandle(__hforkparent);
		__hforkchild = __hforkparent=0;

		//__asm { int 3};
		restore_fds();

		STR_environ = blk2short(environ);
		environ = short2blk(STR_environ);	/* So that we can free it */

		return 0;
	}
	copy_fds();
	memset(&si,0,sizeof(si));
	si.cb= sizeof(si);

	/*
	 * This f!@#!@% function returns the old value even if the std handles
	 * have been closed.
	 * Skip this step, since we know tcsh will do the right thing later.
	 * 
	 si.hStdInput= GetStdHandle(STD_INPUT_HANDLE);
	 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
	 */

	if (!GetModuleFileName(GetModuleHandle(NULL),modname,512) ) {
		rc = GetLastError();
		return -1;
	}
	dwCreationflags = GetPriorityClass(GetCurrentProcess());
	priority = GetThreadPriority(GetCurrentThread());
	rc = CreateProcess(NULL,
			modname,
			NULL,
			NULL,
			TRUE,
			CREATE_SUSPENDED | dwCreationflags,
			NULL,
			NULL,
			&si,
			&pi);
	if (!rc)  {
		rc = GetLastError();
		return -1;
	}

	ResetEvent(__hforkchild);
	ResetEvent(__hforkparent);

	hProc = pi.hProcess;
	hThread = pi.hThread;


	__forked=1;
	/*
	 * Usage of events in the wow64 case:
	 *
	 * h64Parent : initially non-signalled
	 * h64Child  : initially non-signalled
	 *
	 *    1. Create the events, resume the child thread.
	 *    2. Child opens h64Parent to see if it is a child process in wow64
	 *    3. Child opens and sets h64Child to tell parent it's running. (This
	 *       step is needed because we can't copy to a process created in the
	 *       suspended state on wow64.)
	 *    4. Copy gForkData and then set h64Parent. This tells the child
	 *       that the parameters in the structure are trustworthy.
	 *    5. Wait for h64Child so that we know the child has created the stack
	 *       in dynamic memory.
	 *
	 *   The rest of the fork hack should now proceed as in x86
	 *
	 */
	if (bIsWow64Process) {

		// allocate the heap for the child. this can be done even when
		// the child is suspended. 
		// avoids inexplicable allocation failures in the child.
		if (VirtualAllocEx(hProc,
					__heap_base,
					__heap_size,
					MEM_RESERVE,
					PAGE_READWRITE) == NULL) {
			dprintf("virtual allocex failed %d\n",GetLastError());
			goto error;
		}
		if (VirtualAllocEx(hProc,
					__heap_base,
					__heap_size,
					MEM_COMMIT,
					PAGE_READWRITE) == NULL) {
			dprintf("virtual allocex2 failed %d\n",GetLastError());
			goto error;
		}

		// Do NOT expect existing events
		if (!CreateWow64Events(pi.dwProcessId,&h64Parent,&h64Child,FALSE)) {
			goto error;
		}
		ResumeThread(hThread);

		// wait for the child to tell us it is running
		//if (WaitForSingleObject(h64Child,FORK_TIMEOUT) != WAIT_OBJECT_0) {
		//	rc = GetLastError();
		//	goto error;
		//}
		hArray[0] = h64Child;
		hArray[1] = hProc;

		if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != 
				WAIT_OBJECT_0){

			rc = GetLastError();
			goto error;
		}

	}
	//
	// Copy all the shared data
	//
	if (!WriteProcessMemory(hProc,&gForkData,&gForkData,
				sizeof(ForkData),&rc)) {
		goto error;
	}
	if (rc != sizeof(ForkData)) 
		goto error;

	if (!bIsWow64Process) {
		rc = ResumeThread(hThread);
	}
	// in the wow64 case, the child will be waiting  on h64parent again.
	// set it, and then wait for h64child. This will mean the child has
	// a stack set up at the right location.
	else {
		SetEvent(h64Parent);
		hArray[0] = h64Child;
		hArray[1] = hProc;

		if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != 
				WAIT_OBJECT_0){

			rc = GetLastError();
			goto error;
		}
		CloseHandle(h64Parent);
		CloseHandle(h64Child);
		h64Parent = h64Child = NULL;
	}

	//
	// Wait for the child to start and init itself.
	// The timeout is so that we don't wait too long
	//
	hArray[0] = __hforkchild;
	hArray[1] = hProc;

	if (WaitForMultipleObjects(2,hArray,FALSE,FORK_TIMEOUT) != WAIT_OBJECT_0){

		int err = GetLastError(); // For debugging purposes
		dprintf("wait failed err %d\n",err);
		goto error;
	}

	// Stop the child again and copy the stack and heap
	//
	SuspendThread(hThread);

	if (!SetThreadPriority(hThread,priority) ) {
		priority =GetLastError();
	}

	// stack
	stacksize = (char*)__fork_stack_begin - (char*)__fork_stack_end;
	if (!WriteProcessMemory(hProc,(char *)__fork_stack_end,
				(char *)__fork_stack_end,
				(u_long)stacksize,
				&rc)){
		goto error;
	}
	//
	// copy heap itself
	if (!WriteProcessMemory(hProc, (void*)__heap_base,(void*)__heap_base, 
				(DWORD)((char*)__heap_top-(char*)__heap_base),
				&rc)){
		goto error;
	}

	rc = fork_copy_user_mem(hProc);

	if(rc) {
		goto error;
	}

	// Release the child.
	SetEvent(__hforkparent);
	rc = ResumeThread(hThread);

	__forked=0;
	dprintf("forked process %d\n",pi.dwProcessId);
	start_sigchild_thread(hProc,pi.dwProcessId);
	close_copied_fds();

	CloseHandle(hThread);
	//
	// return process id to parent.
	return pi.dwProcessId;

error:
	__forked=0;
	SetEvent(__hforkparent);
	ResumeThread(hThread);
	CloseHandle(hProc);
	CloseHandle(hThread);
	if (h64Parent) {
		SetEvent(h64Parent); // don't let child block forever
		CloseHandle(h64Parent);
	}
	if (h64Child)
		CloseHandle(h64Child);
	return -1;
}
Esempio n. 3
0
File: sehll.c Progetto: simon-eh/hw9
void run_cmd(char * const *args, int *cmds, int numcmds) {
    int s_stdin = dup(STDIN_FILENO);
    int s_stdout = dup(STDOUT_FILENO);
    if(numcmds <= 0) {
	return;
    }

    int fds[2*(numcmds-1)];
    for(int i=0; i<numcmds-1; i++) {
	if(pipe(fds + i*2) < 0) {
	    fprintf(stderr, "Pipe error on line %d", __LINE__);
	    perror("");
	    restore_fds(s_stdin, s_stdout);
	    return;
	}
    }
    int childpid;
    for(int i=0; i<numcmds; i++) {
	int index = cmds[i];

	childpid = fork();
	if(childpid == 0) {

	    if(!fix_fds()) {
		return;
	    }

	    // child proc
	    //fprintf(stderr, "%d\n", i);
	    if(i < numcmds-1) {
		//fprintf(stderr, "Duping stdout for cmd %s\n", *(args + index));
		if(dup2(fds[i*2 + 1], 1) < 0) {
		    fprintf(stderr, "Dup2 error on line %d", __LINE__);
		    perror("");
		    // restore_fds(s_stdin, s_stdout);
		    exit(0);
		}
	    }
	    if(i > 0) {
		//fprintf(stderr, "Duping stdin for cmd %s\n", *(args + index));
		if(dup2(fds[i*2-2], 0) < 0) {
		    fprintf(stderr, "Dup2 error on line %d\n", __LINE__);
		    fprintf(stderr, "File descriptor: %d", fds[i*2-2]);
		    perror("");
		    // restore_fds(s_stdin, s_stdout);
		    // exit(0);
		    kill(getppid(), SIGINT);
		    exit(0);
		}
	    }
	    for(int j=0; j<numcmds*2-2; j++) {
		close(fds[j]);
	    }
	    //fprintf(stderr, "Exec cmd %s\n", *(args + index));
	    execvp(*(args + index), args + index);
	    exit(0);
	}
	else if(childpid < 0) {
	    fprintf(stderr, "Fork Error on line %d", __LINE__);
	    perror("");
	    // restore_fds(s_stdin, s_stdout);
	    exit(0);
	}
	else if(!background) {
	    children[nchildren++] = childpid;
	}
    }
    for(int i=0; i<2*(numcmds-1); i++) {
	close(fds[i]);
    }
    int status;
    if(!background) {
	for(int i=0; i<numcmds; i++) {
	    wait(&status);
	    nchildren--;
	}
    }
    else {
	int pid;
	while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
	    fprintf(stderr, "PID %d exited.\n", pid);
	}
    }
    restore_fds(s_stdin, s_stdout);
}