Skocz do zawartości

Temat został przeniesiony do archiwum

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

martolo

Zadanie w linuxie

Rekomendowane odpowiedzi

Zadanie polega na wykorzystaniu języka ANSI C do napisania prostego programu powłoki – Microshell. Program ten powinien przyjmować na wejściu polecenia, a następnie wykonywać działania zgodne z ich treścia. Powłoka powinna:

 

punkty opis

1,0 pkt wyświetlać znak zachęty w postaci [{path}] $, gdzie {path} jest scieżką do bieżącego katalogu roboczego

1,0 pkt obsługiwać polecenie cd, działające analogicznie do tego znanego nam z powłoki bash

0,5 pkt. obsługiwać polecenie exit, kończące działanie programu powłoki

0,5 pkt. obsługiwać polecenie help, wyświetlające na ekranie informacje o autorze programu i oferowanych przez niego funkcjonalnościach

2,0 pkt. obsługiwać dwa inne, dowolnie wybrane polecenia powłoki (chodzi tutaj np. o własną, samodzielną, prostą implementację dwóch poleceń)

2,0 pkt. przyjmować polecenia odwołujące się przez nazwę do skryptow i programów znajdujacych się w katalogach opisanych wartoscią zmiennej środowiskowej PATH oraz umożliwiać wywołanie tych skryptów i programów z argumentami

1,0 pkt wypisywać komunikat błędu, gdy niemożliwe jest poprawne zinterpretowanie polecenia

2,0 pkt. posiadać tzw. dodatkowe bajery (w zależności od stopnia skomplikowania problemu), np. wyświetlanie loginu aktualnie zalogowanego użytkownika, obsługę kolorów, obsługę argumentów w cudzysłowach, sensowną obsługę sygnałów (np. Ctrl+Z), obsługę historii poleceń, uzupełnianie składni, itp.

 

Z powodów niezależnych ode mnie opuściłam lwią część zajęć i nie mam pojęcia jak się zabrać za to zadanie. Nie proszę o napisanie za mnie kodu, a o pomoc i naprowadzenie w dobrą stronę. ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość Nareszcie

Zatem naprowadzenie.

Masz do napisania program w C, ktory dzialajac w petli bedzie pobieral polecenie, parsowal je, przesylal do systemu operacyjnego i wyswietlal otrzymany wynik.

Na poczatku zacznij od napisania programu, ktory wykona punkt 4 - obsluga polecenia help. Na oko dziesiec linijek kodu, ktory pozniej musisz skompilowac i uruchomic. Wiesz jak to zrobic?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie wiem czy jest to optymalne, ale działa :P

 

#include <unistd.h>
#include <stdio.h>
#include <stdio.h>
int main()
{
char polecenie[100];
do
{
gets(polecenie);
if(strcmp(polecenie,"help")==0)
{
printf("informacje blablabla iformacje\n");
printf("informacje blablabla iformacje\n");
printf("informacje blablabla iformacje\n");
}
} while(strcmp(polecenie,"koniec"));
return 0;
}

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość Nareszcie

Jak na pierwsza wersje jest dobrze.

To teraz trzy zadania:

1. Przepisz program z uzyciem konstrukcji switch / case;

2. Zapoznaj sie z funkcjami "system", "exec" oraz "execl" i uzyj jednej z nich do wykonania polecenia pierwszego. Czesc z nich moze wymagac zalaczenia bibliotego stdlib.h albo innej;

3. Zastap slowo "koniec" slowemn "exit", by spelnic wymagania punktu trzeciego.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie potrafię napisać tego programu z użyciem switch. Przy kompilacji wyskakuje błąd, ponieważ chce wartości jako liczby, a ja podaję mu cale słowa. Szukałam odpowiedzi w internecie i znalazłam tylko użycie tej instrukcji dla pojedynczych znaków a nie całych słów. Aktualnie mój program wyglada tak:

 

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

#define BUFFER_SIZE 1024

int system(const char *string);
int strcmp(const char *s1, const char *s2);


int main()
{
char polecenie[100];
do
{
printf("{");
system("pwd");
printf("} $");

fgets(polecenie, sizeof(polecenie), stdin);
if(strcmp(polecenie,"help")==0)
{
printf("informacje o autorze\n");
}
} while(strcmp(polecenie,"exit"));
return 0;
}

 

Exit nie zatrzymuje dzialania programu,a help nie wyświetla informacji o autorze. :/

