LINUX.ORG.RU

Разработка своего shell'a

 ,


0

1

Добрый день!
Помогите люди добрые полному нубу в программинге!
Короче, есть небольшая программа - shell. Вот ее код:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#define MAXLINE 256
#define MAXPATH 256
#define MAXARGS 25
#define HASHSIZE 101
struct hashList {
    struct hashList *next;
    char *szCommand;
    char *szFullPath;
};
static struct hashList *hashTable[HASHSIZE];
/* hash:  form hash value for a command name */
unsigned hash(char *szCommand) {
    int i=0, sum=0;
    while(szCommand[i]) sum += szCommand[i++];
    return sum % HASHSIZE;
}
/* hashFind:  find command in hash table */
struct hashList *hashFind(char *szCommand) {
    struct hashList *hp;
    for(hp=hashTable[hash(szCommand)]; hp !=NULL; hp=hp->next)       
        if(strcmp(szCommand, hp->szCommand)==0) return hp;
    return NULL;    /* not found */
}
/* hashInsert:  insert command and path in hash table */
struct hashList *hashInsert(char *szCommand, char *szFullPath) {
    struct hashList *hp;
    unsigned hashVal;
    if((hp=hashFind(szCommand))==NULL) {  /* not found */
        hp=(struct hashList *)malloc(sizeof(*hp));
        if(hp==NULL || (hp->szCommand = strdup(szCommand))==NULL
           || (hp->szFullPath = strdup(szFullPath))==NULL)
               return NULL;    /* Couldn't add the hash entry */
        hashVal=hash(szCommand);
        hp->next = hashTable[hashVal];
        hashTable[hashVal]=hp;
    }
    return hp;
}
int main() {
    const char *szPrompt = "msh> ";
    char sInputBuf[MAXLINE];
    char szFilePath[MAXPATH];
    char *szDirPath;
    char *szEnvPath=strdup(getenv("PATH"));
    char *szCommand;
    char *szArgs[MAXARGS];
    DIR *dp;
    struct dirent *d;
    struct stat statBuf;
    struct hashList *hp;
    int i, status;
    pid_t pid;
    /* Scan PATH directories and add commands to hash table */
    szDirPath=strtok(szEnvPath, ":");
    while( szDirPath != NULL ) {
        if((dp=opendir(szDirPath)) != NULL) {
            while((d=readdir(dp))) {
                if(d->d_ino != 0) {
                    strcpy(szFilePath, szDirPath);
                    strcat(szFilePath, "/");
                    strcat(szFilePath, d->d_name);
                    if(lstat(szFilePath, &statBuf) >= 0)
                        if(S_ISREG(statBuf.st_mode) && access(szFilePath,X_OK)==0)
                            hashInsert(d->d_name, szFilePath);
                }
            }
            closedir(dp);
        }
        szDirPath = strtok(NULL, ":");
    }
    /* Get commands until Ctrl-D */
    fputs(szPrompt, stdout);                 /* Prompt for command input */
    while( fgets(sInputBuf, MAXLINE, stdin) != NULL ) {
        /* Parse command line arguments */
        szArgs[i=0] = strtok(sInputBuf, " \n");
        while( i<MAXARGS && szArgs[i] != NULL ) szArgs[++i] = strtok(NULL, " \n");
        if(szArgs[0] == NULL) szCommand = NULL;
        else {     /* Find path to command */
            if(strchr(szArgs[0], '/') != NULL) szCommand=szArgs[0];  /* path given */
            else {   /* look up full command path in hash table */
                if((hp=hashFind(szArgs[0])) != NULL) {                
                    szCommand=hp->szFullPath;
                } else {
                    szCommand = NULL;
                    fprintf(stderr, "%s: command not found.\n", szArgs[0]);
                }
            }
        }
        if(szCommand != NULL) {
            /* Fork and execute command, wait for completion */
            if((pid=fork()) < 0) {            /* Error */
                perror("Error in fork()");
                exit(1);
            } else if(pid == 0) {   /* run command in child process */
                execv(szCommand, szArgs);
                /* Reach here only if the command would not exec */
                perror(szCommand);    
                exit(1);
            }
            if(waitpid(pid, &status, 0) == -1) {
                perror("Error in waitpid()");
                exit(1);
            }
        }
        fputs(szPrompt, stdout);  /* Prompt for next command */
    }
    fputc('\n', stdout);
    return 0;
}

Что сюда нужно добавить, чтобы shell реагировал на команды?
Например, при вводе команды exit, shell прекращает работу.
Если кто знает, подскажите, пожалуйста.

1. пишешь грамматику описывающую язык комманд твоего шелла
2. генерируешь парсер
3 ....
4. PROFIT!

invy ★★★★★
()
Ответ на: комментарий от arssenia

Я думал, в этот код просто можно добавить обработчик вводимых слов.

Это оно и есть.

Zhbert ★★★★★
()

Технический ЛОР такой технический. Неужели вы не нашли хоть какой-то документации по этой теме?

vapor
()
Ответ на: комментарий от arssenia

Неужели? Ну это-то то явно не твой код, да и вообще это похоже на задание для вуза типа «измените так чтобы...».

А так... амени char *szFullPath на int (*cmdPtr)(char **,int); и добавь свой команды с обработчиками их.

invy ★★★★★
()
Ответ на: комментарий от vapor

Нашел, этот пример и есть из докуменатации...

arssenia
() автор топика

сердце мое обливается жир^W кровью при виде польской записи в юниксе.

еще хеш-функция быдловатая.

anonymous
()

Пишешь парсер, советую, регулярными выражениями. Обрабатываешь результат.

eb
()
Ответ на: комментарий от eb

Пишешь парсер, советую, регулярными выражениями

Улетай отсюда.

anonymous
()

В МГУ это, кстати, то ли во втором, то ли в третьем семестре делают, спроси знакомых ВМК-шников.

undertaker ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.