Skip to content

Instantly share code, notes, and snippets.

@pasali
Last active December 15, 2015 14:09
Show Gist options
  • Save pasali/5272260 to your computer and use it in GitHub Desktop.
Save pasali/5272260 to your computer and use it in GitHub Desktop.
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<readline/readline.h>
#include<readline/history.h>
#include<sys/wait.h>
/* pasali */
static char * arguments[10];
static char * komut;
void argv_free(void);
int run(void);
int parse(char *);
int
main(void)
{
while(1) {
komut = readline("#> ");
if (komut == NULL) {
exit(EXIT_SUCCESS);
}else if (!strcmp(komut, "")) {
continue;
}
else {
parse(komut);
run();
argv_free();
}
free(komut);
}
atexit(argv_free);
return 0;
}
void
CD(void)
{
if (!strcmp(arguments[1], "~") || !strcmp(arguments[1], " ") || !strcmp(arguments[1], "")) {
chdir(getenv("HOME"));
}else if (!strcmp(arguments[1], ".")) {
/* none */
}else if (!strcmp(arguments[1], "..")) {
char * parent_directory = strrchr(getenv("PWD"), '/');
char * pwd = getenv("PWD");
int index = parent_directory - pwd;
pwd[index] = '\0';
chdir(pwd);
}else
chdir(arguments[1]);
main();
}
void
argv_free(void)
{
int i;
for (i = 0; arguments[i]; i++) {
free(arguments[i]);
}
}
int
run(void)
{
int status;
pid_t pid;
pid = fork();
if (!pid) {
int ret;
if ( **arguments == '/')
ret = execv(arguments[0], arguments);
else
ret = execvp(arguments[0], arguments);
if (ret == -1) {
perror("execv");
exit(EXIT_FAILURE);
}
} else if (pid == -1)
perror("fork");
if (waitpid(-1, &status, 0) == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
return 0;
}
int
parse(char *string)
{
char ** str_p = &string;
char * token;
int len;
add_history(string);
for (len = 0; (token = strsep(str_p, " \t")); len++) {
arguments[len] = strdup(token);
}
arguments[len] = NULL;
if (!strcmp(arguments[0], "exit") || !strcmp(arguments[0], "quit")) {
exit(EXIT_SUCCESS);
}
if (!strcmp(arguments[0], "cd")) {
CD();
}
if (komut[0] != '/' && strchr(komut, '/')) {
printf("full path of program or just name !!!\n");
main();
}
return 0;
}
@pasali
Copy link
Author

pasali commented Mar 30, 2013

@roktas hocam dedikleriniz doğrultusunda kodu düzenledim. Şuan /bin/ altındaki bütün programlar için sorunsuz çalışıyor :) Şimdi PATH içinde aratma kısmını yapmaya çalışıyorum.

@roktas
Copy link

roktas commented Mar 30, 2013

  • Kritik değil ama strtok değil strsep kullan. strtok kötü bir fonksiyondur :-) (ipucu: reentrant değil) Man linki gönderdim ya sana, oradaki örneği adapte et gitsin, strtok ile niye uğraşıyorsun?
  • Kodunda hala ciddi stil sorunları var. Anahtar kelimelerden sonra boşluk bırakmamak, hatalı girintiler, girinti seviyesi (1 tab: 8 boşluk) vs.
  • fonksiyon ismini bir eylem yap: parser değil parse. Sınıf olsaydı parser olurdu ama buraya uymaz. Bakın bu isimlendirmelere dikkat edin lütfen. Çok yalap şalap isimler kullanıyorsunuz :-)
  • Ansi C üzerinden gitmeye çalış. Ansı C'de deklarasyonlar hemen işlevin girişinde yapılır, arada yapılmaz. Aşağıdaki seçeneklerle derleme yap ve uyarıları sıfırla lütfen:
$ cc -pedantic -ansi -Wall -o kabuk kabuk.c

@roktas
Copy link

roktas commented Mar 30, 2013

Readline'ı nasıl kullanıyoruz? Şu örneği de bir incele: http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC48

Nispeten kompleks bir örnek bu. Her tarafını anlamak zorunda değilsin. :-)

@pasali
Copy link
Author

pasali commented Mar 30, 2013

@roktas hocam , strsep ve fonksiyon isimlerini düzellettim. ANSI C ile ilgili uyarıları düzeltirken strdup , waitpid ve strsep için "örtük bildirim" uyarısı veriyor. Hazır fonksiyonlarında prototipini yazmak mı lazım ? Bir de tab için 4 ve ya 8 boşluk fark eder mi ? Benim gözüme 4 daha düzgün geldiği için 4 kullanıyorum :) Bu örneği bende görmüştüm add_history() yi burdan aldım. Ama nereye kaydettiğini ya da nasıl bizim verdiğimiz bir dosyaya yazacak bilmiyorum :)

