Własny shell - pomoc

Odpowiedz Nowy wątek
2019-01-01 17:09
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;
}

Pozostało 580 znaków

2019-01-01 18:47
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.

edytowany 2x, ostatnio: elwis, 2019-01-01 18:48

Pozostało 580 znaków

2019-01-01 19:06
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

Pozostało 580 znaków

2019-01-01 19:55
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

edytowany 1x, ostatnio: Linux_jest_zly, 2019-01-01 20:03

Pozostało 580 znaków

2019-01-01 20:01
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.

Pozostało 580 znaków

2019-01-02 19:19
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;
}
Raczej chodzi o wywoływanie funkcji typu exit() i system() z odpowiednimi parametrami - Delor 2019-01-02 19:48

Pozostało 580 znaków

2019-01-02 20:08
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)

Pozostało 580 znaków

2019-01-03 19:44
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;
}
widziałem już system("cls"), system("cd xxxx"), ale system("exit") nieco przekracza moją biedną wyobraźnię - AnyKtokolwiek 2019-01-04 10:45

Pozostało 580 znaków

2019-01-03 20:26
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.

Pozostało 580 znaków

2019-01-04 18:27
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;
}
edytowany 1x, ostatnio: Linux_jest_zly, 2019-01-04 18:52

Pozostało 580 znaków

2019-01-04 21:39
0
Linux_jest_zly napisał(a):

Jak mogę przekopiować wartość current_path do prev_path?

strcpy(prev_path, current_path);

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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