⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 17.htm

📁 UNIX环境下C编程的详细详细介绍
💻 HTM
📖 第 1 页 / 共 4 页
字号:
</p>

<p>入可以是打印机状态消息或者给用户的输出。 </p>

<p>_______________________________________________________________________ </p>

<p>______ </p>

<p>#include &quot;lprps.h&quot; </p>

<p>static int eof_count; </p>

<p>static int ignore_input; </p>

<p>static enum parse_state { /* state of parsing input from printer */ </p>

<p>NORMAL, </p>

<p>HAD_ONE_PERCENT, </p>

<p>HAD_TWO_PERCENT, </p>

<p>IN_MESSAGE, </p>

<p>HAD_RIGHT_BRACKET, </p>

<p>HAD_RIGHT_BRACKET_AND_PERCENT </p>

<p>} parse_state; </p>

<p>/* Initialize our input machine. */ </p>

<p>void </p>

<p>init_input(int job) </p>

<p>{ </p>

<p>in_job = job; /* only true when send_file() calls us */ </p>

<p>parse_state = NORMAL; </p>

<p>ignore_input = 0; </p>

<p>} </p>

<p>/* Read from the printer until we encounter an EOF. </p>

<p>* Whether or not the input is processed depends on &quot;ignore&quot;. */ </p>

<p>void </p>

<p>proc_upto_eof(int ignore) </p>

<p>{ </p>

<p>int ec; </p>

<p>ignore_input = ignore; </p>

<p>ec = eof_count; /* proc_input_char() increments eof_count */ </p>

<p>while (ec == eof_count) </p>

<p>proc_some_input(); </p>

<p>} </p>

<p>/* Wait for some data then read it. </p>

<p>* Call proc_input_char() for every character read. */ </p>

<p>void </p>

<p>proc_some_input(void) </p>

<p>{ </p>

<p>char ibuf[IBSIZE]; </p>

<p>char *ptr; </p>

<p>int nread; </p>

<p>fd_set rfds; </p>

<p>FD_ZERO(&amp;rfds); </p>

<p>FD_SET(psfd, &amp;rfds); </p>

<p>set_nonblock(); </p>

<p>if (intr_flag) </p>

<p>handle_intr(); </p>

<p>if (alrm_flag) </p>

<p>handle_alrm(); </p>

<p>while (select(psfd + 1, &amp;rfds, NULL, NULL, NULL) &lt; 0) { </p>

<p>if (errno == EINTR) { </p>

<p>if (alrm_flag) </p>

<p>handle_alrm(); /* doesn't return */ </p>

<p>else if (intr_flag) </p>

<p>handle_intr(); /* doesn't return */ </p>

<p>} else </p>

<p>log_sys(&quot;proc_some_input: select error&quot;); </p>

<p>} </p>

<p>if ( (nread = read(psfd, ibuf, IBSIZE)) &lt; 0) </p>

<p>log_sys(&quot;proc_some_input: read error&quot;); </p>

<p>else if (nread == 0) </p>

<p>log_sys(&quot;proc_some_input: read returned 0&quot;); </p>

<p>ptr = ibuf; </p>

<p>while (--nread &gt;= 0) </p>

<p>proc_input_char(*ptr++); /* process each character */ </p>

<p>} </p>

<p>/* Called by proc_some_input() above after some input has been read. </p>

<p>* Also called by out_buf() whenever asynchronous input appears. */ </p>

<p>void </p>

<p>proc_input_char(int c) </p>