Program wypisuje dobrą ścieżkę, ale nie mogę ująć ścieżki w dwie klamry żeby to było w jednej linii. Jak to naprawić?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Pokaż jak próbowałeś użyć switcha i jaki konkretnie błąd kompilator wyświetlił.

 

Odnośnie tego wyżej, to na początek sprawdź co fgets wczytuje

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

1) switch działa tylko dla typów całkowitych (char, int, long itp.) a C-string to tablica

2) używaj funkcji

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

1) switch działa tylko dla typów całkowitych (char, int, long itp.) a C-string to tablica

2) używaj funkcji

 

Nie do końca rozumiem jakiej funkcji mam użyć. Skoro switch nie działa dla tablic, to go sobie odpuścić?

Wpisałam fgets, ponieważ samo gets mogło przekroczyć rozmiar bufora, czy coś takiego. :/

Nie wiem co teraz, aktualnie dla linuxa nie działa nic, bo nawet aktualna scieżka nie jest w tych klamrach. Wygląda to tak:

{

SCIEŻKA

} $

 

Chyba nie tak to powinno wyglądać :/

 

EDIT: Dopisałam printf za fgets zeby sprawdzic co wczytuje i jest ok, jako polecenie jest zapamiętywane to co wpiszę.

 

EDIT 2: Udało się naprawić działanie wyswietlania sciezki, help i exit. Kod wyglada teraz tak:

 

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

#define BUFFER_SIZE 1024

int system(const char *string);
int strcmp(const char *s1, const char *s2);


int main()
{
char polecenie[100];
char cwd[1000];
do
{
getcwd(cwd,sizeof(cwd));
printf("{");
printf("%s",cwd);
printf("} $");

fgets(polecenie, sizeof(polecenie), stdin);
if(strcmp(polecenie,"help"))
{
printf("informacje o autorze\n");
}
} while(strcmp(polecenie,"exit")==0);
return 0;
}

 

EDIT 3: ODWOŁUJE, DZIAŁA TYLKO POKAZYWANIE ŚCIEŻKI

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

fgets wczytuje znak(i) nowej linii, który jest uwzględniany przy porównaniu.

Na chama można w warunkach dodać \n Lepiej jednak będzie się pozbyć tego dodatkowego znaku (lub znaków, kwestia systemu).

Proste ale nie uniwersalne: if(polecenie[strlen(polecenie) - 1] == '\n') polecenie[strlen(polecenie) - 1] = 0;

 

Niepoprawne warunki przy if i while.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wow, dziękuję bardzo.

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

#define BUFFER_SIZE 1024

int system(const char *string);
int strcmp(const char *s1, const char *s2);


int main()
{
char polecenie[100];
char cwd[100];
do
{
getcwd(cwd,sizeof(cwd));
printf("{");
printf("%s",cwd);
printf("} $");
fgets(polecenie, sizeof(polecenie), stdin);
if(polecenie[strlen(polecenie) - 1] == '\n') polecenie[strlen(polecenie) - 1] = 0;
if(strcmp(polecenie, "help")==0)
{
printf("informacje o autorze\n");
}
} while(strcmp(polecenie,"exit")!=0);
return 0;
}

 

Teraz polecenia działają, więc 3 z 8 wymagań programu jest spełnionych, szkoda tylko, że to 3 najprostsze polecenia. :(

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Od czegoś trzeba zacząć :)

 

Proponuję uprościć wypisywanie znaku zachęty. Nie ma sensu robić tego na 3 printfach, jak można to ogarnąć jednym.

Działanie polecenia help dobrze jest zamknąć w funkcji.

 

Przerobiłbym pętlę, tak żeby działała w nieskończoność, a interpretacja polecenia była w zestawie/drabince if-ów. Wydaje mi się, że wtedy będzie można łatwiej zaimplementować wypisanie informacji o błędnym poleceniu. W tym celu można zrobić drabinkę if-ów (pseudokod):

if(komenda1) wykionaj1;
else if(komenda2) wykonaj2;
else if(komenda3) wykonaj3;
else nie_znam_polecenia;

Będzie to przynajmniej 0,5 punktu za przedostatnie zadanie. Nie wiem jakie są wymagania prowadzącego, czy wystarczy sama informacja o błędnej składni/nieznanym poleceniu, czy ma być dokładniej sprawdzane np. niepoprawne argumenty do polecenia i wypisanie poprawnej składni.

 

Do przerwania nieskończonej pętli można użyć polecenia break lub po prostu return czy exit. Do doczytania co dokładnie robią.

 

