Własny shell - pomoc

0

Witam, muszę napisać własnego shella w C.

Chciałbym, żeby ktoś znający się na tym zweryfikował czy to co zrobiłem do tej pory ma sens.
Proszę o nie wklejanie kodów z poprawionymi błędami, tylko o wskazanie błędy z jakąś podpowiedzią. :)
Nie mam pojęcia jak napisać cd, a jako dodatkowe polecenia chciałem dodać cp i rm.
Czas na napisanie tego mam do końca tygodnia :/

Program ten powinien przyjmować na wejściu polecenia,
a następnie wykonywać działania zgodne z ich treścią. Powłoka taka powinna:
-wyświetlać znak zachęty w postaci [{path}], gdzie {path} jest ścieżką do bieżącego katalogu roboczego, ˙
-obsługiwać polecenie powłoki cd, działające analogicznie do tego znanego
nam z powłoki bash,
-obsługiwać polecenie powłoki exit, kończące działanie programu powłoki. Polecenie exit powinno przyjmować jeden opcjonalny parametr,
będący statusem wyjścia zwracanym do procesu rodzica,
-obsługiwać polecenie powłoki help, wyświetlające na ekranie informacje o autorze programu i oferowanych przez niego funkcjonalnościach,
-obsługiwać dwa inne, dowolnie wybrane polecenie powłoki,
-przyjmować polecenia odwołujące się przez nazwę do skryptów i programów znajdujących się w katalogach opisanych wartością zmiennej
środowiskowej PATH oraz umożliwiać wywołanie tych skryptów i programów z argumentami,
-przyjmować polecenia odwołujące się przez ścieżki względne oraz bezwzględne do skryptów i programów znajdujących się na dysku komputera,
a także umożliwiać ich wywołanie z argumentami,
-wypisywać komunikat błędu, gdy niemożliwe jest poprawne zinterpretowanie polecenia.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

int main()
{
    while(1){

    //Znak zachęty

    char path[PATH_MAX];
    getcwd(path, sizeof(path));
    printf("%s~$ ", path);

    ////////////////////////////////

    char polecenie[150];
    int isHelp, isCd, isExit, isExit1, isFread;

    scanf("%15s", polecenie);

    isExit = strcmp(polecenie, "exit");
    isExit1 = strcmp(polecenie, "exit-u");
    isCd = strcmp(polecenie, "cd");
    isHelp = strcmp(polecenie, "help");

    if(isExit==0){
    exit(0);
    }

    if(isExit1==0){
    exit(1);
    }

    else if(isCd==0){
    printf("cd\n");
    }

    else if(isHelp==0){
    printf("Shell\n");
    printf("Autor: \n");
    printf("\n");
    printf("Polecenia:\n");
    printf("help - pomoc\n");
    printf("exit - wyjscie\n");
    printf("exit-u - wyjscie zakonczonie niepowodzeniem\n");
    }

    else{
        printf("Bledne polecenie!\n");
    }
    }
    return 0;
}
1

https://www.systutorials.com/docs/linux/man/2-chdir/
Swoją drogą, jeśli chcesz to zrobić dobrze, rozważyłbym użyć flexa i bisona. Parsowanie w czystym C to mało przyjemna rzecz.

1

Kilka słów uwag:

  1. tu jest zaledwie próba wstępu do zarysu wykrywania komend, nie ma żadnej nawet próby wykonania. Jesteśmy w lesie.
  2. logika kodu jest jako ogromny if then else - fatalna
pomyśl o czymś takim
struct Command {
const char * cmdString;
void * execute(); // wskażnik funkcjyny
const char * [] // ewentualnie coś o dopuszczalny parametrach. Z tego główny parser dowie się o możliwej ilości, bopierze stringi do help'a itd
};

struct Command[] list ;

Każda komenda będzie jedną funkcją, będą niezależne, i nie będzie musiała zajmować się parsowaniem, tylko wykonaniem
poszerzalność, konserowalność każdej z komend znacznie wzrośnie

0
elwis napisał(a):

https://www.systutorials.com/docs/linux/man/2-chdir/
Swoją drogą, jeśli chcesz to zrobić dobrze, rozważyłbym użyć flexa i bisona. Parsowanie w czystym C to mało przyjemna rzecz.

Dzięki za link :) , musi być czyste C

0
AnyKtokolwiek napisał(a):

