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 + -
显示快捷键?