int main(int argc, char *argv[]) { int *array; int width, height; int value; char **stringPtr; int **matrix; /* testing for part 1 */ printf("Testing Part 1\n"); width = 5; height = 6; array = create2DArray(height, width); printf("Store value 7 at [3,4].\n"); set2DElement(array, 3, 4, 7); value = get2DElement(array, 3, 4); printf("Retrieve value %d from [3,4]\n\n", value); free2DArray(array); /* testing for part 2 */ printf("Testing Part 2\n"); stringPtr = createStringArray(100); printf("Store string - fred\n"); setStringArray(stringPtr, 44, "fred"); printf("Store string - barney\n"); setStringArray(stringPtr, 80, "barney"); printf("Get string - %s\n", getStringArray(stringPtr, 44)); printf("Get string - %s\n", getStringArray(stringPtr, 80)); /* test with NULL string */ printf("Get string - %s\n\n", getStringArray(stringPtr, 3)); freeStringArray(stringPtr, 100); /* testing for part 3 */ printf("Testing Part 3\n"); matrix = createArray(100, 100); printf("Store 33 44 55\n"); matrix[22][76] = 33; matrix[83][29] = 44; matrix[99][65] = 55; printf("Retrieve %d %d %d\n", matrix[22][76], matrix[83][29], matrix[99][65]); freeArray(matrix, 100); return(1); }
int main (int argc, char** argv, char** envp){ /* Record the directory where the executable files are. */ init_dir = (char *)malloc(sizeof(char)*MAX_LINE); getcwd(init_dir,sizeof(char)*MAX_LINE); init_dir[strlen(init_dir)] = '\0'; /* Prompt for input until ctrl-d or exit have been entered */ char *line = (char *)malloc(sizeof(char)*MAX_LINE); fprintf(stdout,"$>"); while(fgets(line,MAX_LINE,stdin)){ line[strlen(line)-1] = '\0'; // Nip the buf int num_tokens = countTokens(line); char **tokens = (char **) malloc(sizeof(char *) * num_tokens); tokens = gettokens(line); /* exit was entered into the terminal so free heap space and quit. */ if (*tokens != NULL && strcmp("exit",tokens[0]) == 0){ freeStringArray(tokens); free(line); free(init_dir); exit(0); } /* Nothing entered in stdin. Continue prompting */ if(*tokens == NULL){ fprintf(stdout,"$> "); continue; } if (DEBUG) fprintf(stderr,"about to eval.\n"); evaluateCommand(tokens); /* free memory */ line = (char *)realloc(line,sizeof(char)*MAX_LINE); freeStringArray(tokens); fprintf(stdout,"$> "); } return 0; }
/* executeCommmand * Given a list of tokens containing the command and its arguments, * fork a process to execute an external command or run a command * internally. * The idea for having a start and end argument is for nested commands. * Currently, start is always going to be 0 because we are assuming 1 comand * that is the 0th token every time. */ int executeCommand(char** command_tokens,int start, int end){ int num_args = end - start; /* Extract the arguments from command_tokens */ // malloc: 1(command) + num_args + 1(NULL) char **arguments = (char **)malloc(sizeof(char *) * (num_args + 2)); int k; int l; for(l=0,k=start;command_tokens[k] != NULL && k < end+1;k++,l++){ arguments[l] = (char *)malloc( sizeof(char) * (strlen(command_tokens[k])+1)); strncpy(arguments[l],command_tokens[k],strlen(command_tokens[k])); // Must Null terminate arguments[l][strlen(command_tokens[k])] = '\0'; } // Null terminate the end. arguments[num_args+1] = NULL; /* Check to see if this command should be given a new process. */ int run_internally = 0; int j; for(j = 0; INTERNAL_UTILS[j] != NULL; j++){ if(strcmp(command_tokens[start],INTERNAL_UTILS[j]) == 0){ run_internally = 1; break; } } if(DEBUG) fprintf(stderr,"about to run.\n"); if(run_internally){ execute(arguments[0],arguments); }else{ // run externally with child process int status = 0; pid_t pid; if((pid = fork()) < 0){ fprintf(stderr,"Fork Error. Unable to run %s.\n",command_tokens[start]); exit(1); } else if(pid == 0){ // child execute(arguments[0],arguments); } if ((pid == waitpid(pid,&status,0)) < 0){ // parent fprintf(stderr,"Wait pid error. Parent process zombified.\n"); return -2; } } /* Release memory */ freeStringArray(arguments); return 0; }
char *test_readtokens() { char **toks = makeStringArray(5, 10); char line[15] = "123,45678,0000"; int count = readtokens(toks, line, ','); mu_assert("read token: count wrong", count == 3); mu_assert("read token: pos 0 wrong", strcmp(toks[0], "123") == 0); mu_assert("read token: pos 1 wrong", strcmp(toks[1], "45678") == 0); mu_assert("read token: pos 2 wrong", strcmp(toks[2], "0000") == 0); freeStringArray(toks, 5); return 0; }
// Merge all add, remove, list add, list remove, and concatenation operations // into the given RoomyList. Return the number of bytes deleted from disk. uint64 RoomyList_mergeUpdates(RoomyList* rl) { uint64 bytesDeleted = 0; char listFile[RGLO_STR_SIZE]; RoomyList_getListFileName(rl, RGLO_MY_RANK, listFile); // merge all add operations: concatenating the list file with all buffer // files, while computing predicates char** fileNames; int numFiles = RoomyList_getAllAddFiles(rl, rl->numSyncs - 1, &fileNames); if(numFiles) { WriteBuffer wb = WriteBuffer_make(RGLO_BUFFER_SIZE, rl->bytesPer, listFile, 1); int i; for(i=0; i<numFiles; i++) { ReadBuffer rb = ReadBuffer_make(RGLO_BUFFER_SIZE, rl->bytesPer, fileNames[i], 1); while(ReadBuffer_hasMore(&rb)) { // calculate predicate value changes int p; for(p=0; p<rl->numPredicates; p++) { rl->predicateVals[p] += rl->predFuncs[p](ReadBuffer_current(&rb)); } // write to main file WriteBuffer_write(&wb, ReadBuffer_current(&rb)); rl->lSize++; ReadBuffer_next(&rb); } ReadBuffer_destroy(&rb); unlink(fileNames[i]); } WriteBuffer_destroy(&wb); rl->isSorted = 0; freeStringArray(fileNames, numFiles); } // merging removes: requires both list and buffers be sorted, then stream // through both numFiles = RoomyList_getAllRemoveFiles(rl, rl->numSyncs - 1, &fileNames); if(numFiles) { bytesDeleted += numBytesInAllFiles(fileNames, numFiles); // If list is locally empty, just delete all remove files and return. // otherwise, continue processing removes. if(rl->lSize == 0) { int i; for(i=0; i<numFiles; i++) unlink(fileNames[i]); return bytesDeleted; } char tmpdir[RGLO_STR_SIZE]; RoomyList_getTmpDirName(rl, tmpdir); // sort list file if(!rl->isSorted) { char* files[1]; files[0] = listFile; extMergeSortByKey(files, 1, 1, 0, listFile, tmpdir, rl->bytesPer, rl->keyStart, rl->keySize, RGLO_MAX_CHUNK_SIZE); rl->isSorted = 1; } // sort removes char sortedName[RGLO_STR_SIZE]; RoomyList_getSortedRemoveName(rl, sortedName); extMergeSortByKey(fileNames, numFiles, 1, 1, sortedName, tmpdir, rl->updateSize, rl->keyStart, rl->keySize, RGLO_MAX_CHUNK_SIZE); uint64 sizeBefore = numBytesInFile(listFile); // stream through both and perform removes ReadBuffer listRB = ReadBuffer_make(RGLO_BUFFER_SIZE, rl->bytesPer, listFile, 1); ReadBuffer remRB = ReadBuffer_make(RGLO_BUFFER_SIZE, rl->updateSize, sortedName, 1); char tmpFile[RGLO_STR_SIZE]; sprintf(tmpFile, "%s%s", listFile, ".tmp"); WriteBuffer newListWB = WriteBuffer_make(RGLO_BUFFER_SIZE, rl->bytesPer, tmpFile, 1); void* listCur; void* remCur; int comp; while(ReadBuffer_hasMore(&listRB) && ReadBuffer_hasMore(&remRB)) { listCur = ReadBuffer_current(&listRB); remCur = ReadBuffer_current(&remRB); comp = RoomyList_compareByKey(listCur, remCur, rl->keyStart, rl->keySize); if(comp < 0) { WriteBuffer_write(&newListWB, listCur); ReadBuffer_next(&listRB); } else if(comp == 0) { // element is being removed, calculate predicate and size changes int p; for(p=0; p<rl->numPredicates; p++) { rl->predicateVals[p] -= rl->predFuncs[p](listCur); } rl->lSize--; ReadBuffer_next(&listRB); } else { ReadBuffer_next(&remRB); } } while(ReadBuffer_hasMore(&listRB)) { listCur = ReadBuffer_current(&listRB); WriteBuffer_write(&newListWB, listCur); ReadBuffer_next(&listRB); } ReadBuffer_destroy(&listRB); ReadBuffer_destroy(&remRB); WriteBuffer_destroy(&newListWB); unlink(listFile); rename(tmpFile, listFile); bytesDeleted += sizeBefore - numBytesInFile(listFile); freeStringArray(fileNames, numFiles); } // space accounting Roomy_dataRemoved(bytesDeleted); return bytesDeleted; }
/* Python's implementation of Popen forks back to python before execing. * Forking a python proc is a very complex and volatile process. * * This is a simpler method of execing that doesn't go back to python after * forking. This allows for faster safer exec. * * return NULL on error and sets the python error accordingly. */ static PyObject * createProcess(PyObject *self, PyObject *args) { int cpid; int deathSignal = 0; int rv; int outfd[2] = {-1, -1}; int in1fd[2] = {-1, -1}; int in2fd[2] = {-1, -1}; int errnofd[2] = {-1, -1}; int childErrno = 0; PyObject* pyArgList; PyObject* pyEnvList; const char* cwd; int close_fds = 0; char** argv = NULL; char** envp = NULL; if (!PyArg_ParseTuple(args, "O!iiiiiiizOi:createProcess;", &PyList_Type, &pyArgList, &close_fds, &outfd[0], &outfd[1], &in1fd[0], &in1fd[1], &in2fd[0], &in2fd[1], &cwd, &pyEnvList, &deathSignal)) { return NULL; } argv = pyListToArray(pyArgList, 1); if (!argv) { goto fail; } if (PyList_Check(pyEnvList)) { envp = pyListToArray(pyEnvList, 0); if (!envp) { goto fail; } } if(pipe(errnofd) < 0) { PyErr_SetFromErrno(PyExc_OSError); goto fail; } try_fork: cpid = fork(); if (cpid < 0) { if (errno == EAGAIN || errno == EINTR ) { goto try_fork; } PyErr_SetFromErrno(PyExc_OSError); goto fail; } if (!cpid) { safeClose(0); safeClose(1); safeClose(2); dup2(outfd[0], 0); dup2(in1fd[1], 1); dup2(in2fd[1], 2); safeClose(outfd[0]); safeClose(outfd[1]); safeClose(in1fd[0]); safeClose(in1fd[1]); safeClose(in2fd[0]); safeClose(in2fd[1]); safeClose(errnofd[0]); if (deathSignal) { childErrno = prctl(PR_SET_PDEATHSIG, deathSignal); if (childErrno < 0) { childErrno = errno; } /* Check that parent did not already die between fork and us * setting the death signal */ if (write(errnofd[1], &childErrno, sizeof(int)) < sizeof(int)) { exit(-1); } if (childErrno != 0) { exit(-1); } } if (setCloseOnExec(errnofd[1]) < 0) { goto sendErrno; } if (close_fds) { closeFDs(errnofd[1]); } if (cwd) { if (chdir(cwd) < 0) { goto sendErrno; } setenv("PWD", cwd, 1); } exec: if (envp) { execvpe(argv[0], argv, envp); } else { execvp(argv[0], argv); } if (errno == EINTR || errno == EAGAIN ) { goto exec; } sendErrno: if (write(errnofd[1], &errno, sizeof(int)) < 0) { exit(errno); } exit(-1); } safeClose(errnofd[1]); errnofd[1] = -1; if (deathSignal) { /* death signal sync point */ rv = safeRead(errnofd[0], &childErrno, sizeof(int)); if (rv != sizeof(int)) { PyErr_SetFromErrno(PyExc_OSError); goto fail; } else if (childErrno != 0) { PyErr_SetString(PyExc_OSError, strerror(childErrno)); goto fail; } } /* error sync point */ rv = safeRead(errnofd[0], &childErrno, sizeof(int)); if (rv == sizeof(int)) { PyErr_SetString(PyExc_OSError, strerror(childErrno)); goto fail; } else if (rv < 0) { PyErr_SetFromErrno(PyExc_OSError); goto fail; } safeClose(errnofd[0]); errnofd[0] = -1; /* From this point errors shouldn't occur, if they do something is very * very very wrong */ freeStringArray(argv); if (envp) { freeStringArray(envp); } return Py_BuildValue("(iiii)", cpid, outfd[1], in1fd[0], in2fd[0]); fail: if (argv) { freeStringArray(argv); } if (envp) { freeStringArray(envp); } if (errnofd[0] >= 0) { safeClose(errnofd[0]); } if (errnofd[1] >= 0) { safeClose(errnofd[1]); } return NULL; }