美文网首页Linux学习之路
APUE读书笔记-19伪终端(11)

APUE读书笔记-19伪终端(11)

作者: QuietHeart | 来源:发表于2020-10-08 20:15 被阅读0次

loop函数

接下来将给出前面用到的loop函数。

#include "apue.h"
#define BUFFSIZE    512
static void sig_term(int);
static volatile sig_atomic_t    sigcaught; /* set by signal handler */

void loop(int ptym, int ignoreeof)
{
    pid_t   child;
    int     nread;
    char    buf[BUFFSIZE];

    if ((child = fork()) < 0) {
        err_sys("fork error");
    } else if (child == 0) {    /* child copies stdin to ptym */
        for ( ; ; ) {
            if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0)
                err_sys("read error from stdin");
            else if (nread == 0)
                break;      /* EOF on stdin means we're done */
            if (writen(ptym, buf, nread) != nread)
                err_sys("writen error to master pty");
        }

        /*
         * We always terminate when we encounter an EOF on stdin,
         * but we notify the parent only if ignoreeof is 0.
         */
        if (ignoreeof == 0)
            kill(getppid(), SIGTERM);   /* notify parent */
        exit(0);    /* and terminate; child can't return */
    }

    /*
     * Parent copies ptym to stdout.
     */
    if (signal_intr(SIGTERM, sig_term) == SIG_ERR)
        err_sys("signal_intr error for SIGTERM");

    for ( ; ; ) {
        if ((nread = read(ptym, buf, BUFFSIZE)) <= 0)
            break;      /* signal caught, error, or EOF */
        if (writen(STDOUT_FILENO, buf, nread) != nread)
            err_sys("writen error to stdout");
    }

    /*
     * There are three ways to get here: sig_term() below caught the
     * SIGTERM from the child, we read an EOF on the pty master (which
     * means we have to signal the child to stop), or an error.
     */
    if (sigcaught == 0) /* tell child if it didn't send us the signal */
        kill(child, SIGTERM);
    /*
     * Parent returns to caller.
     */
}

/*
 * The child sends us SIGTERM when it gets EOF on the pty slave or
 * when read() fails.  We probably interrupted the read() of ptym.
 */
static void sig_term(int signo)
{
    sigcaught = 1;      /* just set flag and return */
}

注意,通过两个进程,当一个进程终止的时候,它应该通知另外一个进程。我们使用SIGTERM信号进行通知。

译者注

对于getopt函数的解说以及例子

实践的系统为ubuntu 8.04,具体如下:

/**@mainpage 程序功能:测试getopt选项以及选项的参数的处理函数的使用方法
 *
 *#include <unistd.h>
 *int getopt(int argc, const * const argv[], const
 * char *options);
 *extern int optind, opterr, optopt;
 *extern char *optarg;
 *
 *参数argc和argv和main函数的一样,它们就是main函数传进来的;
 *参数options是一个字符串,这个字符串包含命令支持的所有选项字符;
 *
 *如果选项是非法的,或者选项缺少参数,那么getopt会返回一个'?'.
 *如果一个选项字符后面跟着一个冒号(即':'),那么说明这个选项需要一个参数。例如有一个命令如下:
 *      command [-i] [-u username] [-z] filename
 *那么这里的options应该赋值为:"iu:z".
 *另外,getopt会忽略"--"后面的选项,例如:rm -- -bar,将删除-bar文件。
 *
 *getopt支持的四个外部变量:
 *optarg:
 *如果一个选项需要参数,那么getopt在处理一个选项的时候把optarg设置成为指向选项参数字符串的指针。
 *opterr:
 *如果出现选项错误,getopt会打印一个错误消息。如果去掉这个特性,那么在程序中将opterr设置成0.
 *optind:
 *下一个要处理的参数在argv数组中的索引。它从1开始,在每次用getopt处理参数的时候会增1。
 *optopt:
 *如果在处理选项的时候遇到了一个错误,getopt将会设置optopt, 让它指向导致错误的选项字符串。
 * */
#include <unistd.h>
//#include <fcntl.h>//只用这个也行
//#include <getopt.h>//只用这个也行

#include <stdio.h>
extern char *optarg;
extern int optind;
int main(int argc, char *argv[])
{
        if(argc == 1)
        {//没有参数
                printf("Introduction:\n");
                printf("Syntax is:\n%s [-i] [-u username] [-z] filename\n",argv[0]);
        }
        else
        {
                printf("Begin to process...\n");
                char c;
                char *optStr = "iu:z";
                while((c = getopt(argc, argv, optStr)) != -1)
                {//不要忘了加"()","="的优先级小于"!=".
                        switch(c)
                        {//处理每一个选项
                                case 'i':
                                        printf("The argument \'i\' is used. \n");
                                        break;
                                case 'u':
                                        printf("The argument \'u\' is used,and ");
                                        printf("the parameter of \'u\' is:%s \n", optarg);//选项的参数
                                        break;
                                case 'z':
                                        printf("The argument \'z\' is used. \n");
                                        break;
                                case '?':
                                        printf("Invalid option!\n");
                                        break;

                                }
                        }

                //选项处理完毕之后,处理输入的真正参数
                printf("option ok, and the main parameter is \"%s\"\n", argv[optind]);
                printf("Processed complete!\n");
        }
        return 0;
}

原文参考

参考: APUE2/ch19lev1sec5.html

相关文章

  • APUE读书笔记-19伪终端(11)

    loop函数 接下来将给出前面用到的loop函数。 注意,通过两个进程,当一个进程终止的时候,它应该通知另外一个进...

  • APUE读书笔记-19伪终端(15)

    (6)通过非交互的方式驱动交互程序 尽管我们觉得pty可以运行任何协作处理进程(甚至一个协作处理进程是交互的进程)...

  • APUE读书笔记-19伪终端(16)

    (7)pty程序的do_driver函数 通过我们自己写的被pty调用的driver程序,我们可以以任何需要的方式...

  • APUE读书笔记-19伪终端(5)

    查看长时间运行的程序的输出 如果我们有一个程序,那个程序运行很长的时间,我们可以在任何一种标准的shell下面将这...

  • APUE读书笔记-19伪终端(2)

    2、概述 伪终端的意思是,这个终端对于应用程序来说表现像是一个终端,但是实际上它并不是一个真正的终端。下面的图就展...

  • APUE读书笔记-19伪终端(9)

    (3)基于Linux的伪终端 Linux提供访问伪终端的BSD方法,所以可以使用上面代码中同样的函数在Linux上...

  • APUE读书笔记-19伪终端(14)

    (4)script程序 使用pty程序,我们可以如下通过shell脚本执行script程序: 当我们运行这个she...

  • APUE读书笔记-19伪终端(17)

    远程模式 通过使用ioctl的TIOCREMOTE命令,PTY master可以设置PTY slave为远程模式。...

  • APUE读书笔记-19伪终端(3)

    伪终端的典型应用 我们现在将会看看一些伪终端的典型使用。 网络登录服务 伪终端被编译成支持网络登录的服务。典型的例...

  • APUE读书笔记-19伪终端(8)

    (2)基于BSD的伪终端 在基于BSD的系统中,和基于Linux的系统中,我们提供了自己的XSI函数版本。 在我们...

网友评论

    本文标题:APUE读书笔记-19伪终端(11)

    本文链接:https://www.haomeiwen.com/subject/pztluktx.html