<p>{ </p>

<p>if (c == '\004') { </p>

<p>eof_count++; /* just count the EOFs */ </p>

<p>return; </p>

<p>} else if (ignore_input) </p>

<p>return; /* ignore everything except EOFs */ </p>

<p>switch (parse_state) { /* parse the input */ </p>

<p>case NORMAL: </p>

<p>if (c == '%') </p>

<p>parse_state = HAD_ONE_PERCENT; </p>

<p>else </p>

<p>mail_char(c); </p>

<p>break; </p>

<p>case HAD_ONE_PERCENT: </p>

<p>if (c == '%') </p>

<p>parse_state = HAD_TWO_PERCENT; </p>

<p>else { </p>

<p>mail_char('%'); mail_char(c); </p>

<p>parse_state = NORMAL; </p>

<p>} </p>

<p>break; </p>

<p>case HAD_TWO_PERCENT: </p>

<p>if (c == '[') { </p>

<p>msg_init(); /* message starting; init buffer */ </p>

<p>parse_state = IN_MESSAGE; </p>

<p>} else { </p>

<p>mail_char('%'); mail_char('%'); mail_char(c); </p>

<p>parse_state = NORMAL; </p>

<p>} </p>

<p>break; </p>

<p>case IN_MESSAGE: </p>

<p>if (c == ']') </p>

<p>parse_state = HAD_RIGHT_BRACKET; </p>

<p>else </p>

<p>msg_char(c); </p>

<p>break; </p>

<p>case HAD_RIGHT_BRACKET: </p>

<p>if (c == '%') </p>

<p>parse_state = HAD_RIGHT_BRACKET_AND_PERCENT; </p>

<p>else { </p>

<p>msg_char(']'); msg_char(c); </p>

<p>parse_state = IN_MESSAGE; </p>

<p>} </p>

<p>break; </p>

<p>case HAD_RIGHT_BRACKET_AND_PERCENT: </p>

<p>if (c == '%') { </p>

<p>parse_state = NORMAL; </p>

<p>proc_msg(); /* we have a message; process it */ </p>

<p>} else { </p>

<p>msg_char(']'); msg_char('%'); msg_char(c); </p>

<p>parse_state = IN_MESSAGE; </p>

<p>} </p>

<p>break; </p>

<p>default: </p>

<p>abort(); </p>

<p>} </p>

<p>} </p>

<p>_______________________________________________________________________ </p>

<p>______ </p>

<p>程序17.13 input.c文件-读取和处理从打印机的输入 </p>

<p>每当我们等待从打印机返回EOF时就会调用函数proc_upto_eof。 </p>

<p>函数proc_some_input从串口读取。注意我们调用select 
函数来确定什么时候 </p>

<p>该描述符是可以读取的。这是因为select 
函数通常被一个捕捉到的信号所中断-它 </p>

<p>并不自动地重启动。因为select 函数能被SIGALRM或SIGINT所中断,我们并不希望 
</p>

<p>它重启动。回忆一下在12.5节中我们关于select函数被正常中断的讨论。同样回忆 
</p>

<p>在10.5节中我们设置SA_RESTART来说明当一个特定信号出现时,应当自动重启动的 
</p>

<p>I/O函数。但是因为并不总是有一个附加的标志,使得我们可以说明I/O 
函数不应 </p>

<p>当重启动。如果不设置SA_RESTART,我们只能倚赖系统的缺省值,而这可能是自动 
</p>

<p>重新启动被中断的I/O函数。当从打印机返回输入时,我们以非阻塞模式读取,得 
</p>

<p>到打印机准备就绪的数据。然后调用函数proc_input_char来处理每一个字符。 
</p>

<p>处理打印机发送给我们的消息是由proc_input_char完成的。我们必须检查每 
</p>

<p>一个字符并记住我们的状态。变量parse_state跟踪记录当前状态。调用msg_char 
</p>

<p>函数把序列%%[以后所有的字符串储存在消息缓冲中。当遇到结束序列]%%时,我们 
</p>

<p>调用proc_msg来处理消息。除了开始%%[ 和最后 ]%%序列以及二者之间的状态消息 
</p>

<p>其他字符串,都被认为是用户的输出,被邮递给用户(调用mail_char)。 
</p>

<p>我们现在查看那些处理由输入函数积累消息的函数。程序17.14是文件messag 
</p>

<p>e.c。 </p>