Kilka słów uwag:

  1. tu jest zaledwie próba wstępu do zarysu wykrywania komend, nie ma żadnej nawet próby wykonania. Jesteśmy w lesie.
  2. logika kodu jest jako ogromny if then else - fatalna
pomyśl o czymś takim
struct Command {
const char * cmdString;
void * execute(); // wskażnik funkcjyny
const char * [] // ewentualnie coś o dopuszczalny parametrach. Z tego główny parser dowie się o możliwej ilości, bopierze stringi do help'a itd
};

struct Command[] list ;

Każda komenda będzie jedną funkcją, będą niezależne, i nie będzie musiała zajmować się parsowaniem, tylko wykonaniem
poszerzalność, konserowalność każdej z komend znacznie wzrośnie

Dzięki, spróbuję jutro poprawić kod.

0

Zrobiłem coś takiego. @AnyKtokolwiek zostałem przy if'ach, ponieważ nie mogłem tego ogarnąć, a czas nagli.
Chciałbym, żeby komendy działały jak w linuxie, ale nie mogę ogarnąć jak pobrać komendy z argumentami po spacji.

Teraz planuję rozszerzenie cd (cd, cd .. itp.)
Czy dobrze zinterpretowałem? "obsługiwać polecenie powłoki exit, kończące działanie programu powłoki. Polecenie exit powinno przyjmować jeden opcjonalny parametr, będący statusem wyjścia zwracanym do procesu rodzica"
Z tego co rozumiem w "przyjmować polecenia odwołujące się przez nazwę do skryptów i programów znajdujących się w katalogach opisanych wartością zmiennej
środowiskowej PATH oraz umożliwiać wywołanie tych skryptów i programów z argumentami" i w "przyjmować polecenia odwołujące się przez ścieżki względne oraz bezwzględne do skryptów i programów znajdujących się na dysku komputera, a także umożliwiać ich wywołanie z argumentami" chodzi o to, żeby funkcje komend były w osobnych plikach, a w main były tylko odwołania do lokalizacji?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

int main()
{
    while(1){

    //Znak zachety

    char path[PATH_MAX];
    getcwd(path, sizeof(path));
    printf("%s~$ ", path);

    ////////////////////////////////

    char polecenie[150];
    int isHelp, isCd, isCd1, isExit, isExit1, isFread;

    scanf("%150s", polecenie);

    isExit = strcmp(polecenie, "exit");
    isExit1 = strcmp(polecenie, "exit-u");
    isCd = strcmp(polecenie, "cd");
    isCd1 = strcmp(polecenie, "cd-");
    isHelp = strcmp(polecenie, "help");

    if(isExit==0){
    exit(0);
    }

    else if(isExit1==0){
    exit(1);
    }

    else if(isCd==0 || isCd1==0){
    printf("Podaj lokalizacje: ");
    char cd_path[PATH_MAX];
    scanf("%s",cd_path);
    if(!strncmp(path,cd_path, sizeof cd_path)){
    chdir(cd_path);
    } else{
    char* strcat(char* path, const char* cd_path);
    chdir(cd_path);
    }
    }

    else if(isHelp==0){
    printf("Shell\n");
    printf("Autor: \n");
    printf("\n");
    printf("Polecenia:\n");
    printf("help - pomoc\n");
    printf("exit - wyjscie\n");
    printf("exit-u - wyjscie zakonczonie niepowodzeniem\n");
    printf("cd - zmiana katalogu\n");
    }

    else{
        printf("Bledne polecenie!\n");
    }
    }
    return 0;
}
0

Z tego co znalazłem w necie wynika, że nie można użyć system("exit"), a zamiast tego jest exit(int kod błędu)

0

Mam coś takiego, ale prev_path wypisuje jakieś dziwne ciągi. Kiedy wypisuję current_path i prev_path to wszystko jest ok, ale później nie działa :/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

