void freePipe(Pipe p) { if ( p == NULL ) return; freeCmd(p->head); freePipe(p->next); free(p); } /*---------- End of freePipe ----------------------------------------------*/
static Pipe mkPipe() { Pipe p; Cmd c; c = mkCmd(Tnil); // at least one command // ignore NULL cmds--generated by empty line or error if ( c == NULL || c == &Empty ) return NULL; // allocate the pipe structure p = ckmalloc(sizeof(*p)); p->type = Pout; // set type to Pout until we know differently p->head = c; while ( PipeToken(LA) ) { if ( LA == TpipeErr ) p->type = PoutErr; // reset type else if(LA == Tpipe) p->type = Pout; //reset type if ( c->out != Tnil ) { printf("Ambiguous output redirect.\n"); // skip to end of command do { Next(); } while ( !EndOfInput(LA) ); freeCmd(c); return NULL; } else c->out = p->type == Pout ? Tpipe : TpipeErr; Next(); c->next = mkCmd(p->type == Pout ? Tpipe : TpipeErr); if ( c->next == NULL || c->next == &Empty ) { if ( c->next == &Empty ) printf("Invalid null command.\n"); while ( !EndOfInput(LA) ) Next(); return NULL; } c = c->next; } // read next pipe on the line p->next = NULL; while ( !EndOfInput(LA) ) { p->next = mkPipe(); if ( !p->next ) break; } return p; } /*---------- End of mkPipe ------------------------------------------------*/
// reads command from fd int readCmd(int fd, struct cmd *command) { command->params = (char **) allocate((MAX_CMD_PARAMS + 1) * sizeof (char *)); int i = 0; char c, r; command->params[0] = NULL; // reads command name if ((r = readWord(fd, command->name, 256)) == 0) { freeCmd(command); return (-1); } // loads parametres while (1) { command->params[i] = NULL; if (r == '\r') { if (read(fd, &c, 1) != 1) { freeCmd(command); return (-1); } if (c == '\n') break; // \r\n sequence } if (r == '\n') break; // read another parameter command->params[i] = (char *) allocate(256 * sizeof (char)); if ((r = readWord(fd, command->params[i], 256)) == 0) { command->params[i+1] = NULL; freeCmd(command); return (-1); } ++i; if (i == MAX_CMD_PARAMS) break; } // returns number of read parameters return (i); }
static void freeCmd(Cmd c) { int i; if ( c == NULL || c == &Empty || c == &End ) return; freeCmd(c->next); if ( c->infile ) free(c->infile); if ( c->outfile ) free(c->outfile); if ( c->args ) { for ( i = 0; i < c->nargs; i++ ) free(c->args[i]); free(c->args); } free(c); } /*---------- End of freeCmd -----------------------------------------------*/
static Cmd mkCmd(Token inpipe) { Cmd c; while ( CmdToken(LA) ) // skip over ; and & Next(); if ( LA != Tword ) { // a word begins every command if ( LA == Tend ) return &End; if ( LA == Tnl || LA == Terror ) // don't complain about empty lines or twice about same error return &Empty; printf(ERR_MSG); #if 0 while ( !CmdToken(LA) && !EndOfInput(LA) ) // kill rest of pipe Next(); #endif return NULL; } assert(LA == Tword); c = newCmd(Word); Next(); c->in = inpipe; while ( InCmd(LA) ) { // loop until next command switch ( LA ) { case Tin: if ( c->in != Tnil ) { // two Tin in one command printf("Ambiguous input redirect.\n"); // skip to end of line do { Next(); } while ( !EndOfInput(LA) ); freeCmd(c); return NULL; } c->in = LA; Next(); if ( LA != Tword ) { printf(ERR_MSG); // skip to end of line do { Next(); } while ( !EndOfInput(LA) ); freeCmd(c); return NULL; } c->infile = mkWord(Word); // save "in" file Next(); break; case Tout: case ToutErr: case Tapp: case TappErr: if ( c->out != Tnil ) { printf("Ambiguous output redirect.\n"); // skip to end of line do { Next(); } while ( !EndOfInput(LA) ); freeCmd(c); return NULL; } c->out = LA; // remember which kind Next(); if ( LA != Tword) { printf(ERR_MSG); // skip to end of line do { Next(); } while ( !EndOfInput(LA) ); freeCmd(c); return NULL; } c->outfile = mkWord(Word); // save "out" file Next(); break; case Tword: if ( c->args == NULL ) { printf("Hmmm...\n"); exit(-2); } // if we've exceeded the size of the arg array double it if ( c->nargs + 2 > c->maxargs ) { c->maxargs += c->maxargs; c->args = realloc(c->args, c->maxargs*sizeof(char *)); if ( c->args == NULL ) { perror("realloc"); exit(errno); } } c->args[c->nargs++] = mkWord(Word); // save the arg Next(); break; default: printf("Shouldn't get here\n"); exit(-1); break; } } if ( LA == Terror ) { // shouldn't happen, but what the heck ... freeCmd(c); return NULL; } if ( LA == Tsemi ) // skip over ending semi Next(); else if ( LA == Tamp ){ // remember the & c->exec = Tamp; Next(); } c->args[c->nargs] = NULL; return c; } /*---------- End of mkCmd -------------------------------------------------*/
int main(int argc, char **argv) { struct rusage usageBegin; getrusage(RUSAGE_SELF, &usageBegin); char *prompt = ";) "; printf("%s", prompt); fflush(stdout); int sequential = 1; struct node* tasks = NULL; struct node *paths = NULL; struct stat haspath; int canhas = stat("shell-config", &haspath); if(canhas==0){ FILE * pathfile = fopen("shell-config", "r"); char* pathline = malloc(128*sizeof(char)); while(fgets(pathline, 128, pathfile) != NULL){ pathline[strlen(pathline)-1] = '/'; list_insert(pathline, &paths); } free(pathline); fclose(pathfile); } char buffer[1024] = "initialized"; int polloop = 1; while(polloop ==1){ struct pollfd pfd = {0, POLLIN}; //"In" events check int input = poll(&pfd, 1, 1000); //Input will be a 1=yes, 0=no input in the past second. if(input ==0){ //run through the grand linked list of background processes. struct node *checkup = tasks; struct node *suture = tasks; int checkstatus = 0; while(checkup!=NULL){ pid_t childp = waitpid((*checkup).pid, &checkstatus, WNOHANG); if(childp != 0){ printf("Parent got carcass of child process %d, return val %d\n", childp, checkstatus); if(checkup == tasks){ tasks = (*checkup).next; free(checkup); checkup = tasks; }else{ (*suture).next = (*checkup).next; free(checkup); checkup = (*suture).next; } }else{ if(checkup != tasks){ suture = (*suture).next; } checkup = (*checkup).next; } } } else if(input<0){ //probably need to free junk before exit. polloop = 0; }else{ //run our fgets and do stuff with their commands. if(fgets(buffer, 1024, stdin) != NULL){ int buflen = 1023; int i = 0; while( i<buflen && buffer[i] != '#'){ i++; } buffer[i] = '\0'; buflen = i-1; //printf("Buffer:%s", buffer); char *** cmd = parseCommand(buffer); //char* test = "a b c d e f g"; //char*** cmd[2] = {tokenify(test), NULL}; /*int a = 0; int b = 0; for(; cmd[a]!=NULL; a++){ for(; (cmd[a])[b] != NULL; b++){ printf("Command: %s\n", (cmd[a])[b]); } b=0; }*/ int com = 0; //Will be used to increment through cmd int built; //Sequential Running of cmd: for(; sequential==1 && cmd[com] != NULL; com++){ built = builtIn(cmd[com]); if(built == 1){ sequential = changeMode(sequential, (cmd[com])[1]); } else if(built == -1){ sequential = -1; } else{ sequential = runSeq(cmd[com], paths); } } int*** newpros; if (sequential == 0 && cmd[com]!=NULL){ newpros = parallel(cmd+com, paths, tasks); sequential = (newpros[0])[0][0]; if(sequential!=-2){ int index = newpros[1][0][0]; for(;index > 1; index--){ /*printf("Index points:%p, Index is:%d\n", newpros[index], index); printf("Index[1] points:%p\n", newpros[index][1]); printf("Index[1][0] points:%d\n", newpros[index][1][0]);*/ if(newpros[index][1][0]>0){ list_insert( (char*)newpros[index][0], &tasks); (*tasks).pid = *(newpros[index][1]); (*tasks).status = 1; //1 for running } free(newpros[index][1]); free(newpros[index][0]); free(newpros[index]); } free(newpros); } } if(sequential == -2){ free(newpros[0][0]); free(newpros[0]); free(newpros); exit(2); } freeCmd(cmd); free(cmd); if(sequential == -1){ //totally wrong. fix. -- fixed if(tasks!=NULL){ struct node *waiter = tasks; while(waiter!=NULL){ int rstatus = 0; pid_t childp = waitpid((*waiter).pid, &rstatus,0); printf("Parent got carcass of child process %d, return val %d\n", childp, rstatus); waiter = (*waiter).next; } while((*tasks).next!=NULL){ waiter = (*tasks).next; free(tasks); tasks = waiter; } free(tasks); } exitUsage(&usageBegin); exit(2); } printf("%s", prompt); fflush(stdout); }else{ polloop = -1; } } } exitUsage(&usageBegin); printf("exited\n"); return 0; }
// function running in separate thread, handling data connection int controlRoutine(struct control_info *info) { int fd = info->fd; struct cmd command; time_t now = time(NULL); struct state cstate = (struct state) { .logged = 0, .path = "/", .data_port = info->configuration->data_port, .transfer_count = 0, .data_sock = 0, .control_sock = 0, .port = 1, .last_accepted = 0, .addr_family = 1, .data_thread = 0, .transfer_type = Image, .client_addr = *(info->client_addr) }; snprintf(cstate.dir, 32, "%d", (int)now); short abor = 0; if (isDir("/control_sockets") == -1) if (mkdir("/control_sockets", 0755) == -1) { perror("Failed to create control_sockets directory."); return (-1); } // reads commands from the accepted connection and executes it while (readCmd(fd, &command) != -1) { executeCmd(&command, &abor, fd, &cstate, info->configuration); freeCmd(&command); if (abor) break; } if (errno == EINTR) return (1); return (0); } // function running in separate thread, handles data connection void *dataRoutine(void *arg) { struct data_info *info = (struct data_info *) arg; int sck; struct sockaddr_un sa; struct sockaddr_in in; bzero(&in, sizeof (in)); bzero(&sa, sizeof (sa)); struct state cstate = *(info->cstate); strncpy(sa.sun_path, info->control_sock, sizeof (sa.sun_path)); sa.sun_family = AF_UNIX; // tries to create a connection // for communicating with the control thread if ((sck = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("Error creating control socket."); return (arg); } if (connect(sck, (struct sockaddr *) &sa, sizeof (sa)) == -1) { perror("Error connecting to control socket."); return (arg); } struct cmd command; cstate.data_sock = 0; // reads commands from control thread and executes them while (1) { // printf("Data socket: %d\n", cstate.data_sock); readUntil(command.name, sck, 0, 256); if (command.name[0] == 'Q') { break; } executeCmd(&command, NULL, sck, &cstate, info->configuration); // projects the changes to the control thread, info->cstate->data_sock = cstate.data_sock; info->cstate->last_accepted = cstate.last_accepted; } if (cstate.data_sock) { close(cstate.data_sock); } free(info); return (arg); }