パーソナルツール
現在の場所: ホーム オペレーティングシステム論 演習 2006年度 第1回 exsh-1.c
文書操作

exsh-1.c

作成者 管理者 最終変更日時 2007年04月22日 00時00分

Click here to get the file

サイズ 3.0 kB - File type text/x-csrc

ファイルのコンテンツ

/* 
 * $Id: exsh-1.c,v 1.15 2006/05/27 14:51:17 yamamoto Exp yamamoto $
 * 
 * (C) Copyright:       S.Yamamoto  2006
 *                      This file is a product of the project Exsh.
 */

#include <stdarg.h>             /* For variable argument lists. */
#include <stdio.h>
#include <stdlib.h>             /* For EXIT_SUCCESS. */
#include <sys/types.h>          /* For pid_t. */
#include <sys/wait.h>           /* For waitpid(). */
#include <unistd.h>             /* For execl() family. */

#ifndef FALSE
#define FALSE           0
#define TRUE            1
#endif

#define MAX_INPUT       81      /* 入力の最大長(NULL terminatorを含む). */

static int      debug_mode = FALSE;

static void debug(const char *format, ...);

int main(int argc, char *argv[])
{
    char        input[MAX_INPUT];       /* 入力行. */
    int         status;                 /* 子プロセスの状態. */
    pid_t       pid;                    /* プロセス番号. */

    /* 簡易オプション解析(本来ならgetopt()を使うこと). */  
    if (2 <= argc && !strcmp(argv[1], "-d")) {
        debug_mode = TRUE;
    }

    debug("getpid() %d.\n", getpid());
    while (TRUE) {
        if (isatty(fileno(stdin))) {    /* 端末の場合だけプロンプト出力. */
            fputs("> ", stderr);
        }

        gets(input);                    /* 1行入力. */
        if (feof(stdin)) {              /* EOF (end of file)状態の場合. */
            exit(EXIT_SUCCESS);
        }
        debug("\"%s\".\n", input);

        if (input[0] == '\0') {         /* 空文字列の場合. */
            continue;
        } if (!strcmp(input, "exit")) { /* 終了コマンドの場合. */
            exit (EXIT_SUCCESS);
        }

        pid = fork();                   /* プロセスをforkする(分身の術). */
        if (pid < 0) {                  /* fork()に失敗. */
            perror(NULL);
        } else if (pid == 0) {          /* 子プロセス. */
            int     retval;
            
            debug("Child: getpid() %d, fork() %d.\n", getpid(), pid);
            retval = execlp(input, input, NULL);    /* コマンド実行(変身の術). */
            perror(input);              /* execlp()に失敗. */
            exit(EXIT_FAILURE);
        } else {                        /* 親プロセス. */
            debug("Parent: getpid() %d, fork() %d.\n", getpid(), pid);
            waitpid(pid, &status, 0);   /* 子プロセスの終了待ち. */
        }
    }

    exit (EXIT_SUCCESS);
}

/* 
 * 可変個の引数を持つデバッグ出力.
 * 
 * C99なら可変個の引数を持つマクロも使用可能.
 * #define debug(format, ...) \
 *         if (debug) fprintf(stderr, "Debug: " format, __VA_ARGS__)
 */

static void debug(const char *format, ...)
{
    va_list     args;
    
    if (!debug_mode) {
        return;
    }

    fflush(stdout);
    fflush(stderr);

    fputs("Debug: ", stderr);
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);

    fflush(stderr);
}