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;
}
网友评论