예제 #1
0
void closeFile(void) {
	/*
	**  Closes the GCM for when we're done...
	*/
	
	verbosePrint("Closing GCM...");
	fclose(gcmFile);
}
예제 #2
0
void extractFile(GCMFileEntryStruct *e, char *dest) {
	/*
	**  extract files from source (in GCM) to dest (in the local filesystem)
	*/
	
	char vstring[1024] = "Extracting ";
	strcat(vstring, e->filename);
	strcat(vstring, " from GCM to ");
	strcat(vstring, dest);
	verbosePrint(vstring);
	
	//check to see if the file was actually found...
	if (!e) {
		printf("File not found (%s)\n", e->filename);
		return;
	}
	
	//this way is fast, but uses up wayyyyyy too much memory.
	//fetch the data
	/*GCMFetchDataForFileEntry(gcmFile, e);
	
	WriteDataToFile(e->data, e->length, dest);
	
	free(e->data);*/
	
	//this thing is wayyyyyyyyy too slow:
	/*FILE *ofile = NULL;
	if (!(ofile = fopen(dest, "w+"))) {
		perror(dest);
		exit(1);
	}
	
	fseek(gcmFile, e->offset, SEEK_SET);
	
	while (ftell(gcmFile) < (e->offset + e->length)) {
		fputc(fgetc(gcmFile), ofile);
	}
	
	fclose(ofile);*/
	
	//this uses buffered reads to copy data in chunks...
	FILE *ofile = NULL;
	if (!(ofile = fopen(dest, "w+"))) {
		perror(dest);
		exit(1);
	}
	
	fseek(gcmFile, e->offset, SEEK_SET);
	
	if (CopyData(gcmFile, ofile, e->length) != e->length) {
		printf("ERROR COPYING DATA!\n");
	}
	
	fclose(ofile);
}
예제 #3
0
void injectApploader(char *sourcePath) {
	/*
	**  this doesn't work, yet... requires some serious shifting of other data...
	*/
	
	verbosePrint("Injecting the apploader...");
	
	//first, load the file into memory...
	
	u32 length = GetFilesizeFromPath(sourcePath);
	char *data = (char*)malloc(length);
	
	if (ReadDataFromFile(sourcePath, data) != length) {
		printf("An error occurred reading the file (%s)", sourcePath);
		free(data);
		return;
	}
	
	free(data);
}
예제 #4
0
void extractBootDol(char *path) {
	/*
	**  extracts the boot DOL from the GCM and saves it to path...
	*/
	
	verbosePrint("Extracting the boot DOL...");
	
	if (!path) return;
	
	u32 length = GCMGetBootDolLength(gcmFile);
	char *buf = (char*)malloc(length);
	
	if (GCMGetBootDol(gcmFile, buf) != length) {
		free(buf);
		printf("An error occurred when getting the DOL. (%d)\n", GCMErrno);
		exit(EXIT_FAILURE);
	}
	
	WriteDataToFile(buf, length, path);
}
예제 #5
0
void extractDiskHeaderInfo(char *path) {
	/*
	**  extracts the diskheaderinfo to bi2.bin
	*/
	
	verbosePrint("Extracting the disk header info...");
	
	//get the data...
	char *buf = (char*)malloc(GCM_DISK_HEADER_INFO_LENGTH);
	
	if (GCMGetDiskHeaderInfo(gcmFile, buf) != GCM_SUCCESS) {
		free(buf);
		printf("An error occurred while reading the disk header info (%d)\n", GCMErrno);
		exit(EXIT_FAILURE);
	}
	
	WriteDataToFile(buf, GCM_DISK_HEADER_INFO_LENGTH, path);
	
	free(buf);
}
예제 #6
0
void openFile(char *mode) {
	/*
	**  opens the GCM file with the mode set to mode
	**	if we were to open it for reading AND writing,
	**	it would error out if we didn't have write permission
	*/
	
	verbosePrint("Opening GCM...");
	
	if (!filepath) {
		printUsage();
		exit(1);
	}
	
	if (!(gcmFile = fopen(filepath, mode))) { //open as r+ so we can inject data, too...
		perror(filepath);
		exit(1);
	}
	
}
예제 #7
0
void extractApploader(char *path) {
	/*
	**  extracts the apploader to appldr.bin
	*/
	
	verbosePrint("Extracting the apploader...");
	
	//get the data...
	u32 apploaderLength = GCMGetApploaderSize(gcmFile) + GCM_APPLOADER_CODE_OFFSET;
	char *buf = (char*)malloc(apploaderLength);
	
	if (GCMGetApploader(gcmFile, buf) != GCM_SUCCESS) {
		free(buf);
		printf("An error occurred while reading the apploader (%d)\n", GCMErrno);
		exit(EXIT_FAILURE);
	}
	
	WriteDataToFile(buf, apploaderLength, path);
	
	free(buf);
}
예제 #8
0
void injectDiskHeaderInfo(char *sourcePath) {
	/*
	**  take a diskHeaderInfo (bi2.bin) from sourcePath and inject it into gcmFile.
	*/
	
	verbosePrint("Injecting the disk header info...");
	
	char *buf = (char*)malloc(GetFilesizeFromPath(sourcePath));
	
	if (ReadDataFromFile(buf, sourcePath) != GCM_DISK_HEADER_INFO_LENGTH) {
		free(buf);
		printf("This does not appear to be a diskheaderinfo (%s)\n", sourcePath);
		exit(EXIT_FAILURE);
	}
	
	if (GCMPutDiskHeaderInfo(gcmFile, buf) != GCM_SUCCESS) {
		free(buf);
		printf("An error occurred when writing the disk header info! (%d)\n", GCMErrno);
		exit(EXIT_FAILURE);
	}
	
	free(buf);
	return;
}
예제 #9
0
int main (int argc, char **argv) {
	// start flags declarations...
	
	gDataOffset = 0; //globally declared in GCMutils.h; Must be initialized before use...
	int hexFlag = 0;
	
	//for extracting:
	char *extractFileFrom = NULL;
	char *extractFileTo = NULL;
	
	char *fsReplacePath = NULL;
	
	verboseFlag = 0;
	
	int showInfoFlag = 1;

	int extractDiskHeaderFlag = 0;
	char *extractDiskHeaderFile = GCM_DISK_HEADER_FILENAME;
	
	int extractDiskHeaderInfoFlag = 0;
	char *extractDiskHeaderInfoFile = GCM_DISK_HEADER_INFO_FILENAME;

	int extractApploaderFlag = 0;
	char *extractApploaderFile = GCM_APPLOADER_FILENAME;
	
	int extractBootDolFlag = 0;
	char *extractBootDolFile = GCM_BOOT_DOL_FILENAME;
	
	int injectDiskHeaderFlag = 0;
	char *injectDiskHeaderFile = GCM_DISK_HEADER_FILENAME;
	
	int injectDiskHeaderInfoFlag = 0;
	char *injectDiskHeaderInfoFile = GCM_DISK_HEADER_INFO_FILENAME;
	
	int injectApploaderFlag = 0;
	char *injectApploaderFile = GCM_APPLOADER_FILENAME;
	
	char *replaceFileLocalPath = NULL;
	char *replaceFileGCMPath = NULL;

	int listFilesFlag = 0;
	listInfoFlag = 0;
	listPathFlag = 0;
	// end flag declarations
	
	//start argument parsing...
	char *currentArg = NULL;

	do {
		currentArg = GET_NEXT_ARG;
		if (!currentArg) {
			//there's no args! uh oh!
			
			//printf("No arguments...\n");
			printUsage();
			exit(0);
		} else if (CHECK_ARG(ARG_VERBOSE)) {
			//turn on verbosity!
			
			verboseFlag++;
			
			verbosePrint("Verbose output ON.");
		} else if (CHECK_ARG(ARG_HELP)) {
			// print extended help
			
			printExtendedUsage();
			exit(0);
		} else if (CHECK_ARG(ARG_INFO)) {
			//they want to see info...
			
			showInfoFlag++;
			
			verbosePrint("Show info flag ON.");
		} else if (CHECK_ARG(ARG_HEX)) {
			//they want hex notation...
			
			hexFlag = 1;
			
			verbosePrint("Hex notation ON.");
			
		} else if (CHECK_ARG(ARG_OFFSET)) {
			//change the data offset
			
			gDataOffset = strtoul(GET_NEXT_ARG, NULL, 0);
			
			char verboseMsg[32] = "";
			sprintf(verboseMsg, "Data offset changed to: %d", gDataOffset);
			
			verbosePrint(verboseMsg);
		} else if (CHECK_ARG(ARG_REPLACE_FILESYSTEM)) {
			// they want to replace the filesystem
			
			fsReplacePath		= GET_NEXT_ARG;
			
			if (!fsReplacePath) {
				printf("Argument error...\n");
				printUsage();
				exit(1);
			}
		} else if (CHECK_ARG(ARG_EXTRACT)) {
			// extract files...
			// usage: -e <path> <destPath>
			
			extractFileFrom		= GET_NEXT_ARG;
			extractFileTo		= GET_NEXT_ARG;
			
			if (!extractFileFrom || !extractFileTo) {
				//argument error... something was omitted...
				printf("Argument error.\n");
				printUsage();
				exit(1);
			}
		} else if (CHECK_ARG(ARG_EXTRACT_DISK_HEADER)) {
			// extract disk header... (to a file called "boot.bin")
			
			extractDiskHeaderFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				// if they're specifying a file...
				
				SKIP_NARG(1); //skip that -f we just looked at...
				extractDiskHeaderFile = GET_NEXT_ARG;
			}
		
		} else if (CHECK_ARG(ARG_EXTRACT_DISK_HEADER_INFO)) {
			// extract disk header info... (to a file called "bi2.bin")
			
			extractDiskHeaderInfoFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				// if they're specifying a file...
				
				SKIP_NARG(1); //skip that -f we just looked at...
				extractDiskHeaderInfoFile = GET_NEXT_ARG;
			}
			
		} else if (CHECK_ARG(ARG_EXTRACT_APPLOADER)) {
			//extract apploader... (to a file called "appldr.bin")
			
			extractApploaderFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				// if they're specifying a file...
				
				SKIP_NARG(1); //skip that -f we just looked at...
				extractApploaderFile = GET_NEXT_ARG;
			}
		} else if (CHECK_ARG(ARG_EXTRACT_BOOT_DOL)) {
			//extract the boot dol...
			
			extractBootDolFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				//if they specify a file...
				
				SKIP_NARG(1); //skip that -f
				extractBootDolFile = GET_NEXT_ARG;
			}
		} else if (CHECK_ARG(ARG_INJECT_DISK_HEADER)) {
			//inject the diskheader
			
			injectDiskHeaderFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				//if they're specifying a file... (otherwise use the default);
				
				SKIP_NARG(1); //skip the -f we just looked at...
				injectDiskHeaderFile = GET_NEXT_ARG;
			}
			
		} else if (CHECK_ARG(ARG_INJECT_DISK_HEADER_INFO)) {
			//inject the diskheaderinfo...
			
			injectDiskHeaderInfoFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				// if they're specifying a file...
				
				SKIP_NARG(1);
				injectDiskHeaderInfoFile = GET_NEXT_ARG;
			}
		} else if (CHECK_ARG(ARG_INJECT_APPLOADER)) {
			//inject the apploader...
			
			injectApploaderFlag++;
			
			if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) {
				//if they're specifying a file...
				
				SKIP_NARG(1);
				injectApploaderFile = GET_NEXT_ARG;
			}
		} else if (CHECK_ARG(ARG_REPLACE_FILE)) {
			//they want to replace a file...
			
			replaceFileGCMPath = GET_NEXT_ARG;
			replaceFileLocalPath = GET_NEXT_ARG;
			
			if (!replaceFileGCMPath || !replaceFileLocalPath) {
				printf("Argument error!\n");
				printUsage();
				exit(1);
			}
			
		} else if (CHECK_ARG(ARG_LIST)) {
			// list filesystem
			
			listFilesFlag++; //turn the listFiles flag on.
			
			while(1) {
				if (PEEK_ARG && (strcmp(PEEK_ARG, OPT_FILE_INFO) == 0 || strcmp(PEEK_ARG, OPT_FILE_INFO_SYN) == 0)) {
					SKIP_NARG(1);
					listInfoFlag++;
				} else if (PEEK_ARG && (strcmp(PEEK_ARG, OPT_FULL_PATH) == 0 || strcmp(PEEK_ARG, OPT_FULL_PATH_SYN) == 0)) {
					SKIP_NARG(1);
					listPathFlag++;
				} else {
					break;
				}
			}
		} else {
			// do it to this file... this is the last argument... just ignore the rest...
			
			filepath = currentArg;
			filename = lastPathComponent(filepath);
			
			break;
		}
	} while(*argv);
	//end parsing arguments...
	
	//open the file for reading and start doing read operations!
	openFile("r");

	// print the info...
	if (showInfoFlag) {
		printGCMInfo(hexFlag);
	}
	
	// list the files, if necesary...
	if (listFilesFlag) {
		listFiles();
	}

	// extract files...
	if (extractFileFrom && extractFileTo) {
		//testing recursive extraction...
		
		GCMFileEntryStruct *e = NULL;
		
		if (strcmp(extractFileFrom, "/") == 0) {
			e = GCMGetRootFileEntry(gcmFile);
			printf("root file entry index: %d\n", e->index);
		} else {	
			e = GCMGetFileEntryAtPath(gcmFile, extractFileFrom);
		}
		
		strcpy(extractRootPath, extractFileTo);
		
		recurseFileEntry(e, extractFileEntry);
		
		free(e);
		//extractFile(extractFileFrom, extractFileTo);
	}
	
	
	//extract diskheader
	if (extractDiskHeaderFlag) {
		extractDiskHeader(extractDiskHeaderFile);
	}
	
	//extract diskheaderinfo
	if (extractDiskHeaderInfoFlag) {
		extractDiskHeaderInfo(extractDiskHeaderInfoFile);
	}
	
	//extract apploader
	if (extractApploaderFlag) {
		extractApploader(extractApploaderFile);
	}
	
	//extract main executable DOL
	if (extractBootDolFlag) {
		extractBootDol(extractBootDolFile);
	}
	
	//close the file and open it again for read/write
	closeFile();
	openFile("r+");
	
	//inject the diskheader
	if (injectDiskHeaderFlag) {
		injectDiskHeader(injectDiskHeaderFile);
	}
	
	//inject the diskheaderinfo
	if (injectDiskHeaderInfoFlag) {
		injectDiskHeaderInfo(injectDiskHeaderInfoFile);
	}
	
	//inject the apploader
	if (injectApploaderFlag) {
		injectApploader(injectApploaderFile);
	}
	
	if (replaceFileLocalPath && replaceFileGCMPath) {
		replaceFile(replaceFileGCMPath, replaceFileLocalPath);
	}

	//replace the filesystem
	if (fsReplacePath) {
		GCMReplaceFilesystem(gcmFile, fsReplacePath);
	}
	
	closeFile();
	
	return 0;
}
예제 #10
0
int main(int argc, char **argv){
    int optwait = 0;
    int numArgs = 0, start;
    open_files = (struct file_info*)malloc(maxfiles*sizeof(struct file_info));
    running_threads = (struct thread_info*)malloc(maxthreads*sizeof(struct thread_info));
    char option = 0;
    int i = 0, a;
    while ((option = (char)getopt_long(argc, argv, "", long_options, &i)) != -1)
    {
        switch (option){
            case 'a':{
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec/1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec/1000000.0;
                
                
                verbosePrint(option, optind, argv, i, argc);
                if ((argv[optind - 1][0] == '-' && argv[optind - 1][1] == '-') || (optind < argc && argv[optind][0] != '-' && argv[optind][1] != '-'))
                {
                    optind--;
                    fprintf(stderr, "Error: Wrong number of operands\n");
                    errors++;
                    break;
                }
                if (curfiles >= maxfiles){
                    open_files = (struct file_info*)realloc(open_files, (maxfiles *= 2)*sizeof(struct file_info));
                    if (open_files == NULL){
                        fprintf(stderr, "Error: Unable to reallocate memory; file was not opened.\n");
                        errors++;
                        break;
                    }
                }
                
                a = open(optarg, O_RDONLY | (O_APPEND & append) | (O_CLOEXEC & cloexec) | (O_CREAT & create) | (O_DIRECTORY & directory) | (O_DSYNC & dsyc) | (O_EXCL & excl) | (O_NOFOLLOW & nofollow)
                         | (O_NONBLOCK & nonblock) | (O_RSYNC & rsync) | (O_SYNC & syc) | (O_TRUNC & trun));
                
                if (a == -1){
                    errors++;
                    fprintf(stderr, "Error: Unable to open file\n");
                    errors++;
                    break;
                }
                
                open_files[curfiles].descriptor = a;
                open_files[curfiles].readable = 1;
                open_files[curfiles].writable = 0;
                open_files[curfiles].open = 1;
                curfiles++;
                append = cloexec = create = directory = dsyc = excl = nofollow = nonblock = rsync = syc = trun = 0;
                //some storage of the open value into some global int array.
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f for --rdonly\n", kertime);
                }
                break;
            }
            case 'b':{
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                if ((argv[optind - 1][0] == '-' && argv[optind - 1][1] == '-') || (optind < argc && argv[optind][0] != '-' && argv[optind][1] != '-'))
                {
                    optind--;
                    fprintf(stderr, "Error: Wrong number of operands\n");
                    errors++;
                    break;
                }
                if (curfiles >= maxfiles){
                    open_files = (struct file_info*)realloc(open_files, (maxfiles *= 2)*sizeof(struct file_info));
                    if (open_files == NULL){
                        fprintf(stderr, "Error: Unable to reallocate memory; file was not opened.\n");
                        errors++;
                        break;
                    }
                }
                
                
                a = open(optarg, O_WRONLY | (O_APPEND & append) | (O_CLOEXEC & cloexec) | (O_CREAT & create) | (O_DIRECTORY & directory) | (O_DSYNC & dsyc) | (O_EXCL & excl) | (O_NOFOLLOW & nofollow)
                         | (O_NONBLOCK & nonblock) | (O_RSYNC & rsync) | (O_SYNC & syc) | (O_TRUNC & trun));
                
                if (a == -1){
                    errors++;
                    fprintf(stderr, "Error: Unable to create file\n");
                    errors++;
                    break;
                }
                
                open_files[curfiles].descriptor = a;
                open_files[curfiles].readable = 0;
                open_files[curfiles].writable = 1;
                open_files[curfiles].open = 1;
                curfiles++;
                append = cloexec = create = directory = dsyc = excl = nofollow = nonblock = rsync = syc = trun = 0;
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f for --wronly\n", kertime);
                }
                break;
            }
            case 'p':{
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                if ((argv[optind - 1][0] == '-' && argv[optind - 1][1] == '-') || (optind < argc && argv[optind][0] != '-' && argv[optind][1] != '-'))
                {
                    optind--;
                    fprintf(stderr, "Error: Wrong number of operands\n");
                    errors++;
                    break;
                }
                if (curfiles >= maxfiles){
                    open_files = (struct file_info*)realloc(open_files, (maxfiles *= 2)*sizeof(struct file_info));
                    if (open_files == NULL){
                        fprintf(stderr, "Error: Unable to reallocate memory; file was not opened.\n");
                        errors++;
                        break;
                    }
                }
                
                
                a = open(optarg, O_RDWR | (O_APPEND & append) | (O_CLOEXEC & cloexec) | (O_CREAT & create) | (O_DIRECTORY & directory) | (O_DSYNC & dsyc) | (O_EXCL & excl) | (O_NOFOLLOW & nofollow)
                         | (O_NONBLOCK & nonblock) | (O_RSYNC & rsync) | (O_SYNC & syc) | (O_TRUNC & trun));
                
                if (a == -1){
                    errors++;
                    fprintf(stderr, "Error: Unable to create file\n");
                    errors++;
                    break;
               } 
                
                open_files[curfiles].descriptor = a;
                open_files[curfiles].readable = 1;
                open_files[curfiles].writable = 1;
                open_files[curfiles].open = 1;
                curfiles++;
                append = cloexec = create = directory = dsyc = excl = nofollow = nonblock = rsync = syc = trun = 0;
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
                //COMMAND
			case 'c':{  
				int b = getrusage(RUSAGE_SELF, &thread_timer);
				if (b == -1){
					errors++;
					fprintf(stderr, "Error: Could not get resource usage data\n");
					errors++;
					break;
				}
				double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
				double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
				verbosePrint(option, optind, argv, i, argc);
                int index, count=0;
                int oldoptind = optind;
                for (index = optind - 1; index < argc; index++, count++){
                    if (argv[index][0] == '-' && argv[index][1] == '-')
                        break;
                }
                optind = index;
                if (count < 4){
                    fprintf(stderr, "Error: --command requires at least 4 options.\n");
                    errors++;
                    break;
                }
                
                
                int openCheck = 0, i;
                for (i = oldoptind - 1; i < (oldoptind + 2) && i < argc; i++){
                    if (atoi(argv[i]) >= curfiles || open_files[atoi(argv[i])].open==0){
                        openCheck = 1;
                        break;
                    }
                }
                if (openCheck){
                    fprintf(stderr, "Error: File not open\n");
                    errors++;
                    break;
                }
                
                int stdinFilePos = atoi(argv[oldoptind - 1]), stdoutFilePos = atoi(argv[oldoptind]), stderrFilePos = atoi(argv[oldoptind + 1]);
                /*if (!open_files[stdinFilePos].readable || !open_files[stdoutFilePos].writable || !open_files[stderrFilePos].writable){
                 fprintf(stderr, "Error: File permission denied\n");
                 break;
                 }
                 */
                
                ////////////////////////////////////////////////////////////////////////Executable Processing////////////////////////////////////////////////////////////////////
                
                int childPID = fork();
                //int fd[2];
                //pipe(fd);
                
                if (childPID < 0){
                    fprintf(stderr, "Error: Unable to fork child process\n");
                    errors++;
                    break;
                }
                
                else if (childPID == 0){
                    //close(fd[1]);
                    int b=dup2(open_files[stdinFilePos].descriptor, STDIN_FILENO), c=dup2(open_files[stdoutFilePos].descriptor, STDOUT_FILENO), d=dup2(open_files[stderrFilePos].descriptor, STDERR_FILENO);
                    int j;
                    for (j = 0; j < curfiles; j++){
                        open_files[j].open = 0;
                        close(open_files[j].descriptor);
                    }
                    if (d == -1 || b == -1 || c == -1){
                        fprintf(stderr, "Error: unable to open file");
                        errors++;
                        break;
                    }
                    argv[optind] = '\0';
                    
                    if (curfiles >= maxfiles){
                        open_files = (struct file_info*)realloc(open_files, (maxfiles *= 2)*sizeof(struct file_info));
                        if (open_files == NULL){
                            fprintf(stderr, "Error: Unable to reallocate memory; file was not opened.\n");
                            errors++;
                            break;
                        }
                    }
                    
                    
                    execvp(argv[oldoptind+2], &argv[oldoptind+2]);
                    
                }
                else{
                    /*int status;
                     int returnedPid=waitpid(childPID, &status, 0);
                     if (status > maxExit)
                     maxExit = status;*/ //removed exit status because they get reaped which makes it so i can't access them in wait
                    running_threads[curthreads].start_ind = oldoptind + 2;
                    running_threads[curthreads].end_ind = optind;
                    running_threads[curthreads].threadnum = childPID;
                    curthreads++;
					if (profile){
						b = getrusage(RUSAGE_SELF, &thread_timer);
						if (b == -1){
							errors++;
							fprintf(stderr, "Error: Could not get resource usage data\n");
							errors++;
							break;
						}
						usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
						kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
						fprintf(stdout, "user time: %f  ", usrtime);
						fprintf(stdout, "kernel time: %f for --command\n", kertime);
					}
                    break;
                    
                }
                
                
            }
            case 'd':{
                verbose = 1;
                break;
            }
                //dealing with file opening options.
            case 'e':{
                append = -1;
                break;
            }
            case 'f':{
                cloexec = -1;
                break;
            }
            case 'g':{
                create = -1;
                break;
            }
            case 'h':{
                directory = -1;
                break;
            }
            case 'i':{
                dsyc = -1;
                break;
            }
            case 'j':{
                excl = -1;
                break;
            }
            case 'k':{
                nofollow = -1;
                break;
            }
            case 'l':{
                nonblock = -1;
                break;
            }
            case 'm':{
                rsync = -1;
                break;
            }
            case 'n':{
                syc = -1;
                break;
            }
            case 'o':{
                trun = -1;
                break;
            }
            case 'q':{
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                if (atoi(optarg) >= curfiles || open_files[atoi(optarg)].open==0){
                    fprintf(stderr, "Error: File not opened\n");
                    break;
                }
                open_files[atoi(optarg)].open = 0;
                close(open_files[atoi(optarg)].descriptor);
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 'r':{
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                raise(SIGSEGV);
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 's':{ //catch
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                signal(atoi(optarg), sig_handler);
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 't': {//ignore
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                signal(atoi(optarg), SIG_IGN);
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 'u':{ //default
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                signal(atoi(optarg), SIG_DFL);
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 'v':{
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                pause();
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 'w':{
                int b = getrusage(RUSAGE_CHILDREN, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                optwait = 1;
                for (int i = 0; i < curfiles; i++){
                    if (open_files[i].open)
                        close(open_files[i].descriptor);
                }
                for (int i = 0; i < curthreads; i++){
                    int status;
                    pid_t thrd = waitpid(-1, &status, 0);
                    
                    if (status > maxExit)
                        maxExit = status;
                    
                    for (int i = 0; i < curthreads;i++)
                        if (thrd == running_threads[i].threadnum){
                            fprintf(stdout, "%d", status);
                            for (int b = running_threads[i].start_ind; b < running_threads[i].end_ind; b++)
                                fprintf(stdout, " %s", argv[b]);
                            fprintf(stdout, "\n");
                        }
                }
                
                if (profile){
                    b = getrusage(RUSAGE_CHILDREN, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 'x':{ //pipe
                int b = getrusage(RUSAGE_SELF, &thread_timer);
                if (b == -1){
                    errors++;
                    fprintf(stderr, "Error: Could not get resource usage data\n");
                    errors++;
                    break;
                }
                double usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0;
                double kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0;
                
                verbosePrint(option, optind, argv, i, argc);
                if (argv[optind][0] != '-' && argv[optind][1] != '-')
                {
                    fprintf(stderr, "Error: Pipe should not have operands\n");
                    errors++;
                    break;
                }
                
                int fd[2];
                int p = pipe(fd);
                if (p){
                    fprintf(stderr, "Error: Unable to create file descriptors.\n");
                    errors++;
                    break;
                }
                int i;
                for (i = 0; i < 2; i++){ // add two file descriptors to the open_files array
                    if (curfiles >= maxfiles){
                        open_files = (struct file_info*)realloc(open_files, (maxfiles *= 2)*sizeof(struct file_info));
                        if (open_files == NULL){
                            fprintf(stderr, "Error: Unable to reallocate memory; file was not opened.\n");
                            errors++;
                            break;
                        }
                    }
                    open_files[curfiles].descriptor = fd[i];
                    if (i){ // when i is 0 and the read end of the pipe
                        open_files[curfiles].readable = 1;
                        open_files[curfiles].writable = 0;
                    }
                    else {// when i is 1 and the write end of the pipe
                        open_files[curfiles].readable = 0;
                        open_files[curfiles].writable = 1;
                    }
                    open_files[curfiles].open = 1;
                    curfiles++;
                }
                
                if (profile){
                    b = getrusage(RUSAGE_SELF, &thread_timer);
                    if (b == -1){
                        errors++;
                        fprintf(stderr, "Error: Could not get resource usage data\n");
                        errors++;
                        break;
                    }
                    usrtime = thread_timer.ru_utime.tv_sec + thread_timer.ru_utime.tv_usec / 1000000.0 - usrtime;
                    kertime = thread_timer.ru_stime.tv_sec + thread_timer.ru_stime.tv_usec / 1000000.0 - kertime;
                    fprintf(stdout, "user time: %f  ", usrtime);
                    fprintf(stdout, "kernel time: %f\n", kertime);
                }
                break;
            }
            case 'y':{
                profile = 1;
                break;
            }
            default:{
                break;
            }
        }
        
        
        
    }
    if (!optwait){
        for (int i = 0; i < curfiles; i++){
            if (open_files[i].open)
                close(open_files[i].descriptor);
        }
        
        for (int i = 0; i < curthreads; i++){
            int status;
            pid_t thrd = waitpid(-1, &status, 0);
            if (status > maxExit)
                maxExit = status;
        }
    }
    free(open_files);
    if (errors > 0 && maxExit == 0)
        maxExit = 1;
    exit(maxExit);
}