第8章 进程和程序:编写命令解释器sh

/*
 * prompting shell version 1
 * Prompts for the command and its arguments.
 * Builds the argument vector for the call to execvp.
 * Uses execvp(), and never returns.
 */

#include <stdio.h>
#include <signal.h>
#include <string.h>

#define MAXARGS     20      /* cmdline args */
#define ARGLEN      100     /* token length */

int main()
{
    char    *arglist[MAXARGS + 1];      /* an array of ptrs */
    int     numargs;                    /* index into array */
    char    argbuf[ARGLEN];             /* read stuff here */
    char    *makestring();              /* malloc etc */
    numargs = 0;
    while (numargs < MAXARGS)
    {
        printf("arg[%d]? ", numargs);
        if (fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n')
            arglist[numargs++] = makestring(argbuf);
        else
        {
            if (numargs > 0) {          /* any args? */
                arglist[numargs] = NULL;    /* close list */
                execute(arglist);       /* do it */
                numargs = 0;            /* and reset */
            }
        }
    }
    return 0;
}

int execute(char *arglist[])
/*
 * use execvp to do it
 */
{
    execvp(arglist[0], arglist);        /* do it */
    perror("execvp failed");
    exit(1);
}

char *makestring(char *buf)
/*
 * tim off newline and create storage for the string
 */
{
    char *cp, *malloc();

    buf[strlen(buf) - 1] = '\0';        /* trim newline */
    cp = malloc(strlen(buf) + 1);       /* get memory */
    if (cp == NULL) {                   /* or die */
        fprintf(stderr, "no memory\n");
        exit(1);
    }
    strcpy(cp, buf);                    /* copy chars */
    return cp;                          /* return ptr */
}
/*
 * forkdemo1.c
 * shows how fork creates two processes, distinguishable
 * by the different return values from fork()
 */

#include <stdio.h>

main()
{
    int ret_from_fork = 1, mypid;

    mypid = getpid();                               /* who am i? */
    printf("Before: my pid is %d\n", mypid);        /* tell the world */

    ret_from_fork = fork();

    sleep(1);
    printf("After: my pid is  %d, fork() said %d\n",
            getpid(), ret_from_fork);
}
/*
 * forkdemo2.c
 * shows how child processes pick up at the return
 * from fork() and can execute any code they like,
 * even fork(). Predict number of lines of output.
 */

main()
{
    printf("my pid is %d\n", getpid());
    fork();
    fork();
    fork();
    printf("my pid is %d\n", getpid());
}
/*
 * forkdemo3.c
 * shows how the return value from fork()
 * allows a process to determine whether
 * it is a child process
 */

main()
{
    int fork_rv;

    printf("Before: my pid is %d\n", getpid());

    fork_rv = fork();           /* create new process */

    if (fork_rv == -1)          /* check for error */
        perror("fork");
    else if (fork_rv == 0)
        printf("I am the child. my pid = %d\n", getpid());
    else
        printf("I am the parent. my child is %d\n", fork_rv);
}
/*
 * waitdemo1.c
 * shows how parent pauses until child finishes
 */

#include <stdio.h>

#define DELAY   2

main()
{
    int newpid;
    void child_code(), parent_code();

    printf("before: mypid is %d\n", getpid());

    if ((newpid = fork()) == -1)
        perror("fork");
    else if (newpid == 0)
        child_code(DELAY);
    else
        parent_code(newpid);
}

/*
 * new process takes a nap and then exits
 */
void child_code(int delay)
{
    printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
    sleep(delay);
    printf("child donee. about to exit\n");
    exit(17);
}

/*
 * parent waits for child then prints a message
 */
void parent_code(int childpid)
{
    int wait_rv;                /* return value from wait() */
    wait_rv = wait(NULL);
    printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);
}
/*
 * waitdemo2.c
 * shows how parent gets child status
 */

#include <stdio.h>

#define DELAY 10

main()
{
    int newpid;
    void child_code(), parent_code();

    printf("before: mypid is %d\n", getpid());

    if ((newpid = fork()) == -1)
        perror("fork");
    else if (newpid == 0)
        child_code(DELAY);
    else
        parent_code(newpid);
}

/*
 * new process takes a nap and then exits
 */
void child_code(int delay)
{
    printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
    sleep(delay);
    printf("child done. about to exit\n");
    exit(17);
}

/*
 * parent waits for child then prints a message
 */
void parent_code(int childpid)
{
    int wait_rv;            /* return value from wait() */
    int child_status;
    int high_8, low_7, bit_7;

    wait_rv = wait(&child_status);
    printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);

    high_8 = child_status >> 8;         /* 1111 1111 0000 0000 */
    low_7 = child_status & 0x7F;        /* 0000 0000 0111 1111 */
    bit_7 = child_status & 0x80;        /* 0000 0000 1000 0000 */
    printf("status: exit = %d, sig = %d, core = %d\n", high_8, low_7, bit_7);
}
/* 
 * prompting shell version 2
 *
 * Solves the 'one-shot' problem of version 1
 *      Uses execvp(), but fork()s first so that the
 *      shell waits around to perform another command
 * New problem: shell catches signals. Run vi, press ^c;
 */

#include <stdio.h>
#include <signal.h>

#define MAXARGS     20      /* cmdline args */
#define ARGLEN      100     /* token length */

int main()
{
    char    *arglist[MAXARGS + 1];      /* an array of ptrs */
    int     numargs;                    /* index into array */
    char    argbuf[ARGLEN];             /* read stuff here */
    char    *makestring();              /* malloc etc */

    numargs = 0;
    while (numargs < MAXARGS)
    {
        printf("arg[%d]? ", numargs);
        if (fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n')
            arglist[numargs++] = makestring(argbuf);
        else
        {
            if (numargs > 0) {          /* any args? */
                arglist[numargs] = NULL;    /* close list */
                execute(arglist);       /* do it */
                numargs = 0;            /* and reset */
            }
        }
    }
    return 0;
}

int execute(char *arglist[])
/*
 * use fork and execvp and wait to do it
 */
{
    int pid, exitstatus;                /* of child */

    pid = fork();                       /* make new process */
    switch(pid) {
        case -1:
            perror("fork failed");
            exit(1);
        case 0:
            execvp(arglist[0], arglist);        /* do it */
            perror("execvp failed");
            exit(1);
        default:
            while (wait(&exitstatus) != pid)
                ;
            printf("child exited with status %d, %d\n",
                    exitstatus >> 8, exitstatus & 0377);
    }
}

char *makestring(char *buf)
/*
 * tim off newline and create storage for the string
 */
{
    char *cp, *malloc();

    buf[strlen(buf) - 1] = '\0';        /* trim newline */
    cp = malloc(strlen(buf) + 1);       /* get memory */
    if (cp == NULL) {                   /* or die */
        fprintf(stderr, "no memory\n");
        exit(1);
    }
    strcpy(cp, buf);                    /* copy chars */
    return cp;                          /* return ptr */
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值