Program dosyć łatwo rozbudować o wypisywanie loginu użytkownika, wystarczy użyć funkcji getlogin_r, podobnie do getcwd.

 

Następnie zająłbym się chyba obsługą polecenia cd, bo to też wstęp do bardziej skomplikowanych.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Proponuję uprościć wypisywanie znaku zachęty. Nie ma sensu robić tego na 3 printfach, jak można to ogarnąć jednym.

Zrobione :)

Działanie polecenia help dobrze jest zamknąć w funkcji.

Ale nie jest to konieczne? Jadę po najmniejszej linii oporu :cool:

Przerobiłbym pętlę, tak żeby działała w nieskończoność, a interpretacja polecenia była w zestawie/drabince if-ów. Wydaje mi się, że wtedy będzie można łatwiej zaimplementować wypisanie informacji o błędnym poleceniu.

Jest!

Do przerwania nieskończonej pętli można użyć polecenia break lub po prostu return czy exit. Do doczytania co dokładnie robią.

Zrobione!

Program dosyć łatwo rozbudować o wypisywanie loginu użytkownika, wystarczy użyć funkcji getlogin_r, podobnie do getcwd.

To również sie udało!

Następnie zająłbym się chyba obsługą polecenia cd, bo to też wstęp do bardziej skomplikowanych.

I tu się zaczynają prawdziwe schody. Czytałam o tym nieco, zrobiłam nawet swoją wersję, jednak działała w taki sposób, że najpierw wpisywało się "cd" a potem w kolejnej linii do jakiego folderu chce się przenieść. Także zalatuje biedą. ;'(

 

Obecny program:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 1024

int system(const char *string);
int strcmp(const char *s1, const char *s2);
int chdir(const char *path);
int getlogin_r(char *buf, size_t bufsize);

int main()
{
printf("\n\n         Witaj w moim programie microshell! Jesli potrzebujesz pomocy-wpisz help\n\n\n");

char polecenie[100];
char cwd[100];
char login[100];

while(1)
   {
   getcwd(cwd,sizeof(cwd));
   printf("{%s}$",cwd);
   fgets(polecenie, sizeof(polecenie), stdin);
   if(polecenie[strlen(polecenie) - 1] == '\n') polecenie[strlen(polecenie) - 1] = 0;
   if(strcmp(polecenie, "help")==0) printf("informacje o autorze\n");
   else if(strcmp(polecenie, "login")==0){ getlogin_r(login,sizeof(login)); printf("%s\n",login);}
   else if(strcmp(polecenie,"exit")==0) return 0;
   else printf("Bledne polecenie.\nDostepne opcje programu- wpisz help\n");
   }
return 0;
}

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Z tym loginem, to nie wiem czy nie chodziło, żeby wyświetlał się ze znakiem zachęty.

 

Z cd i innymi poleceniami z argumentami można różnie podejść:

-na chama dajesz w warunku czy pierwsze litery napisu pasują (przy dłuższych trochę uciążliwe w pisaniu)

-korzystasz z funkcji wyszukujących na stringach (np. strstr) czy dane polecenie znajduje się w pobranym napisie i czy znajduje się na początku

-dzielisz napis na kawałki (np. strtok) i sprawdzasz po kolei co i jak

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ogarnęłam login przy znaku zachety, ale poza cd nie wiem jakie inne polecenia moze ta powłoka wykonywać :mad:

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

A jakie chcesz żeby wykonała? :Up_to_s:

Nie chciałbym niczego narzucać, pomyśl przez chwilę jakie polecenia w takiej powłoce by się przydały. Jak już masz zmianę katalogu czy zaraz będziesz miał, to kolejne polecenie wręcz samo się nasuwa.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli jest(a właściwie może będzie, postaram się podołać) zmiana katalogu... To jakieś kopiowanie/przenoszenie pliku do innego katalogu?

 

EDIT: Nie wiem, siedze pare godzin i załamuję ręce. Termin oddania projektu sie zbliza a ja mam prawie nic.

 

Próbowałam coś dodać, szukałam w internecie, to co dodalam wyroznilam odstępami. POMOCY NIE DZIAŁA

 

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


#define BUFFER_SIZE 1024

int strcmp(const char *s1, const char *s2);
int chdir(const char *path);
int getlogin_r(char *buf, size_t bufsize);
char* strstr (const char* str1, const char* str2);
char *strcat (char* strTo, const char* strFrom);

