Exemple #1
0
char *str_uri_path(char *str_request) {
	char *str_return = NULL;
	
	// if the request is not long enough to have a URI then abort
	ERROR_CHECK(strlen(str_request) >= 5, "request too short to parse;");
	
	// find uri start character
	char *ptr_uri;
	if (strncmp(str_request, "GET ", 4) == 0 ) {
		ptr_uri = str_request + 4;
	} else if (strncmp(str_request, "HEAD ", 5) == 0 || strncmp(str_request, "POST ", 5) == 0) {
		ptr_uri = str_request + 5;
	} else {
		ERROR("unknown request type");
	}
	// return just the Request-URI
	char *ptr_uri_end = strstr(ptr_uri, " ");
	int int_uri_len = (int)(ptr_uri_end - ptr_uri);
	
	DEBUG("int_uri_len: %i", int_uri_len);
	
	ERROR_SALLOC(str_return, int_uri_len + 1);
	memcpy(str_return, ptr_uri, int_uri_len);
	str_return[int_uri_len] = '\0';
	return str_return;
error:
	SFREE(str_return);
	return NULL;
}
Exemple #2
0
char *aes_decrypt(char *str_ciphertext_base64, int *ptr_int_ciphertext_length) {
	DEFINE_VAR_ALL(str_ciphertext);
	char *str_return = NULL;
	
	//base64
	//printf("test1>%d<\n", *ciphertext_len);
	str_ciphertext = b64decode(str_ciphertext_base64, ptr_int_ciphertext_length);
	//printf("str_ciphertext: %s\n", str_ciphertext);
	
	//initialize
	set_aes_key_iv();
	AES_KEY AESkey;
	ERROR_SALLOC(str_return, *ptr_int_ciphertext_length + 1);
    memset(str_return, 0, *ptr_int_ciphertext_length);
	//printf("test2>%d<\n", *ptr_int_ciphertext_length);
	//encrypt
	AES_set_decrypt_key((const unsigned char *) str_global_aes_key, 256, &AESkey);
	
	AES_cbc_encrypt((const unsigned char *)str_ciphertext, (unsigned char *)str_return,
		*ptr_int_ciphertext_length, &AESkey, (unsigned char *)str_global_aes_iv, AES_DECRYPT);
	
	//aes_crypt_cbc(&aes, AES_DECRYPT, *ciphertext_len, (unsigned char *)iv, (unsigned char *)str_ciphertext, (unsigned char *)str_return);
	//printf("test3>%d<\n", *ciphertext_len);
	SFREE_ALL();
	
	return str_return;
error:
	SFREE_ALL();
	SFREE_PWORD(str_return);
	return NULL;
}
Exemple #3
0
char *str_cookie(char *str_request, char *str_cookie_name) {
	char *str_return = NULL;
	DEFINE_VAR_ALL(str_full_cookie);
	
	DEBUG("str_cookie 1");
	
	ERROR_CAT_CSTR(str_full_cookie, str_cookie_name, "=");
	
	DEBUG("str_cookie 2");
	
	// find the cookie
	char *ptr_cookie = strstr(str_request, "Cookie:");
	WARN_CHECK(ptr_cookie != NULL, "no cookie found");
	ptr_cookie = strstr(ptr_cookie, str_full_cookie);
	WARN_CHECK(ptr_cookie != NULL, "no cookie found");
	ptr_cookie = ptr_cookie + strlen(str_full_cookie); // advance cursor past "postage="
	SFREE(str_full_cookie);
	
	DEBUG("str_cookie 3");
	
	// get cookie length
	char *ptr_cookie_end_return = strstr(ptr_cookie, "\r\n");
	char *ptr_cookie_end_semi = strstr(ptr_cookie, ";");
	int int_cookie_len;
	
	DEBUG("str_cookie 4");
	
	if (ptr_cookie_end_return == NULL && ptr_cookie_end_semi == NULL) {
		int_cookie_len = strlen(ptr_cookie);
	} else if (ptr_cookie_end_return != NULL && ptr_cookie_end_semi == NULL) {
		int_cookie_len = ptr_cookie_end_return - ptr_cookie;
	} else if (ptr_cookie_end_return == NULL && ptr_cookie_end_semi != NULL) {
		int_cookie_len = ptr_cookie_end_semi - ptr_cookie;
	} else {
		int_cookie_len = (ptr_cookie_end_return < ptr_cookie_end_semi) ? ptr_cookie_end_return - ptr_cookie : ptr_cookie_end_semi - ptr_cookie;
	}
	
	DEBUG("str_cookie 5");
	
	// return just the postage cookie
	ERROR_SALLOC(str_return, int_cookie_len + 1);
	memcpy(str_return, ptr_cookie, int_cookie_len);
	str_return[int_cookie_len] = '\0';
	
	DEBUG("str_cookie 6");
	
	SFREE_PWORD_ALL();
	return str_return;
error:
	SFREE_PWORD_ALL();
	SFREE_PWORD(str_return);
	return NULL;
}
Exemple #4
0
char *aes_encrypt(char *str_plaintext, int *ptr_int_plaintext_length) {
	DEFINE_VAR_ALL(str_output);
	char *str_return = NULL;
	
	//initialize
	set_aes_key_iv();
	AES_KEY AESkey;
	//int int_new_length = *ptr_int_plaintext_length;
	*ptr_int_plaintext_length = ((*ptr_int_plaintext_length + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
	int int_aes_length = *ptr_int_plaintext_length;
	//*ptr_int_plaintext_length = (*ptr_int_plaintext_length) - ((*ptr_int_plaintext_length) % 16) + 16;
	ERROR_SALLOC(str_output, int_aes_length + 1);
    memset(str_output, 0, int_aes_length);
	
	AES_set_encrypt_key((const unsigned char *) str_global_aes_key, 256, &AESkey);
	
	AES_cbc_encrypt((const unsigned char *)str_plaintext, (unsigned char *)str_output,
		int_aes_length, &AESkey, (unsigned char *)str_global_aes_iv, AES_ENCRYPT);
	/*
	AES_cbc_encrypt((const unsigned char *)str_plaintext, (unsigned char *)str_output,
		int_new_length, &AESkey, (unsigned char *)str_global_aes_iv, AES_ENCRYPT);
	*/
	
	//int int_original_length = int_new_length;
	//int_new_length = (int_new_length & 0xFFFFFFF0) + ((int_new_length & 0x0F) ? 16 : 0);
	//*(str_output + int_new_length) = (int_new_length - int_original_length);
	
	//printf("str_output: %s\n", str_output);
	
	//encrypt
	//aes_setkey_enc(&aes, (unsigned char *)key, 256);
	//aes_crypt_cbc(&aes, AES_ENCRYPT, *plaintext_len, (unsigned char *)iv, (unsigned char *)plaintext, (unsigned char *)str_output);
	
	//base64
	str_return = b64encode(str_output, ptr_int_plaintext_length);
	
	SFREE_ALL();
	
	return str_return;
error:
	SFREE_ALL();
	
	SFREE_PWORD(str_return);
	return NULL;
}
Exemple #5
0
char *request_header(char *str_request, char *str_name) {
	char *str_return = NULL;
	
	DEFINE_VAR_ALL(str_full_name);
	ERROR_CAT_CSTR(str_full_name, str_name, ": ");
	// find the cookie
	char *ptr_header = strstr(str_request, str_full_name);
	WARN_CHECK(ptr_header != NULL, "no %s found", str_name);
	
	ptr_header = ptr_header + strlen(str_full_name); // advance cursor past "referer: "
	
	// get cookie length
	char *ptr_header_end_return = strstr(ptr_header, "\r\n");
	int int_header_len;
	if (ptr_header_end_return == NULL) {
		ptr_header_end_return = strstr(ptr_header, "\r");
		if (ptr_header_end_return == NULL) {
			ptr_header_end_return = strstr(ptr_header, "\n");
			if (ptr_header_end_return == NULL) {
				int_header_len = strlen(ptr_header);
			} else {
				int_header_len = ptr_header_end_return - ptr_header;
			}
		} else {
			int_header_len = ptr_header_end_return - ptr_header;
		}
	} else {
		int_header_len = ptr_header_end_return - ptr_header;
	}
	
	// return just the host
	ERROR_SALLOC(str_return, int_header_len + 1);
	memcpy(str_return, ptr_header, int_header_len);
	str_return[int_header_len] = '\0';
	
	SFREE_ALL();
	return str_return;
error:
	
	SFREE_ALL();
	SFREE(str_return);
	return NULL;
}
Exemple #6
0
//take a file list and convert it into json
//int_remove_length is the number of characters to remove from each line
//useful if your list is like:
//  /path/to/file1
//  /path/to/file2
//and you want it like:
//  file1
//  file2
char *file_list_to_json (char *str_content, int int_remove_length) {
	char *str_return = NULL;
	char *str_temp = NULL;
	char *str_temp_json = NULL;
	ERROR_NORESPONSE("int_remove_length: %d", int_remove_length);
	ERROR_CAT_CSTR(str_return, "");
	char *ptr_content = str_content + int_remove_length + 1; // + 1 means remove /
	if (*(ptr_content - 1) == '\n') { //if we are at a newline,
		//then the first line must be the full length to remove, so skip that line
		ptr_content = ptr_content + int_remove_length + 1; // + 1 means remove \n
	}
	int int_length;
	int int_done = 1;
	char *ptr_end_content = str_content + strlen(str_content);
	while (int_done > 0) {
		if (ptr_content <= ptr_end_content && strchr(ptr_content, '\n') != 0) {
			int_length = (strchr(ptr_content, '\n') - ptr_content);
			if (int_length > 0) {
				ERROR_SALLOC(str_temp, int_length + 1);
				memcpy(str_temp, ptr_content, int_length);
				str_temp[int_length] = 0;
				str_temp_json = jsonify(str_temp);
				SFREE(str_temp);
				if (strlen(str_return) > 0) {
					ERROR_CAT_APPEND(str_return, ",", str_temp_json);
				} else {
					ERROR_CAT_APPEND(str_return, str_temp_json);
				}
				ERROR_NORESPONSE(">%s|%s|%s<", str_return, str_temp_json, ptr_content);
				SFREE(str_temp_json);
			}
			ptr_content = strchr(ptr_content, '\n') + int_remove_length + 1 + 1; // + 1 means remove \n // + 1 means remove /
		} else {
			int_done = 0;
		}
	}
	return str_return;
error:
	SFREE(str_temp);
	SFREE(str_temp_json);
	SFREE(str_return);
	return NULL;
}
Exemple #7
0
// Check path environment variable for a program
char *where_is_program(char *str_program_name) {
	DEFINE_VAR_ALL(str_PATH, str_PATH2);
	char *str_return = NULL;
	
	ERROR_CAT_CSTR(str_PATH, getenv("PATH"));
	char *ptr_PATH = str_PATH;
	char *ptr_PATH_end = str_PATH + strlen(str_PATH);
	int int_next_colon;
	
	while (ptr_PATH < ptr_PATH_end) {
		//DEBUG("%s", ptr_PATH);
		int_next_colon = strcspn(ptr_PATH, ":");
		
		ERROR_SALLOC(str_PATH2, int_next_colon + 2);
		memcpy(str_PATH2, ptr_PATH, int_next_colon);
		str_PATH2[int_next_colon] = '/';
		str_PATH2[int_next_colon + 1] = '\0';
		//DEBUG("%s", str_ptr_PATH);
		str_return = canonical(str_PATH2, str_program_name, "read_dir_or_file"); //"read_file");
		SFREE(str_PATH2);
		if (str_return != NULL) {
			SFREE_ALL();
			return str_return;
		}
		
		//DEBUG("%i", int_next_colon);
		ptr_PATH += int_next_colon + 1;
	}
	
	WARN("Could not find program: %s", str_program_name);
	//ERROR("Could not find program: %s", str_program_name);
error:
	SFREE_ALL();
	SFREE(str_return);
	return NULL;
}
Exemple #8
0
sun_upload *get_sun_upload(char *str_request, int int_request_length) {
	sun_upload *sun_return = NULL;
	DEFINE_VAR_ALL(str_boundary, str_full_boundary, str_name, str_file_content);
	
	////GET BOUNDARY
	//get boundary length
	char *ptr_boundary = strstr(str_request, "Content-Type: multipart/form-data; boundary=") + 44;
	ERROR_CHECK(ptr_boundary != NULL, "No Boundary");
	int int_boundary_carriage = strchr(ptr_boundary, '\r') - ptr_boundary;
	int int_boundary_newline = strchr(ptr_boundary, '\n') - ptr_boundary;
	int int_boundary_length = int_boundary_carriage < int_boundary_newline ? int_boundary_carriage : int_boundary_newline;
	
	//copy boundary
	ERROR_SALLOC(str_boundary, int_boundary_length + 1);
	memcpy(str_boundary, ptr_boundary, int_boundary_length);
	str_boundary[int_boundary_length] = '\0';
	ERROR_CAT_CSTR(str_full_boundary, "--", str_boundary);
	DEBUG(">BOUNDARY|%s<", str_boundary);
	SFREE(str_boundary);
	
	////GET FILE NAME
	//get file name
	char *ptr_name = bstrstr(str_request, int_request_length, "Content-Disposition: form-data; name=\"file_name\"", 48);
	ERROR_CHECK(ptr_name != NULL, "No Content Disposition for File Name, (Maybe there is no file name?)");
	ptr_name = ptr_name + 48;
	
	char *ptr_name_dos  = strstr(ptr_name, "\r\n\r\n");
	char *ptr_name_unix = strstr(ptr_name, "\n\n");
	char *ptr_name_mac  = strstr(ptr_name, "\r\r");
	ptr_name = ptr_name_dos > ptr_name_unix ? ptr_name_dos + 4 :
		ptr_name_dos > ptr_name_mac ? ptr_name_dos + 4 :
		ptr_name_unix > ptr_name_mac ? ptr_name_unix + 2 :
		ptr_name_mac + 2;
	
	//copy file name
	int int_name_carriage = strchr(ptr_name, '\r') - ptr_name;
	int int_name_newline  = strchr(ptr_name, '\n') - ptr_name;
	int int_name_boundary = strstr(ptr_name, str_full_boundary) - ptr_name;
	int int_name_length   =
		int_name_carriage < int_name_newline ? int_name_carriage :
		int_name_carriage < int_name_boundary ? int_name_carriage :
		int_name_boundary < int_name_carriage ? int_name_boundary :
		int_name_boundary;
	ERROR_SALLOC(str_name, int_name_length + 1);
	memcpy(str_name, ptr_name, int_name_length);
	str_name[int_name_length] = '\0';
	DEBUG(">FILE NAME|%s<", str_name);
	
	////GET FILE
	//get file content
	DEBUG("str_request: %20.20s", str_request);
	
	char *ptr_file_content = bstrstr(str_request, int_request_length, "Content-Disposition: form-data; name=\"file_content\"", 51);
	ERROR_CHECK(ptr_file_content != NULL, "No Content Disposition for File Content, (Maybe there is no file content?)");
	ptr_file_content = ptr_file_content + 51;
	
	DEBUG("str_request + int_request_length d: %d", str_request + int_request_length);
	DEBUG("ptr_file_content: %20.20s", ptr_file_content);
	
	char *ptr_file_content_dos  = strstr(ptr_file_content, "\r\n\r\n");
	char *ptr_file_content_unix = strstr(ptr_file_content, "\n\n");
	char *ptr_file_content_mac  = strstr(ptr_file_content, "\r\r");
	ptr_file_content = ptr_file_content_dos > ptr_file_content_unix ? ptr_file_content_dos + 4 :
		ptr_file_content_dos > ptr_file_content_mac ? ptr_file_content_dos + 4 :
		ptr_file_content_unix > ptr_file_content_mac ? ptr_file_content_unix + 2 :
		ptr_file_content_mac + 2;
	
	//copy file content
	int int_file_content_length =
		bstrstr(ptr_file_content,
				(str_request + int_request_length) - ptr_file_content,
				str_full_boundary,
				int_boundary_length + 2) -
		ptr_file_content;
	ERROR_SALLOC(str_file_content, int_file_content_length + 1);
	memcpy(str_file_content, ptr_file_content, int_file_content_length);
	str_file_content[int_file_content_length] = '\0';
	DEBUG(">FILE CONTENT|%s<", str_file_content);
	DEBUG(">FILE CONTENT LENGTH|%i<", int_file_content_length);
	
	////RETURN
	ERROR_SALLOC(sun_return, sizeof(sun_upload));
	SFREE(str_full_boundary);
	sun_return->str_name = str_name;
	str_name = NULL;
	sun_return->str_file_content = str_file_content;
	str_file_content = NULL;
	sun_return->int_file_content_length = int_file_content_length;
	
	SFREE_ALL();
	return sun_return;
error:
	SFREE_ALL();
	SFREE(sun_return);
	return NULL;
}
Exemple #9
0
// safe system execute function
int s_exec(char *str_user_environment, int args, ...) {
	NOTICE("EXEC.C");
	
    // to use: umask(002); // if you plan on creating a file or copying a file then set the default perms.
    //         int int_test = sunny_exec("", "/usr/local/pgsql/bin/pg_ctl", "-D", "/opt/3comets/data", "stop");
    //         int int_test = sunny_exec("", "/bin/echo", "test1");
    //         printf( "%i: ", int_test ); // 1 = error, -1 = parent
	
	// #### secure execute of programs ###
	pid_t pid;
	int status;
	pid_t ret;
	
	// set errno to "Success" in case caller functions have errors in them
	errno = 0;
  
	// fork causes the existing program to split into two identical processes.
	pid = fork();
	ERROR_CHECK(pid != -1, "Fork error.");
	if (pid != 0) {
        // pid = -1 means wait for all children, 
        while((ret = waitpid(-1, &status, WUNTRACED)) > 0) {
			DEBUG("ret: %d", ret);
			if (errno != EINTR) {
				break;
			}
        }
		/*while ((ret = waitpid(pid, &status, 0)) == -1) {
			DEBUG("ret: %d", ret);
			if (errno != EINTR) {
				break;
			}
		}*/
		// keep this code in case you have problems
		if (ret != -1 && errno != 0 && (!WIFEXITED(status) || !WEXITSTATUS(status)) && errno != 10) {
			ERROR("Child has unexpected status. errno: %d (%s)", errno, strerror(errno));
		}
		
		INFO("EXEC.C END");
		DEBUG("TEST1>%d|%d<", status, WEXITSTATUS(status));
		return WEXITSTATUS(status);
error:
		DEBUG("TEST2");
		return -1;
	} else {
		DEBUG("global_csock: %i", global_csock);
		if (global_csock > -1) {
			DEBUG("close(global_csock): %i", global_csock);
			close(global_csock);
		}
		// the first item is our program executable
		// assemble a nice array of all our args with a null element at the end
		va_list ap;
		va_list bp;
		int     i;
		int     len = 0;
		// arr_args[0] is the program path
		// arr_args[1] is the program name
		// arr_args[2-args] are the arguments to the program
		int lengths[args+1];
		int prog_len;    // put args[0] len here
		int prog_name_len = 0;
	
		// allocate prog and an array large enough for everything
		va_start(ap, args);
		va_copy(bp, ap);  // powerpc can't do two va_starts. use va_copy instead.
	
		// fill prog
		char *prog = va_arg( ap, char *);
		prog_len = strlen(prog) + 1;
	
		// get program name length from path
		for (i = 0; i < prog_len; i = i + 1) {
			if ( strncmp( "/", prog + i, 1 ) == 0) {
				prog_name_len = prog_len - (i+1);
			}
		}
		ERROR_CHECK(prog_name_len > 0, "First arg must be a complete path, e.g. /bin/touch. You tried '%s'.", prog);
		lengths[0] = prog_name_len;
		
		// get the rest of the lengths
		for (i = 1; i < args; i = i + 1) {
			len = strlen(va_arg (ap, char *)) + 1;
			lengths[i] = len;
		}
		va_end( ap );
		
		// set up arr_args
		char  * arr_args[args+1];
		for (i = 0; i < args; i = i + 1) {
			ERROR_SALLOC(arr_args[i], lengths[i]);
		}
		
		// get prog name from path
		char  *prog_name = (char *)((prog + prog_len) - prog_name_len);
		
		len = strlen(prog_name) + 1;
		memcpy( arr_args[0], prog_name, len-1 );
		arr_args[0][len-1] = '\0';
		
		// we don't need the path again so run va_arg once to pass it.
		va_arg(bp, char *);
		for (i = 1; i < args; i = i + 1) {
			memcpy(arr_args[i], va_arg (bp, char *), lengths[i] - 1);
			arr_args[i][lengths[i]-1] = '\0';
		}
		va_end(bp);
		
		// add a null element to the array
		arr_args[args] = (char*)salloc(1);
		arr_args[args] = 0; // WRONG: arr_args[args][0] = '\0';
		
		char *pathbuf;
		size_t n;
		
		if (clearenv() != 0) {
			ERROR_NORESPONSE("Command clearenv failed. Exiting.");
			exit(1);
		}
		
		n = confstr(_CS_PATH, NULL, 0);
		if (n == 0) {
			ERROR_NORESPONSE("Command confstr not available. Exiting.");
			exit(1);
		}
		
		if ((pathbuf = salloc(n)) == NULL) {
			ERROR_NORESPONSE("Command salloc errored. Exiting.");
			exit(1);
		}
		
		if (confstr(_CS_PATH, pathbuf, n) == 0) {
			ERROR_NORESPONSE("Command confstr errored. Exiting.");
			exit(1);
		}
		
		if (setenv("PATH", pathbuf, 1) == -1) {
			ERROR_NORESPONSE("Command setenv PATH errored. Exiting.");
			exit(1);
		}
		
		SFREE(pathbuf);//void, no test
		
		if (setenv("IFS", " \t\n", 1) == -1) {
			ERROR_NORESPONSE("Command setenv IFS errored. Exiting.");
			exit(1);
		}
		
		// environment is sanitized
		//https://www.securecoding.cert.org/confluence/display/seccode/ENV03-C.+Sanitize+the+environment+when+invoking+external+programs
		
		char *ptr_user_environment = str_user_environment;
		char *ptr_end_user_environment = str_user_environment + strlen(str_user_environment);
		char str_name[255];
		char str_value[255];
		int int_length;
		while (ptr_user_environment < ptr_end_user_environment) {
			DEBUG(">%s<", ptr_user_environment);
			
			//get name
			//search for next comma, colon, or null byte
			int_length = strcspn(ptr_user_environment, "&=");
			memcpy(str_name, ptr_user_environment, int_length);
			str_name[int_length] = '\0';
			ptr_user_environment = ptr_user_environment + int_length + 1;
			
			//get value
			//search for next comma, colon, or null byte
			int_length = strcspn(ptr_user_environment, "&=");
			memcpy(str_value, ptr_user_environment, int_length);
			str_value[int_length] = '\0';
			ptr_user_environment = ptr_user_environment + int_length + 1;
			
			//use name and value
			DEBUG(">%s|%s<", str_name, str_value);
			
			char *temp = uri_to_cstr(str_value, strlen(str_value));
			setenv(str_name, temp, 1);
			SFREE(temp);
		}
		
		DEBUG(">%s|%i<", prog, args);
		for (i = 0; i < args; i += 1) {
			DEBUG(">%i|%s<", i, arr_args[i]);
		}
		int int_status = execv( prog, arr_args );
		
		ptr_user_environment = str_user_environment;
		while (ptr_user_environment < ptr_end_user_environment) {
			DEBUG(">%s<", ptr_user_environment);
			
			//get name
			//search for next comma, colon, or null byte
			int_length = strcspn(ptr_user_environment, "&=");
			memcpy(str_name, ptr_user_environment, int_length);
			str_name[int_length] = '\0';
			ptr_user_environment = ptr_user_environment + int_length + 1;
			
			//get value
			//search for next comma, colon, or null byte
			int_length = strcspn(ptr_user_environment, "&=");
			memcpy(str_value, ptr_user_environment, int_length);
			str_value[int_length] = '\0';
			ptr_user_environment = ptr_user_environment + int_length + 1;
			
			//use name and value
			DEBUG(">%s|%s<", str_name, str_value);
			
			unsetenv(str_name);
		}
		
		//DEBUG("%s %s %s %s %s", prog, arr_args[0], arr_args[1], arr_args[2], arr_args[3]);
		if (int_status == -1) {
			ERROR_NORESPONSE("Error executing '%s' %d (%s)\n", prog, errno, strerror(errno));
			for (i = 0; i < args; i = i + 1) {
				SFREE(arr_args[i]);
			}
			SFREE(arr_args[args]);
			_exit(127);
		}
		ERROR_NORESPONSE("Error in sunny_exec: '%s'\n", prog);
		for (i = 0; i < args; i = i + 1) {
			SFREE(arr_args[i]);
		}
		SFREE(arr_args[args]);
		// This process terminates. The calling (parent) process will now continue.
		//   we only return a value if there was an error. (errno will be set)
		// the following line won't execute unless there is an error.
		_exit(127);
	}
	
	DEBUG("TEST3");
	return -1;
}