[so] Tema1 - Problema mini-shell Windows la citirea / executarea comenzilor simple

ana-maria lepar amylepar at gmail.com
Tue Aug 4 23:53:18 EEST 2009


Salutare tuturor,

Stiu ca este vacanta, dar ma gandesc ca poate cineva isi arunca un ochi si
pe lista de discutii de la so si ajuta vreun disperat ca mine.
Eu ma confrunt cu urmatoarea problema :
- incerc sa rulez din shell-ul meu comenzi simple + cele 3 comenzi interne
(exit, quit, cd) si dupa ce scriu dir sau alta comanda , imi da outputul
acestia si apoi mi se blocheaza
Am folosit copy / paste functia de executare a unui proces din laborator,
iar parsarea o fac intr-o bucla (dupa modelul DisplayStructure.cpp) .

CloseProcess si Exec sunt din laborator.
CreateCommand -> creeaza o comanda (concateneaza verbul si parametri (dc
exista) si o pune intre ghilimele ca sa o trimita la executie lui Exec .
ExecuteCOmmand -> executa o comanda simpla (momentan).
Mainul -> luat cu copy paste din exemplele din parserul vostru
Blocarea apare la a doua comanda care ar urma sa fie scrisa, mai precis in
bucla de for din main,  intre               cout << "> ";        si
getline(cin, line);

Redau mai jos bucata de cod care executa comanda si cea care se ocupa de
citirea ei :
=================================================================
/*@ fn  void CloseProcess(LPPROCESS_INFORMATION ppi)
    @brief functia inchide procesul curent; functia este preluata mot-a-mot
din laborator
    @param ppi : pointer catre structura de informatii a procesului
    @return nimic
*/
inline void CloseProcess(LPPROCESS_INFORMATION ppi)
{
    CloseHandle(ppi->hThread);
    CloseHandle(ppi->hProcess);
}

/*@ fn int Exec(const char *cmdLine)
    @brief executa o comanda simpla; functia este preluata mot-a-mot din
laborator
    @param cmdLine : comanda care trebuie executata
    @return -1 la esec; pidul procesului la succes
*/
int Exec(const char *cmdLine)
{
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi;
    char *cmd = _strdup(cmdLine);    // lpCommandLine not const
    BOOL bRes = CreateProcess(NULL, cmd, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL,
        NULL, &si, &pi);


    if (!bRes) {
          cerr << "eroare la createprocess " << endl;
        free(cmd);    // proper
        return -1;
    }
    DWORD dwRes = WaitForSingleObject(pi.hProcess, INFINITE);    // signaled
= finished

    if (WAIT_FAILED == dwRes) {
         cerr << "eroare la Wait for single object" <<endl;
        free(cmd);    // proper
        CloseProcess(&pi);
        return -1;
    }
    bRes = GetExitCodeProcess(pi.hProcess, &dwRes);

    free(cmd);
    CloseProcess(&pi);

    if (!bRes) {
            cerr << " eroare la closeprocess " << endl;
            return -1;
        }

    return static_cast<int>(dwRes);
}


/*! fn CreateCommand(simple_command_t comanda)
    @brief concateneaza verbul si parametri comenzii pentru o comanda simpla
    @param comanda : comanda simpla
    @return sirul rezultat din concatenare
*/

char* CreateCommand(simple_command_t *comanda){
    char* rez = (char*) calloc(256,sizeof(char));
    if (!rez) {
        cerr <<"Eroare la alocare"<<endl;
        return NULL;
    }
    strcat_s(rez,256,comanda->verb->string);
    if (comanda->params != NULL) {
        strcat_s(rez,256," ");
        strcat_s(rez,256,comanda->params->string);
    }
    return rez;
}


/*! fn ExecuteCommand(command_t* root);
    @brief executa o comanda primita de la utilizator
    @param root : este comanda
    @return nimic
*/

void ExecuteCommand(command_t *root) {
    char *comanda, *comanda_exec;
    int res,dim;
    //daca este o comanda simpla

    if(root->op == OP_NONE) {
        comanda = CreateCommand(root->scmd);

        //daca este cumva exit/quit
        ExitShell((char*) root->scmd->verb->string);

        //daca este cd director
        if (_stricmp(root->scmd->verb->string,"cd") == 0)
            ChangeDirectory((const char*)root->scmd->params->string);
        else {
            dim = 3+strlen(comanda);
            comanda_exec =(char*) calloc(dim , sizeof(char));
            if (comanda_exec == NULL)
                return;
            strcat_s(comanda_exec,dim,"\"");
            strcat_s(comanda_exec,dim,comanda);
            strcat_s(comanda_exec,dim,"\"");
            res = Exec(comanda_exec);
            if (res < 0) {
                cerr << "Execution failed for
"<<root->scmd->verb->string<<endl;
            }
        }
    }
}

/*! fn int main()
    @brief mainul; este mini-shellul in care se ruleaza comenzile
    @param fara parametri
    @return 0 la succes; -1 la esec
*/
int main(void)
{
    string line;
    command_t* root = NULL;

    for (;;) {
        cout << "> ";
        getline(cin, line);
        if ((line.length() == 0) && !cin.good()) {
            // end of file reached
            cerr << "End of file!" << endl;
            return EXIT_SUCCESS;
        }

        if (parse_line(line.c_str(), &root)) {

            if (root == NULL) {
                cout << "Command is empty!" << endl;
            }
            else {
                // root points to a valid command tree
                // that we can use
                ExecuteCommand(root);

            }
        }
        else {
            // there was an error parsing the command
            cout << "Error parsing!" << endl;
        }

        cout << endl << endl;
        free_parse_memory();
    }
}
===============================================


Multumesc mult de tot.
Astept un raspuns.

Ana
332cc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cursuri.cs.pub.ro/pipermail/so/attachments/20090804/6ec971ee/attachment.html>


More information about the so mailing list