to_erl.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 432 行

C
432
字号
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//*  * Module: to_erl.c *  * This module implements a process that opens two specified FIFOs, one * for reading and one for writing; reads from its stdin, and writes what * ithas read to the write FIF0; reads from the read FIFO, and writes to * its stdout. * */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <termios.h>#include <dirent.h>#include <signal.h>#include <errno.h>#if defined(O_NONBLOCK)# define DONT_BLOCK_PLEASE O_NONBLOCK#else# define DONT_BLOCK_PLEASE O_NDELAY# if !defined(EAGAIN)#  define EAGAIN -3898734# endif#endif#define noDEBUG#define PIPE_DIR        "/tmp/"#define PIPE_STUBNAME   "erlang.pipe"#define PIPE_STUBLEN    strlen(PIPE_STUBNAME)#ifdef DEBUG#define STATUS(s)  { fprintf(stderr, (s)); fflush(stderr); }#else#define STATUS(s)#endif#ifndef FILENAME_MAX#define FILENAME_MAX 250#endifstatic struct termios tty_smode, tty_rmode;static int tty_eof = 0;static int ctrlc = 0;#ifdef DEBUGstatic void show_terminal_settings(struct termios *);#endifstatic void handle_ctrlc(int sig) {  /* Reinstall the handler, and signal break flag */  signal(SIGINT,handle_ctrlc);  ctrlc = 1;}  static void usage(char *pname){  fprintf(stderr, "Usage: %s [pipe_name|pipe_dir/]\n", pname);}int main(int argc, char **argv){    char  FIFO1[FILENAME_MAX], FIFO2[FILENAME_MAX];    int i, len, wfd, rfd, result = 0;    fd_set readfds;    char buf[BUFSIZ];    char pipename[FILENAME_MAX];        if (argc < 1) {	usage(argv[0]);	exit(1);    }    #ifdef DEBUG    fprintf(stderr, "%s: pid is : %d\n", argv[0], (int)getpid());#endif        if(argv[1])	strcpy(pipename,argv[1]);    else	strcpy(pipename,PIPE_DIR);        if(*pipename && pipename[strlen(pipename)-1] == '/') {	/* The user wishes us to find a unique pipe name in the specified */	/* directory */	int highest_pipe_num = 0;	DIR *dirp;	struct dirent *direntp;	dirp = opendir(pipename);	if(!dirp) {	    fprintf(stderr, "Can't access pipe directory %s.\n", pipename);	    exit(1);	}	/* Check the directory for existing pipes */    	while((direntp=readdir(dirp)) != NULL) {	    if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) {		int num = atoi(direntp->d_name+PIPE_STUBLEN+1);		if(num > highest_pipe_num)		    highest_pipe_num = num;	    }	}		closedir(dirp);	sprintf(pipename+strlen(pipename),		(highest_pipe_num?"%s.%d":"%s"),PIPE_STUBNAME,highest_pipe_num);    } /* if */        /* read FIFO */    strncpy(FIFO1, pipename, FILENAME_MAX);    strncat(FIFO1, ".r", FILENAME_MAX - strlen(FIFO1));    /* write FIFO */    strncpy(FIFO2, pipename, FILENAME_MAX);    strncat(FIFO2, ".w", FILENAME_MAX - strlen(FIFO2));        if ((rfd = open (FIFO1, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {#ifdef DEBUG	fprintf(stderr, "Could not open FIFO %s for reading.\n", FIFO1);#endif	fprintf(stderr, "No running Erlang on pipe %s.\n", pipename);	exit(1);    }#ifdef DEBUG    fprintf(stderr, "to_erl: %s opened for reading\n", FIFO1);#endif        if ((wfd = open (FIFO2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {#ifdef DEBUG	fprintf(stderr, "Could not open FIFO %s for writing.\n", FIFO2);#endif	fprintf(stderr, "No running Erlang on pipe %s.\n", pipename);	close(rfd);	exit(1);    }#ifdef DEBUG    fprintf(stderr, "to_erl: %s opened for writing\n", FIFO2);#endif        fprintf(stderr, "Attaching to %s (^D to exit)\n\n", pipename);        /* Set break handler to our handler */    signal(SIGINT,handle_ctrlc);        /*      * Save the current state of the terminal, and set raw mode.     */    if (tcgetattr(0, &tty_rmode) , 0) {	fprintf(stderr, "Cannot get terminals current mode\n");	exit(-1);    }    tty_smode = tty_rmode;    tty_eof = '\004'; /* Ctrl+D to exit */#ifdef DEBUG    show_terminal_settings(&tty_rmode);#endif    tty_smode.c_iflag =	1*BRKINT |/*Signal interrupt on break.*/	    1*IGNPAR |/*Ignore characters with parity errors.*/		1*ISTRIP |/*Strip character.*/		    0;    #if 00*IGNBRK |/*Ignore break condition.*/0*PARMRK |/*Mark parity errors.*/0*INPCK  |/*Enable input parity check.*/0*INLCR  |/*Map NL to CR on input.*/0*IGNCR  |/*Ignore CR.*/0*ICRNL  |/*Map CR to NL on input.*/0*IUCLC  |/*Map upper-case to lower-case on input.*/0*IXON   |/*Enable start/stop output control.*/0*IXANY  |/*Enable any character to restart output.*/0*IXOFF  |/*Enable start/stop input control.*/0*IMAXBEL|/*Echo BEL on input line too long.*/#endif						    tty_smode.c_oflag =	1*OPOST  |/*Post-process output.*/	    1*ONLCR  |/*Map NL to CR-NL on output.*/#ifdef XTABS		1*XTABS  |/*Expand tabs to spaces. (Linux)*/#endif#ifdef OXTABS		    1*OXTABS  |/*Expand tabs to spaces. (FreeBSD)*/#endif#ifdef NL0			1*NL0    |/*Select newline delays*/#endif#ifdef CR0			    1*CR0    |/*Select carriage-return delays*/#endif#ifdef TAB0				1*TAB0   |/*Select horizontal tab delays*/#endif#ifdef BS0				    1*BS0    |/*Select backspace delays*/#endif#ifdef VT0					1*VT0    |/*Select vertical tab delays*/#endif#ifdef FF0					    1*FF0    |/*Select form feed delays*/#endif											    0;    #if 00*OLCUC  |/*Map lower case to upper on output.*/0*OCRNL  |/*Map CR to NL on output.*/0*ONOCR  |/*No CR output at column 0.*/0*ONLRET |/*NL performs CR function.*/0*OFILL  |/*Use fill characters for delay.*/0*OFDEL  |/*Fill is DEL, else NULL.*/0*NL1    |0*CR1    |0*CR2    |0*CR3    |0*TAB1   |0*TAB2   |0*TAB3   |/*Expand tabs to spaces.*/0*BS1    |0*VT1    |0*FF1    |#endif								        /* JALI: removed setting the tty_smode.c_cflag flags, since this is not */    /* advisable if this is a *real* terminal, such as the console. In fact */    /* this may hang the entire machine, deep, deep down (signalling break */    /* or toggling the abort switch doesn't help) */        tty_smode.c_lflag =									0;    #if 00*ISIG   |/*Enable signals.*/0*ICANON |/*Canonical input (erase and kill processing).*/0*XCASE  |/*Canonical upper/lower presentation.*/0*ECHO   |/*Enable echo.*/0*ECHOE  |/*Echo erase character as BS-SP-BS.*/0*ECHOK  |/*Echo NL after kill character.*/0*ECHONL |/*Echo NL.*/0*NOFLSH |/*Disable flush after interrupt or quit.*/0*TOSTOP |/*Send SIGTTOU for background output.*/0*ECHOCTL|/*Echo control characters as ^char, delete as ^?.*/0*ECHOPRT|/*Echo erase character as character erased.*/0*ECHOKE |/*BS-SP-BS erase entire line on line kill.*/0*FLUSHO |/*Output is being flushed.*/0*PENDIN |/*Retype pending input at next read or input character.*/0*IEXTEN |/*Enable extended (implementation-defined) functions.*/#endif								    tty_smode.c_cc[VMIN]      =0;/* Note that VMIN is the same as VEOF! */    tty_smode.c_cc[VTIME]     =0;/* Note that VTIME is the same as VEOL! */    tty_smode.c_cc[VINTR]     =3;        tcsetattr(0, TCSANOW, &tty_smode);    #ifdef DEBUG    show_terminal_settings(&tty_smode);#endif    /*     * Write a ^R to the FIFO which causes the other end to redisplay     * the input line.     */    write(wfd, "\022", 1);    /*     * read and write     */    while (1) {	FD_ZERO(&readfds);	FD_SET(0, &readfds);	FD_SET(rfd, &readfds);	if (select(rfd + 1, &readfds, NULL, NULL, NULL) < 0) {	    if(ctrlc) {		FD_ZERO(&readfds);	    } else {		fprintf(stderr, "Error in select.\n");		result = -1;		break;	    }	}	/*	 * Read from terminal, write to FIFO	 */	if (ctrlc || FD_ISSET(0, &readfds)) {	    STATUS("Terminal read; ");	    if(ctrlc) {		ctrlc = 0;		fprintf(stderr, "[Break]\n\r");		buf[0] = '\003';		len = 1;	    } else if ((len = read(0, buf, BUFSIZ)) <= 0) {		close(rfd);		close(wfd);		if (len < 0) {		    fprintf(stderr, "Error in reading from stdin.\n");		    result = -1;		} else {		    fprintf(stderr, "[EOF]\n\r");		}		break;	    }	    /* check if there is an eof character in input */	    for (i = 0; i < len && buf[i] != tty_eof; i++);	    if (buf[i] == tty_eof) {		fprintf(stderr, "[Quit]\n\r");		break;	    }	    STATUS("FIFO write; \"");#ifdef DEBUG	    write(1, buf, len);#endif	    if (write(wfd, buf, len) != len) {		fprintf(stderr, "Error in writing to FIFO.\n");		close(rfd);		close(wfd);		result = -1;		break;	    }	    STATUS("\" OK\r\n");	}	/*	 * Read from FIFO, write to terminal.	 */	if (FD_ISSET(rfd, &readfds)) {	    STATUS("FIFO read: ");	    len = read(rfd, buf, BUFSIZ);	    if (len < 0 && errno == EAGAIN) {		/*		 * No data this time, but the writing end of the FIFO is still open.		 * Do nothing.		 */		;	    } else if (len <= 0) {		/*		 * Either an error or end of file. In either case, break out		 * of the loop.		 */		close(rfd);		close(wfd);		if (len < 0) {		    fprintf(stderr, "Error in reading from FIFO.\n");		    result = -1;		} else		    fprintf(stderr, "[End]\n\r");		break;	    } else {		/*		 * We successfully read at least one character. Write what we got.		 */		STATUS("Terminal write: \"");		if (write(1, buf, len) != len) {		    fprintf(stderr, "Error in writing to terminal.\n");		    close(rfd);		    close(wfd);		    result = -1;		    break;		}		STATUS("\" OK\r\n");	    }	}    }    /*      * Reset terminal characterstics      * XXX     */    tcsetattr(0, TCSANOW, &tty_rmode);    return 0;}#ifdef DEBUG#define S(x)  ((x) > 0 ? 1 : 0)static void show_terminal_settings(struct termios *t){  fprintf(stderr,"c_iflag:\n");  fprintf(stderr,"Signal interrupt on break:   BRKINT  %d\n", S(t->c_iflag & BRKINT));  fprintf(stderr,"Map CR to NL on input:       ICRNL   %d\n", S(t->c_iflag & ICRNL));  fprintf(stderr,"Ignore break condition:      IGNBRK  %d\n", S(t->c_iflag & IGNBRK));  fprintf(stderr,"Ignore CR:                   IGNCR   %d\n", S(t->c_iflag & IGNCR));  fprintf(stderr,"Ignore char with par. err's: IGNPAR  %d\n", S(t->c_iflag & IGNPAR));  fprintf(stderr,"Map NL to CR on input:       INLCR   %d\n", S(t->c_iflag & INLCR));  fprintf(stderr,"Enable input parity check:   INPCK   %d\n", S(t->c_iflag & INPCK));  fprintf(stderr,"Strip character              ISTRIP  %d\n", S(t->c_iflag & ISTRIP));  fprintf(stderr,"Enable start/stop input ctrl IXOFF   %d\n", S(t->c_iflag & IXOFF));  fprintf(stderr,"ditto output ctrl            IXON    %d\n", S(t->c_iflag & IXON));  fprintf(stderr,"Mark parity errors           PARMRK  %d\n", S(t->c_iflag & PARMRK));  fprintf(stderr,"\n");  fprintf(stderr,"c_oflag:\n");  fprintf(stderr,"Perform output processing    OPOST   %d\n", S(t->c_oflag & OPOST));  fprintf(stderr,"\n");  fprintf(stderr,"c_cflag:\n");  fprintf(stderr,"Ignore modem status lines    CLOCAL  %d\n", S(t->c_cflag & CLOCAL));  fprintf(stderr,"\n");  fprintf(stderr,"c_local:\n");  fprintf(stderr,"Enable echo                  ECHO    %d\n", S(t->c_lflag & ECHO));  fprintf(stderr,"\n");  fprintf(stderr,"c_cc:\n");  fprintf(stderr,"c_cc[VEOF]                           %d\n", t->c_cc[VEOF]);}#endif

⌨️ 快捷键说明

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