int main (int argc, char **argv) { char * cmdLine; char * username; char ** cmd; char hostname[256]; size_t len = 256; struct sigaction new_action, old_action; /* Inicializa a lista que guarda os processos que rodam em background */ childs = malloc(sizeof(LIST)); ListCreate(childs); /* Inicializa a variável que guarda o ID do processo atual do foreground */ fgChildPid = 0; child_handler_lock = 0; /* Set up the structure to specify the new action. */ new_action.sa_handler = termination_handler; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; sigaction (SIGINT, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGINT, &new_action, NULL); sigaction (SIGHUP, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGHUP, &new_action, NULL); sigaction (SIGTERM, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGTERM, &new_action, NULL); new_action.sa_handler = child_handler; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; sigaction (SIGCHLD, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGCHLD, &new_action, NULL); new_action.sa_handler = sigtstop_handler; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; sigaction (SIGTSTP, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGTSTP, &new_action, NULL); /*inicializa lista que guarda o historico de comandos */ history = malloc(sizeof(struct node)); history->cmd = NULL; history->next = NULL; /* Pega o nome do usuario atual e da máquina */ username = getlogin(); gethostname(hostname, len); asprintf(&userdir, "/home/%s", username); /* Coloca o diretório do usuário como diretório inicial */ chdir(userdir); while (1) { printPrompt(username, hostname); output_r = input_r = 0; rewind(stdin); cmdLine = readline(); if(strcmp(cmdLine, "") != 0) { add_history(cmdLine); cmd = parse(cmdLine); int cmd_id = isBuiltIn(cmd[0]); if(cmd_id >= 0) callBuiltIn(cmd_id, cmd[1]); else { if((childPid = fork()) == 0) { if(output_r) { fd_out = open(output_r_filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR, 0666); dup2(fd_out, 1); } if(input_r) { fd_in = open(input_r_filename, O_RDONLY, 0666); dup2(fd_in, 0); } fgChildPid = childPid; int i = execvp(cmd[0], cmd); if (output_r) close(fd_out); if (input_r) close(fd_in); if(i < 0) { printf("%s: command not found\n", cmd[0]); exit(101); } } else { /*Após criar o processo filho, o pai insere em uma lista ligada o novo processo */ int status; pid_t pidfg; ITEM * p; p = malloc(sizeof(ITEM)); p->pid = childPid; p->isBackground = isBackground; strcpy(p->status, "Running"); strcpy(p->command, cmdLine); ListInsert(childs, p); isBackground = 0; /*E espera ele terminar, caso seja um processo de foreground */ if(!p->isBackground) { child_handler_lock = 1; pidfg = waitpid(childPid, &status, WUNTRACED); child_handler_lock = 0; if ((pidfg >= 0) && (WIFSTOPPED(status) == 0)) ListRemoveByPid(childs, childPid); } } } free_parse(); free(cmdLine); } } }
bool continueFunction (loadedFunction * fun) { bool keepLooping = true; bool advanceNow; unsigned int param; sludgeCommand com; if (fun -> cancelMe) { abortFunction (fun); return true; } // if (numBIFNames) newDebug ("*** Function:", allUserFunc[fun -> originalNumber]); //debugOut ("SLUDGER: continueFunction\n"); while (keepLooping) { advanceNow = true; param = fun -> compiledLines[fun -> runThisLine].param; com = fun -> compiledLines[fun -> runThisLine].theCommand; // fprintf (stderr, "com: %d param: %d (%s)\n", com, param, // (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE); fflush(stderr); if (numBIFNames) { setFatalInfo ( (fun -> originalNumber < numUserFunc) ? allUserFunc[fun -> originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE); // newDebug ( // (com < numSludgeCommands) ? sludgeText[com] : "Unknown SLUDGE machine code", // param); } //debugOut ("SLUDGER: continueFunction - in da loop: %s\n", sludgeText[com]); switch (com) { case SLU_RETURN: if (fun -> calledBy) { loadedFunction * returnTo = fun -> calledBy; if (fun -> returnSomething) copyVariable (fun -> reg, returnTo -> reg); finishFunction (fun); fun = returnTo; restartFunction (fun); } else { finishFunction (fun); advanceNow = false; // So we don't do anything else with "fun" keepLooping = false; // So we drop out of the loop } break; case SLU_CALLIT: switch (fun -> reg.varType) { case SVT_FUNC: pauseFunction (fun); if (numBIFNames) setFatalInfo ( (fun -> originalNumber < numUserFunc) ? allUserFunc[fun -> originalNumber] : "Unknown user function", (fun -> reg.varData.intValue < numUserFunc) ? allUserFunc[fun -> reg.varData.intValue] : "Unknown user function"); if (! startNewFunctionNum (fun -> reg.varData.intValue, param, fun, fun -> stack)) return false; fun = allRunningFunctions; advanceNow = false; // So we don't do anything else with "fun" break; case SVT_BUILT: { builtReturn br = callBuiltIn (fun -> reg.varData.intValue, param, fun); switch (br) { case BR_ERROR: return fatal("Unknown error. This shouldn't happen. Please notify the SLUDGE developers."); case BR_PAUSE: pauseFunction (fun); // No break! case BR_KEEP_AND_PAUSE: keepLooping = false; break; case BR_ALREADY_GONE: keepLooping = false; advanceNow = false; break; case BR_CALLAFUNC: { int i = fun -> reg.varData.intValue; setVariable (fun -> reg, SVT_INT, 1); pauseFunction (fun); if (numBIFNames) setFatalInfo ( (fun -> originalNumber < numUserFunc) ? allUserFunc[fun -> originalNumber] : "Unknown user function", (i < numUserFunc) ? allUserFunc[i] : "Unknown user function"); if (! startNewFunctionNum (i, 0, fun, noStack, false)) return false; fun = allRunningFunctions; advanceNow = false; // So we don't do anything else with "fun" } break; default: break; } } break; default: return fatal (ERROR_CALL_NONFUNCTION); } break; // These all grab things and shove 'em into the register case SLU_LOAD_NULL: setVariable (fun -> reg, SVT_NULL, 0); break; case SLU_LOAD_FILE: setVariable (fun -> reg, SVT_FILE, param); break; case SLU_LOAD_VALUE: setVariable (fun -> reg, SVT_INT, param); break; case SLU_LOAD_LOCAL: if (! copyVariable (fun -> localVars[param], fun -> reg)) return false; break; case SLU_AND: setVariable (fun -> reg, SVT_INT, getBoolean (fun -> reg) && getBoolean (fun -> stack -> thisVar)); trimStack (fun -> stack); break; case SLU_OR: setVariable (fun -> reg, SVT_INT, getBoolean (fun -> reg) || getBoolean (fun -> stack -> thisVar)); trimStack (fun -> stack); break; case SLU_LOAD_FUNC: setVariable (fun -> reg, SVT_FUNC, param); break; case SLU_LOAD_BUILT: setVariable (fun -> reg, SVT_BUILT, param); break; case SLU_LOAD_OBJTYPE: setVariable (fun -> reg, SVT_OBJTYPE, param); break; case SLU_UNREG: if (dialogValue != 1) fatal (ERROR_HACKER); break; case SLU_LOAD_STRING: if (! loadStringToVar (fun -> reg, param)) { return false; } break; case SLU_INDEXGET: case SLU_INCREMENT_INDEX: case SLU_DECREMENT_INDEX: switch (fun -> stack -> thisVar.varType) { case SVT_NULL: if (com == SLU_INDEXGET) { setVariable (fun -> reg, SVT_NULL, 0); trimStack (fun -> stack); } else { return fatal (ERROR_INCDEC_UNKNOWN); } break; case SVT_FASTARRAY: case SVT_STACK: if (fun -> stack -> thisVar.varData.theStack -> first == NULL) { return fatal (ERROR_INDEX_EMPTY); } else { int ii; if (! getValueType (ii, SVT_INT, fun -> reg)) return false; variable * grab = (fun -> stack -> thisVar.varType == SVT_FASTARRAY) ? fastArrayGetByIndex (fun -> stack -> thisVar.varData.fastArray, ii) : stackGetByIndex (fun -> stack -> thisVar.varData.theStack -> first, ii); trimStack (fun -> stack); if (! grab) { setVariable (fun -> reg, SVT_NULL, 0); } else { int ii; switch (com) { case SLU_INCREMENT_INDEX: if (! getValueType (ii, SVT_INT, * grab)) return false; setVariable (fun -> reg, SVT_INT, ii); grab -> varData.intValue = ii + 1; break; case SLU_DECREMENT_INDEX: if (! getValueType (ii, SVT_INT, * grab)) return false; setVariable (fun -> reg, SVT_INT, ii); grab -> varData.intValue = ii - 1; break; default: if (! copyVariable (* grab, fun -> reg)) return false; } } } break; default: return fatal (ERROR_INDEX_NONSTACK); } break; case SLU_INDEXSET: switch (fun -> stack -> thisVar.varType) { case SVT_STACK: if (fun -> stack -> thisVar.varData.theStack -> first == NULL) { return fatal (ERROR_INDEX_EMPTY); } else { int ii; if (! getValueType (ii, SVT_INT, fun -> reg)) return false; if (! stackSetByIndex (fun -> stack -> thisVar.varData.theStack -> first, ii, fun -> stack -> next -> thisVar)) { return false; } trimStack (fun -> stack); trimStack (fun -> stack); } break; case SVT_FASTARRAY: { int ii; if (! getValueType (ii, SVT_INT, fun -> reg)) return false; variable * v = fastArrayGetByIndex (fun -> stack -> thisVar.varData.fastArray, ii); if (v == NULL) return fatal ("Not within bounds of fast array."); if (! copyVariable (fun -> stack -> next -> thisVar, * v)) return false; trimStack (fun -> stack); trimStack (fun -> stack); } break; default: return fatal (ERROR_INDEX_NONSTACK); } break; // What can we do with the register? Well, we can copy it into a local // variable, a global or onto the stack... case SLU_INCREMENT_LOCAL: { int ii; if (! getValueType (ii, SVT_INT, fun -> localVars[param])) return false; setVariable (fun -> reg, SVT_INT, ii); setVariable (fun -> localVars[param], SVT_INT, ii + 1); } break; case SLU_INCREMENT_GLOBAL: { int ii; if (! getValueType (ii, SVT_INT, globalVars[param])) return false; setVariable (fun -> reg, SVT_INT, ii); setVariable (globalVars[param], SVT_INT, ii + 1); } break; case SLU_DECREMENT_LOCAL: { int ii; if (! getValueType (ii, SVT_INT, fun -> localVars[param])) return false; setVariable (fun -> reg, SVT_INT, ii); setVariable (fun -> localVars[param], SVT_INT, ii - 1); } break; case SLU_DECREMENT_GLOBAL: { int ii; if (! getValueType (ii, SVT_INT, globalVars[param])) return false; setVariable (fun -> reg, SVT_INT, ii); setVariable (globalVars[param], SVT_INT, ii - 1); } break; case SLU_SET_LOCAL: if (! copyVariable (fun -> reg, fun -> localVars[param])) return false; break; case SLU_SET_GLOBAL: // newDebug (" Copying TO global variable", param); // newDebug (" Global type at the moment", globalVars[param].varType); if (! copyVariable (fun -> reg, globalVars[param])) return false; // newDebug (" New type", globalVars[param].varType); break; case SLU_LOAD_GLOBAL: // newDebug (" Copying FROM global variable", param); // newDebug (" Global type at the moment", globalVars[param].varType); if (! copyVariable (globalVars[param], fun -> reg)) return false; break; case SLU_STACK_PUSH: if (! addVarToStack (fun -> reg, fun -> stack)) return false; break; case SLU_QUICK_PUSH: if (! addVarToStackQuick (fun -> reg, fun -> stack)) return false; break; case SLU_NOT: setVariable (fun -> reg, SVT_INT, ! getBoolean (fun -> reg)); break; case SLU_BR_ZERO: if (! getBoolean (fun -> reg)) { advanceNow = false; fun -> runThisLine = param; } break; case SLU_BRANCH: advanceNow = false; fun -> runThisLine = param; break; case SLU_NEGATIVE: { int i; if (! getValueType (i, SVT_INT, fun -> reg)) return false; setVariable (fun -> reg, SVT_INT, -i); } break; // All these things rely on there being somet' on the stack case SLU_MULT: case SLU_PLUS: case SLU_MINUS: case SLU_MODULUS: case SLU_DIVIDE: case SLU_EQUALS: case SLU_NOT_EQ: case SLU_LESSTHAN: case SLU_MORETHAN: case SLU_LESS_EQUAL: case SLU_MORE_EQUAL: if (fun -> stack) { int firstValue, secondValue; switch (com) { case SLU_PLUS: addVariablesInSecond (fun -> stack -> thisVar, fun -> reg); trimStack (fun -> stack); break; case SLU_EQUALS: compareVariablesInSecond (fun -> stack -> thisVar, fun -> reg); trimStack (fun -> stack); break; case SLU_NOT_EQ: compareVariablesInSecond (fun -> stack -> thisVar, fun -> reg); trimStack (fun -> stack); fun -> reg.varData.intValue = ! fun -> reg.varData.intValue; break; default: if (! getValueType (firstValue, SVT_INT, fun -> stack -> thisVar)) return false; if (! getValueType (secondValue, SVT_INT, fun -> reg)) return false; trimStack (fun -> stack); switch (com) { case SLU_MULT: setVariable (fun -> reg, SVT_INT, firstValue * secondValue); break; case SLU_MINUS: setVariable (fun -> reg, SVT_INT, firstValue - secondValue); break; case SLU_MODULUS: setVariable (fun -> reg, SVT_INT, firstValue % secondValue); break; case SLU_DIVIDE: setVariable (fun -> reg, SVT_INT, firstValue / secondValue); break; case SLU_LESSTHAN: setVariable (fun -> reg, SVT_INT, firstValue < secondValue); break; case SLU_MORETHAN: setVariable (fun -> reg, SVT_INT, firstValue > secondValue); break; case SLU_LESS_EQUAL: setVariable (fun -> reg, SVT_INT, firstValue <= secondValue); break; case SLU_MORE_EQUAL: setVariable (fun -> reg, SVT_INT, firstValue >= secondValue); break; default: break; } } } else { return fatal (ERROR_NOSTACK); } break; default: return fatal (ERROR_UNKNOWN_CODE); } if (advanceNow) fun -> runThisLine ++; } return true; }