@roktas
Copy link

roktas commented Mar 30, 2013

strsep ANSI'de bulunmadığından uyarı alman normal. string.h'da tanımı bulamıyor ve "örtük olarak" tanımlıyor. waitpid için ise sys/wait.h eklemen gerekir. Derlemede -ansi anahtarını kaldırarak (diğerleri kalsın) devam et.

Stil konusunda şu erken yaşlarda "gözüme bu daha hoş geldi" diyerek moda uydurmayın :-) büyükler ne yapmışsa onları izleyin. Bakın uymanız gereken stil şu:

http://www.openbsd.org/cgi-bin/man.cgi?query=style&section=9

(bu da olabilir: https://www.kernel.org/doc/Documentation/CodingStyle)

Şimdilik readline'sız tamamla, sonra ona da bakarız.

@roktas
Copy link

roktas commented Mar 30, 2013

Stil düzeltmek için:

$ sudo apt-get install astyle
$ astyle --style=linux shellim.c
$ git diff # farkı gör

@roktas
Copy link

roktas commented Mar 30, 2013

@pasali: programın ciddi bir sorunu var, bu kabuktan normal yolla nasıl çıkacağız?

  • Kullanıcı Ctrl-d tuşuna basar. Bunu nasıl yakalayacağız? Kolay, readline bu durumda NULL döner. Bunu gerçeklemen kolay.
  • Kullanıcı exit veyaquit yazar. Bunu da gerçeklemen kolay, strcmp vs ile.

Hadi bakalım bunları da bir ekle :-) Türkiye'de çalışana böyle yapıyorlar biliyorsun. Ne kadar iş yaparsan o kadar ekstra iş alırsın. :-) Bu ödevi sallayarak yatan arkadaşlara duyurulur. :-)

Aferin iyi gidiyorsun...

@pasali
Copy link
Author

pasali commented Mar 30, 2013

Teşekkürler hocam , Ctrl -d ve exit- quit i ekledim. Stilimi de değiştirmeye çalşıyorum.
Birde @roktas hocam gcc ve ya cc derleyicilerinin verdiği hataları ingilizce olarak vermesini nasıl sağlarız ? Türkçe ile bir sorunum yok ama ingilizce olunca googleda daha kolay cevap bulunuyor :)

@roktas
Copy link

roktas commented Mar 30, 2013

İngilizce mesajlar için:

$ LC_ALL=C cc ...

şeklinde derle.

@roktas
Copy link

roktas commented Mar 30, 2013

Programın exit veya Ctrl-d ile sonlanması, programın hatasız sonlanması demektir (yani exit(1) yerine exit(EXIT_SUCCES)).

@pasali
Copy link
Author

pasali commented Mar 30, 2013

Düzelttim hocam " cc -pedantic -Wall csh.c -lreadline " derleyince hata ve ya uyarı gelmiyor artık :)

@roktas
Copy link

roktas commented Mar 31, 2013

Güzel :-) Stili de düzelt artık. Bu stille nasıl rahat ediyorsun bilmiyorum. :-) astyle...

@pasali
Copy link
Author

pasali commented Mar 31, 2013

En kısa zamanda onuda hallederim inşallah :)

@roktas
Copy link

roktas commented Mar 31, 2013

Yavrum 10 sn'lik bir işlemden bahsediyoruz:

$ git clone [email protected]:5272260.git # hala klonlamamışsan
$ cd 5272260
$ astyle --style=linux *.c
$ git commit -a -m "stil düzelt"
$ git push origin master

Bundan sonra stili bozuk bir koda review yapmayacağım, notu düşüreceğim. Duyan duymayana bildirsin. Başka türlü anlatamıyorum meseleyi size.

@roktas
Copy link

roktas commented Mar 31, 2013

Peki soru? Kullanıcı programdan çıkarken kullanılan belleğin boşaltılmasını nasıl garanti altına alırız (her ne kadar İşletim Sistemi bu işlemi her sonlanan proses için yapsa bile)... İpucu: atexit

@pasali
Copy link
Author

pasali commented Apr 1, 2013

@roktas hocam, ben stili elimin alışması bakımından söylemiştim tam ifade edememişim kendimi :) Bellekle ilgili olarak argv_free() zaten istenileni yapmıyor mu hocam ? Orayı anlayamadım.

@roktas
Copy link

roktas commented Apr 2, 2013

exit işlevi çağrıldığı noktada program sonlanır; argv_free'nin çağrıldığı noktaya dikkat et ;-)

@pasali
Copy link
Author

pasali commented Apr 2, 2013

Onuda ekledim hocam. Son bir cd işlevi kaldı onu bu akşamlık pes ettim yarın o da inşallah çalışacak :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment