예제 #1
0
char *buffer_append(buffer *b, char *bytes, unsigned int size)
{
	if (!b || !bytes) 
		return NULL;

	char *space = buffer_makespace(b, size);
	if (!space)
		return NULL;
	memcpy(space, bytes, size);
	buffer_usespace(b, size);

	return space;
}
예제 #2
0
proc *process_run(char executable[], char *args[], int timeout)
{
	proc *retval = NULL;
	char *text;
	int status;
	tl_stream stdout_p;
	tl_stream stdin_p;
	SECURITY_ATTRIBUTES saAttr; 
	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	BOOL createproc_success = FALSE; 
	BOOL timedout = FALSE; 
	TCHAR *commandline = NULL;

	proc *p = process_new();

	if (p == NULL)
		return NULL;

	/* Make sure pipe handles are inherited */
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 
	
	p->causeofdeath = PROC_PIPECREATE;

	DEBUG(("making pipes \n"));
	/* Child's Stdout */
	if ( ! CreatePipe(&stdout_p.read, &stdout_p.write, &saAttr, 1) ) 
	{
		printlasterror();
		RETURN(p);
	}
	DEBUG(("stdout done \n"));
	
	/* read handle to the pipe for STDOUT is not inherited */
	if ( ! SetHandleInformation(stdout_p.read, HANDLE_FLAG_INHERIT, 0) )
	{
		printlasterror();
		RETURN(p); 
	}
	DEBUG(("stdout noinherit \n"));
	
	/* a pipe for the child process's STDIN */
	if ( ! CreatePipe(&stdin_p.read, &stdin_p.write, &saAttr, 0) ) 
	{
		printlasterror();
		RETURN(p); 
	}
	DEBUG(("stdin done \n"));
	
	/*  write handle to the pipe for STDIN not inherited */
	if ( ! SetHandleInformation(stdin_p.read, HANDLE_FLAG_INHERIT, 0) )
	{
		printlasterror();
		RETURN(p); 
	}
	DEBUG(("pipes done \n"));
	
	
	p->causeofdeath = PROC_START;

	ZeroMemory( &si, sizeof(STARTUPINFO) );
	ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
	
	si.cb = sizeof(STARTUPINFO); 
	si.hStdError = stdout_p.write;
	si.hStdOutput = stdout_p.write;
	/*
	  Rather than use the stdin pipe, which would be
       		  si.hStdInput = stdin_p.read;
	  Pass on talon's own standard input to the child process
	  This helps with programs like xcopy which demand that
	  they are attached to a console and not just any type of
	  input file.
	 */
	si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
	si.dwFlags |= STARTF_USESTDHANDLES;

	
	DEBUG(("pre commandline \n"));
	/* create the commandline string */
	int len = 0;
	int i = 0;
	while (args[i] != NULL)
	{
		len += strlen(args[i++]) + 1;
	}
	len+=2;

	commandline = malloc(len*2);
	if (! commandline) 
		RETURN(p);
	commandline[0] = '\0';

	i = 0;
	while (args[i] != NULL)
	{
		strcat(commandline, args[i]);
		strcat(commandline, " ");
		i++;
	}


	/* Get the read thread ready to go before creating
	 * the process.
	 */
	ReadOpQ *ropq  = malloc(sizeof(ReadOpQ));

	ropq->first=NULL;
	ropq->last=NULL;
	ropq->semaphore = CreateSemaphore(NULL, 0, 1, NULL);
	DEBUG(("Creating read thread. \n"));

	DWORD readpipe_threadid;
	HANDLE h_readpipe_thread = CreateThread(NULL, 8192, (LPTHREAD_START_ROUTINE) readpipe_thread, (void*)ropq, 0, &readpipe_threadid);

	/* ready to run the process */
 
	DEBUG(("process commandline:\n%s \n", commandline));
	DEBUG(("\n"));
	createproc_success = CreateProcess(executable, 
	   commandline,     // command line 
	   NULL,          // process security attributes 
	   NULL,          // primary thread security attributes 
	   TRUE,          // handles are inherited 
	   0,             // creation flags 
	   NULL,          // use parent's environment 
	   NULL,          // use parent's current directory 
	   &si,  // STARTUPINFO pointer 
	   &pi);  // receives PROCESS_INFORMATION 

	if (! createproc_success)
	{
		DEBUG(("Createprocess failed. \n"));
		p->causeofdeath = PROC_SOMEODDDEATH;
		RETURN(p);
	}

	int have_status = 0;


	DEBUG(("Closing Handles. \n"));
	if (!CloseHandle(stdout_p.write)) 
		RETURN(p);
	if (!CloseHandle(stdin_p.read)) 
		RETURN(p);

	DEBUG(("Closed Handles. \n"));


	static int id=0;
	do
	{
		char *space = buffer_makespace(p->output, READSIZE);

		DWORD waitres;
		ReadOp *iopipe_op = malloc(sizeof(ReadOp));
		iopipe_op->semaphore = CreateSemaphore(NULL, 0, 1, NULL);
		iopipe_op->thread =  h_readpipe_thread;
		iopipe_op->timeout = timeout;
		iopipe_op->file = stdout_p.read;
		iopipe_op->space = malloc(READSIZE);
		iopipe_op->id = id++;
		iopipe_op->nbytes = READSIZE;
		iopipe_op->next = NULL;

		if (!ropq->first)
		{
			ropq->first = iopipe_op;
			ropq->last = iopipe_op;
		} else {
			ropq->last->next = iopipe_op;
			ropq->last = iopipe_op;
		}

		ReleaseSemaphore(ropq->semaphore, 1, NULL);

		DEBUG(("waiting for read %d\n", timeout));
		waitres = WaitForSingleObject(iopipe_op->semaphore, timeout);
		DEBUG(("read wait finished result= %d\n", waitres));

		if (waitres != WAIT_OBJECT_0)
		{
			DEBUG(("timeout \n"));
			timedout = TRUE;
			break;
		}
		else
		{
			DEBUG(("read signalled: nbytes: %d \n", iopipe_op->nbytes));
			if (iopipe_op->nbytes <= 0)
			{
				break;
			}
			memcpy(space, iopipe_op->space, iopipe_op->nbytes);	
			buffer_usespace(p->output, iopipe_op->nbytes);	
			DEBUG(("buffer took on nbytes: %d \n", iopipe_op->nbytes));
		}
	}
	while (1);

	if (timedout == FALSE) 
	{
		DEBUG(("Wait for process exit\n"));
		// Wait until child process exits.
		WaitForSingleObject(pi.hProcess, INFINITE);
		DEBUG(("Process exited\n"));

		DWORD exitcode;

		if (GetExitCodeProcess(pi.hProcess, &exitcode))
		{
			p->causeofdeath = PROC_NORMALDEATH;
			p->returncode = exitcode;
			DEBUG(("process exited normally = %d:\n", p->returncode));
			RETURN(p);	
		} else {
			p->causeofdeath = PROC_SOMEODDDEATH;
			p->returncode = 128;
			DEBUG(("process terminated \n"));
			RETURN(p);	
		}
	} else {
		TerminateProcess(pi.hProcess,1);
		p->causeofdeath = PROC_TIMEOUTDEATH;
		p->returncode = 128;
		DEBUG(("process timedout \n"));
		RETURN(p);	
	}

	/* Clean up the read operation queue 
	ReadOp *r = ropq.first;
	do
	{
		CloseHandle(r->semaphore);
		free(r->space);
		free(r);
		r = r->next;
	} while (r != NULL); */

	CLEANUP();
	if (retval == NULL)
	{
		if (p)
			process_free(&p);
	}
	if (commandline)
		free(commandline);
	
	return retval;
}