<p>当检测到%%[ 后,调用函数msg_init。它只是初始化缓冲计数器。然后对于消 
</p>

<p>息中的每一个字符都调用msg_char函数。 </p>

<p>函数proc_msg将消息分解为key:val对(关键字:值对),并检查key。调用A 
</p>

<p>NSI C的strtok函数将消息分解为记号,每个key: val对用分号分隔。 </p>

<p>一个以下形式的消息 </p>

<p>%%[ Flushing : rest of job (to end-of-fiel) will be ignored ]%% </p>

<p>引起函数printer_flushing 被调用。它清理终端的缓冲,发送一个EOF给打印 
</p>

<p>机,然后等待打印机返回一个EOF。 </p>

<p>如果收到一个以下形式的消息 </p>

<p>%%[ PrinterError: reason]%% </p>

<p>就调用log_msg函数来记录这个错误。带有Error Key的出错消息邮递传送回用 
</p>

<p>户。这些一般是PostScript程序的错误。 </p>

<p>如果返回一个带有关键字status的状态消息,它很可能是由于函数get_statu 
</p>

<p>s发送给打印机一个状态请求(Control-T)而引起的。我们查看val,并按照它来 
</p>

<p>设置变量status。 </p>

<p>_______________________________________________________________________ </p>

<p>______ </p>

<p>#include &quot;lprps.h&quot; </p>

<p>#include &lt;ctype.h&gt; </p>

<p>static char msgbuf[MBSIZE]; </p>

<p>static int msgcnt; </p>

<p>static void printer_flushing(void); </p>

<p>/* Called by proc_input_char() after it's seen the &quot;%%[&quot; that </p>

<p>* starts a message. */ </p>

<p>void </p>

<p>msg_init(void) </p>

<p>{ </p>

<p>msgcnt = 0; /* count of chars in message buffer */ </p>

<p>} </p>

<p>/* All characters received from the printer between the starting </p>

<p>* %%[ and the terminating ]%% are placed into the message buffer </p>

<p>* by proc_some_input(). This message will be examined by </p>

<p>* proc_msg() below. */ </p>

<p>void </p>

<p>msg_char(int c) </p>

<p>{ </p>

<p>if (c != '\0' &amp;&amp; msgcnt &lt; MBSIZE - 1) </p>

<p>msgbuf[msgcnt++] = c; </p>

<p>} </p>

<p>/* This function is called by proc_input_char() only after the final </p>

<p>* percent in a &quot;%%[ &lt;message&gt; ]%%&quot; has been seen. It parses the </p>

<p>* &lt;message&gt;, which consists of one or more &quot;key: val&quot; pairs. </p>

<p>* If there are multiple pairs, &quot;val&quot; can end in a semicolon. */ </p>

<p>void </p>

<p>proc_msg(void) </p>

<p>{ </p>

<p>char *ptr, *key, *val; </p>

<p>int n; </p>

<p>msgbuf[msgcnt] = 0; /* null terminate message */ </p>

<p>for (ptr = strtok(msgbuf, &quot;;&quot;); ptr != NULL; </p>

<p>ptr = strtok(NULL, &quot;;&quot;)) { </p>

<p>while (isspace(*ptr)) </p>

<p>ptr++; /* skip leading spaces in key */ </p>

<p>key = ptr; </p>

<p>if ( (ptr = strchr(ptr, ':')) == NULL) </p>

<p>continue; /* missing colon, something wrong, ignore */ </p>

<p>*ptr++ = '\0'; /* null terminate key (overwrite colon) */ </p>

<p>while (isspace(*ptr)) </p>

<p>ptr++; /* skip leading spaces in val */ </p>

<p>val = ptr; </p>

<p>/* remove trailing spaces in val */ </p>

<p>ptr = strchr(val, '\0'); </p>

<p>while (ptr &gt; val &amp;&amp; isspace(ptr[-1])) </p>

<p>--ptr; </p>

<p>*ptr = '\0'; </p>

<p>if (strcmp(key, &quot;Flushing&quot;) == 0) { </p>

<p>printer_flushing(); /* never returns */ </p>

<p>} else if (strcmp(key, &quot;PrinterError&quot;) == 0) { </p>

<p>log_msg(&quot;proc_msg: printer error: %s&quot;, val); </p>

<p>} else if (strcmp(key, &quot;Error&quot;) == 0) { </p>

<p>mail_line(&quot;Your PostScript printer job &quot; </p>

<p>&quot;produced the error `%s'.\n&quot;, val); </p>

<p>} else if (strcmp(key, &quot;status&quot;) == 0) { </p>

<p>if (strcmp(val, &quot;idle&quot;) == 0) </p>

<p>status = IDLE; </p>

<p>else if (strcmp(val, &quot;busy&quot;) == 0) </p>

<p>status = BUSY; </p>

<p>else if (strcmp(val, &quot;waiting&quot;) == 0) </p>

<p>status = WAITING; </p>

<p>else </p>

<p>status = UNKNOWN; /* &quot;printing&quot;, &quot;PrinterError&quot;, </p>

<p>&quot;initializing&quot;, or &quot;printing test page&quot;. */ </p>

<p>} else if (strcmp(key, &quot;OffendingCommand&quot;) == 0) { </p>

<p>mail_line(&quot;The offending command was `%s'.\n&quot;, val); </p>

<p>} else if (strcmp(key, &quot;pagecount&quot;) == 0) { </p>

<p>if (sscanf(val, &quot;%d&quot;, &amp;n) == 1 &amp;&amp; n &gt;= 0) { </p>

<p>if (start_page &lt; 0) </p>

<p>start_page = n; </p>

<p>else </p>

<p>end_page = n; </p>

<p>} </p>

<p>} </p>

<p>} </p>

<p>} </p>

<p>/* Called only by proc_msg() when the &quot;Flushing&quot; message </p>

<p>* is received from the printer. We exit. */ </p>

<p>static void </p>

<p>printer_flushing(void) </p>

<p>{ </p>

<p>clear_intr(); /* don't catch SIGINT */ </p>

<p>tty_flush(); /* empty tty input and output queues */ </p>

<p>block_write(&amp;eofc, 1); /* send an EOF to the printer */ </p>

<p>proc_upto_eof(1); /* this call won't be recursive, </p>

<p>since we specify to ignore input */ </p>

<p>get_page(&amp;end_page); </p>

<p>do_acct(); </p>

<p>exit(EXIT_SUCCESS); </p>

<p>} </p>

<p>_______________________________________________________________________ </p>

<p>______ </p>

<p>程序17.14 message.c文件,处理从打印机返回消息 </p>

<p>一个OffendingCommand的关键字一般总是与其它key : val对一起出现,如 </p>

<p>%% [ Error : stackunderflow ; OffendingCommand : pop ]%% </p>

<p>我们在送回给用户的邮件中就要添加一行。 </p>

<p>最后,在函数get_page(程序17.9)中的PostScript程序产生一个页面计数值 
</p>

<p>。我们调用sscanf把val转换为二进制,设置起始或结束页面值变量。函数get_pa 
</p>

<p>ge中的while循环就在等待这个变量变成非负值。 </p>

<p>17.5 摘要 </p>

<p>在这一章中实现一个完整的程序-它发送一个PostScript程序给连接在RS-232 
</p>

<p>端口的PostScript打印机。这给我们一个实践机会,把前些章所介绍的很多函数用 
</p>

<p>到一个实用的程序中:例如I/O多路转接、非阻塞的I/O、终端I/O和信号等。 
</p>

<p>习题: </p>

<p>17.1 我们需要使用lprps来打印标准输入的文件,它也可能是一个管道。因为程序 
</p>

<p>psif一定要查看输入文件的前两个字节,那么应当如何开发psif程序(图17.5)来 
</p>

<p>处理这种情况呢? </p>

<p>17.2 实现psif过滤器,处理前一个练习中的实例。 </p>

<p>17.3 参考12.5节中Adobe Systems[1998]关于在Postscript程序中字体请求的处理 
</p>

<p>,修改本章中的lprps程序以处理字体请求。 </p>

<p>-</font></p>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -