Команды UNIX, реализованные в C - PullRequest
2 голосов
/ 18 февраля 2012

Для моего класса «Операционные системы» у меня есть назначение, которое встроено в предыдущее назначение.К сожалению, мой предыдущий проект не работает правильно, кроме того, я не знаю, с чего мне начать следующий проект.Приведенный ниже код должен имитировать простую оболочку UNIX / Linux с некоторыми дополнительными командами, которые нельзя выполнить с помощью execvp: фоновая обработка с помощью оператора ampersand, команда оболочки 'jobs': перечислить pids всех живых дочерних процессов (т. е. не завершившихся), «пожинает» процессы «зомби» и команду оболочки «cd»: изменить рабочий каталог оболочки.

Я считаю, что все, кроме команды «jobs», и «CD "команда работает, но я не уверен, почему эти два не.

Следующим назначением является добавление некоторого перенаправления ввода-вывода в форме «mysh $ cmd arg1 arg2 argN> file.out», которое я не знаю, где вообще начинать ...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
#include <sys/types.h>

int main(int argc, char **argv) {
    char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
    int jobs[100];
    int jobList = 0;
    int background;
    ssize_t rBytes;
    int aCount;
    pid_t pid;
    int status;
    while(!feof(stdin)) {
        pid = waitpid(-1, &status, WNOHANG);
        if (pid > 0)
        printf("waitpid reaped child pid %d\n", pid);
        write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
        rBytes = read(0, bBuffer, BUFSIZ-1);
        if(rBytes == -1) {
        perror("read");
        exit(1);
    }

    bBuffer[rBytes-1] = '\0';
    if(!strcasecmp(bBuffer, "exit")){ 
        exit(0);
    }

    sPtr = bBuffer;
    aCount = 0;
    do {
        aPtr = strsep(&sPtr, " ");
        pArgs[aCount++] = aPtr;
    } while(aPtr);
        background = (strcmp(pArgs[aCount-2], "&") == 0);
        if (background)
        pArgs[aCount-2] = NULL;

        if (strlen(pArgs[0]) > 1) {
            pid = fork();
            if (pid == -1) {
                perror("fork");
                exit(1);
            } else if (pid == 0) {
                jobs[jobList] = pid;
                jobList++;

                if(!strcasecmp(pArgs[0], "jobs")){                                         
                    for(int i; i<jobList; i++) {
                        if(kill(jobs[i],0)==0){
                            printf(jobs[i]);    
                        }
                        printf("these are jobs\n");
                        exit(1);
                    }
                    if(!strcasecmp(pArgs[0], "cd")){ 
                        int ret;
                        if (!pArgs[1])
                            strcpy(bBuffer, "pwd");
                        ret = chdir(pArgs[1]);
                        strcpy(bBuffer, "pwd");
                        exit(1);
                    }                                
                    fclose(stdin);
                    fopen("/dev/null", "r");
                    execvp(pArgs[0], pArgs);
                    exit(1);
                } else if (!background) {
                    pid = waitpid(pid, &status, 0);
                    if (pid > 0)
                        printf("waitpid reaped child pid %d\n", pid);
                }
        }
    }
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 18 февраля 2012

Сначала вы захотите проанализировать свою строку и определить, что вам нужно перенаправить в файл. Итак, давайте скажем, что вы используете strsep или что-то еще, и вы обнаружили, что вывод будет file.out или ввод поступит с file.in.

На данный момент вы хотите перенаправить вывод, используя dup / dup2. Например, для перенаправления STDOUT:

int
do_redirect(int fileno, const char *name)
{
    int newfd;

    switch (fileno) {
    case STDOUT_FILENO:
        newfd = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IRUSR);
        break;
    }
    if (newfd == -1) {
        perror("open");
        return -1;
    }

    return dup2(fileno, newfd);
}
/* ... */


pid = fork();
do_redirect(STDOUT_FILENO, name);

Что следует отметить:

  • Я не тестировал код - он может даже не скомпилироваться
  • Я не делал много проверок на ошибки - вы должны (как я сделал для open)
  • Вам необходимо самостоятельно выполнить STDIN_FILENO перенаправление
  • Обратите внимание, как я использовал отдельную функцию, ваш main ПУТЬ к большому, как
  • Ваш код имеет примерно 7 уровней отступа - когда-либо слышали о код стрелки ?
0 голосов
/ 18 февраля 2012

Поскольку это домашнее задание, я не буду давать вам код напрямую.

dup, dup2 и freopen хорошо подходят для перенаправления ввода / вывода.

fork для запуска параллельного процесса (амперсанд)

Вы на правильном пути, используя waitpid для получения дочерних процессов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...