void  p(char *polecenie, char **argv);

int main()
{
printf("\n\n     Witaj w moim programie microshell! Jesli potrzebujesz pomocy-wpisz help  \n\n\n");

char polecenie[100];
char cwd[100];
char login[100];
char  *gdir;
char  *dir;
char  *to;
char buf[100];
char *argv[bUFFER_SIZE];

while(1)
   {
   getcwd(cwd,sizeof(cwd));
   getlogin_r(login,sizeof(login));
   printf("{%s}%s$ ",cwd,login);
   fgets(polecenie, sizeof(polecenie), stdin);
   if(polecenie[strlen(polecenie) - 1] == '\n') polecenie[strlen(polecenie) - 1] = 0;


   p(polecenie, argv);


   if(strcmp(polecenie, "help")==0) printf("exit- wyjscie z programu\n");

   if(strstr(argv[0], "cd")!=NULL)
   {
       gdir = getcwd(buf, sizeof(buf));
       dir = strcat(gdir, "/");
       to = strcat(dir, argv[1]);

       chdir(to);
       continue;
   }


   else if(strcmp(polecenie,"exit")==0) exit(0);
   else printf("Bledne polecenie.\nDostepne opcje programu- wpisz help\n");
   }
}

 

EDIT2: Kolega mi podpowiedział żeby rozbić polecenie na pojedyncze wyrazy z uzyciem warunku while(line!=10), ktory oznacza end of line w kodzie ascii, ale nie do konca wiem jak to podzielić...

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Takie pytanka:

-po co deklarujesz funkcje, które są definiowane w dołączonych nagłówkach?

-gdzie jest implementacja funkcji p, co ta funkcja ma robić?

 

Odnośnie poleceń, to myślałem nad wyświetleniem zawartości katalogu.

Kopiowanie pliku nie jest trudne ale musisz z polecenia wyciągnąć 2 argumenty. Chyba łatwiej zrobić wyświetlenie zawartości pliku.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

  • Popularne aktualnie

  • Tematy

  • Odpowiedzi

    • Całe szczęście. Ja bym poszedł jeszcze dalej - zlikwidował te RODy, które są w dobrych lokalizacjach i pobudował tam osiedla. 
    • Jestem bardzo na nie. Wymęczyłem się do połowy drugiego odcinka. [uwaga, lekkie spoilery] To nie jest serial, to jest zestaw przydługich teledysków z losowymi scenami mającymi tylko zaakcentować charakterystyczne elementy z gier. Tępa jak maszynka do golenia z promocji na aliexpress laska wychodzi ze swojej nory, w której jej klan spędził ostatnie kilkaset lat, ot tak sobie i nagle to wywołuje heheheszki na całego, bo joj, ma niebieski kostium! Mimo że zachowuje się jak upośledzona, nic kompletnie nic jej nie zagraża na ziejącym promieniowaniem, wypełnionym szkieletami i mutantami terenie. Wielki rycerz Braterstwa Stali ma problemy z wielkim, zmutowanym misiem, ale na szczęście jego giermek załatwia misia jednym strzałem ze starożytnego rewolweru. Przed genetycznym laboratorium stoją wieżyczki gatlinga, ale nie są w stanie trafić w szybko idącego przed nimi staruszka.  Scenariusz tego dzieła jest tak prosty, że gierki, na które przecież narzekano, przy nim są historiami wartymi nagród literackich. Całość wypełniona jest stereotypowymi "dads jokes". Mimo że serial jest wypełniony zwłokami, mutantami, nie ma żadnego zagrożenia, nawet nikt nie udaje że cokolwiek tępej głównej bohaterce może się przydarzyć. Żarcik za żarcikiem i tyle.  Dobitnie to przypomina, że jedynym powodem produkcji jest przyciągnięcie więcej ludzi do prime poprzez maksymalne uproszczenie wszystkiego, co można uprościć. Można obejrzeć...tylko po co?
    • Nie będziesz miał niczego i będziesz szczęśliwy 😆
    • Ubi + i po problemie, dla mnie to gra na jeden raz wiec nawet zeby absolutnie pelna wersja kosztowala 250zl i tak bym wzial +.
    • Gsync dalej ssie, migotanie w Alan Wake 2 dalej takie samo. W sumie przy ponad 70+ FPS nie widzę już rozrywania obrazu, wady wzroku mają swoje plusy  
  • Aktywni użytkownicy

×
×
  • Dodaj nową pozycję...