int main()
{
    char path_home[PATH_MAX];
    char path[PATH_MAX];
    getcwd(path_home, sizeof(path_home));
    char prev_path[PATH_MAX];
    char current_path[PATH_MAX];
    char cd_path[PATH_MAX];
    while(1){

    //Znak zachety

    getcwd(path, sizeof(path));
    printf("%s~$ ", path);
    ////////////////////////////////
    getcwd(current_path, sizeof(current_path));

    char polecenie[150];
    int isHelp, isCd, isExit, isExit1, isFread;

    scanf("%150s", polecenie);

    isExit = strcmp(polecenie, "exit");
    isExit1 = strcmp(polecenie, "exit-u");
    isCd = strcmp(polecenie, "cd");
    isHelp = strcmp(polecenie, "help");

    if(isExit==0){
    exit(0);
    }

    else if(isExit1==0){
    exit(1);
    }

    else if(isCd==0){
    printf("Podaj lokalizacje: ");
    scanf("%s",cd_path);
    if(strncmp(current_path,cd_path, sizeof cd_path)!=0)
    {
        char* strcpy(char* prev_path, const char* prev_current);
        printf("%s\n",prev_path);
    }
    if(strncmp("cd-",cd_path,3)==0)
    {
        chdir(prev_path);
    }
    else if(strncmp("cd",cd_path,2)==0)
    {
        chdir(path_home);
    }
    else if(!strncmp(path,cd_path, sizeof cd_path)){
    chdir(cd_path);
    } else{
    char* strcat(char* path, const char* cd_path);
    chdir(cd_path);
    }
    }

    else if(isHelp==0){
    printf("Shell\n");
    printf("Autor:\n");
    printf("\n");
    printf("Polecenia:\n");
    printf("help - pomoc\n");
    printf("exit - wyjscie\n");
    printf("exit-u - wyjscie zakonczonie niepowodzeniem\n");
    printf("cd - zmiana katalogu\n");
    }

    else{
        printf("Bledne polecenie!\n");
    }
    }
    return 0;
}
0

Czym jest i po co jest każda z tych zmiennych?

    char path_home[PATH_MAX];
    char path[PATH_MAX];
    char prev_path[PATH_MAX];
    char current_path[PATH_MAX];
    char cd_path[PATH_MAX];

Podziel ten program na jakieś funkcje.

0

char path_home[PATH_MAX]; - ścieżka do katalogu głównego;
char path[PATH_MAX]; - aktualna lokalizacja (do wyświetlania znaku zachęty)
char prev_path[PATH_MAX]; - poprzednia lokalizacja ( do cd- )
char current_path[PATH_MAX];- aktualna lokalizacja ( do cd- )
char cd_path[PATH_MAX]; - tablica do wpisania lokalizacji lub cd, cd- (scanf("%s",cd_path);)

Nie podzieliłem kodu, ponieważ wtedy coś się sypie przy cd. :(
Zamiast tego usunąłem kilka zmiennych, które były bezsensowne.
Jak mogę przekopiować wartość current_path do prev_path?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

int main()
{
    char path_home[PATH_MAX];
    char path[PATH_MAX];
    getcwd(path_home, sizeof(path_home));
    char prev_path[PATH_MAX];
    char current_path[PATH_MAX];
    char cd_path[PATH_MAX];
    while(1){

    //Znak zachety

    getcwd(path, sizeof(path));
    printf("%s~$ ", path);
    ////////////////////////////////
    getcwd(current_path, sizeof(current_path));

    char polecenie[150];
    scanf("%150s", polecenie);

    if((strcmp(polecenie, "exit"))==0){
    exit(0);
    }

    else if((strcmp(polecenie, "exit-u"))==0){
    exit(1);
    }

    else if((strcmp(polecenie, "cd"))==0){
    printf("Podaj lokalizacje: ");
    scanf("%s",cd_path);
    if(strncmp(current_path,cd_path, sizeof cd_path)!=0)
    {
        char* strcpy(char* prev_path, const char* prev_current);
        printf("%s\n",prev_path);
    }
    if(strncmp("cd-",cd_path,3)==0)
    {
        chdir(prev_path);
    }
    else if(strncmp("cd",cd_path,2)==0)
    {
        chdir(path_home);
    }
    else if(!strncmp(path,cd_path, sizeof cd_path)){
    chdir(cd_path);
    } else{
    char* strcat(char* path, const char* cd_path);
    chdir(cd_path);
    }
    }

    else if((strcmp(polecenie, "help"))==0){
    printf("Shell\n");
    printf("Autor: Jakub Wieczorek\n");
    printf("\n");
    printf("Polecenia:\n");
    printf("help - pomoc\n");
    printf("exit - wyjscie\n");
    printf("exit-u - wyjscie zakonczonie niepowodzeniem\n");
    printf("cd - zmiana katalogu\n");
    }

    else{
        printf("Bledne polecenie!\n");
    }
    }
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0