/*************************************************************** * * * EMULATORE DI TERMINALE PER SISTEMI UNIX/XENIX * * -------------------------------------------------------- * * Nocera Informatica s.r.l. * * Antonio Pennino * * 11/01/2000 * * -------------------------------------------------------- * * OPZIONI: -d device indica la device * * -b bps bits per secondo * * -e 7 bit, parity even * * -s no emulazione, setta solo * * la device e si ferma * * -f x imposta ad 'x' il carattere * * che fa terminare l' emulazione * * -x usa solo Xon/Xoff, no flow hw * * * ***************************************************************/ #include #include #include #include #define FINE_EMUL (126) /* default per fine emulazione */ #define RIP_FINE (0x03) /* numero di ripetizioni tasto */ #define PAUSA_EMUL '@' /* default per pausa emulazione */ #define FORMATO "formato: umodem -d device [-b bps] [-s] [-e] [-f x] [-x]\n" #define BANNER "\ ---------------------------------------------------------------------------\n\r\ UMODEM -- Emulatore di Terminale per sistemi UNIX-XENIX - AP - Ver. 1.32 \n\r\ (%05s.%3s) battere %d volte il tasto %c per uscire, %c per sospendere \n\r\ ---------------------------------------------------------------------------\n\r\ \n\r" extern int optind,opterr; /* usati da getopt() */ extern char *optarg; /* usato da getopt() */ void setta_porta(), resetta_porta(), rileva_del(); struct termio term, video_old, video_new; FILE *fp_dev_i,*fp_dev_o; char device[32]; int count_fine,count_sosp,flag_cs7=0,char_del=127; pid_t pid; struct { int setta; /* vero se setto la porta e basta */ int pareven; /* parity even (pari) */ int xon_off_only;/* flag: solo xon/xoff, no hw. */ char fine; /* chr. terminante l' emulazione */ char device[32]; /* device di collegamento */ char bps[32]; /* bps */ } opzioni; /*************************************************************** * INIZIO PROGRAMMA PRINCIPALE * ***************************************************************/ main(argc,argv) int argc; char *argv[]; { int i,c; if (argc < 2) exit(fprintf(stderr,FORMATO),1); if (setta_opzioni(argc,argv)) exit(fprintf(stderr,FORMATO),2); if (! *opzioni.device ) exit(fprintf(stderr,FORMATO),2); if (*opzioni.device == '/') strcpy(device,opzioni.device); else sprintf(device,"/dev/%s",opzioni.device); if (!opzioni.setta) printf(BANNER,opzioni.bps,(opzioni.pareven ? "7E1" : "8N1"), RIP_FINE,opzioni.fine,PAUSA_EMUL); if ((fp_dev_i=fopen(device,"rb"))==(FILE *)NULL) errore("fopen input device"); if ((fp_dev_o=fopen(device,"wb"))==(FILE *)NULL) errore("fopen output device"); setta_porta(); signal(SIGINT,rileva_del); if (opzioni.setta) pause(); else puts("\n\rok! batti \r\n"); for( ;; ) { /* dtr_off_on(); */ c=terminale(); kill(pid,15); if (c == opzioni.fine) { printf("\rFine Emulazione\r\n"); break; } if (c == PAUSA_EMUL) { printf("EMULATORE SOSPESO, riattivalo con ENTER "); getchar(); resetta_porta(); /* serve a risettare la porta */ setta_porta(); /* senza perdere 'video_old' */ } else { puts("emulatore imballato - termino"); exit(1); } } resetta_porta(); signal(SIGINT,SIG_DFL); fclose(fp_dev_i); fclose(fp_dev_o); exit(0); /*NOTREACHED*/ } /**************************************************************** * segnalazione errore con uscita dal programma * ****************************************************************/ errore(errmsg) char *errmsg; { extern int errno; extern char *sys_errlist[]; printf("\numodem: errore su %s -- errno %d : %s \n", errmsg,errno,sys_errlist[errno]); exit(1); } /**************************************************************** * configurazione porta di i-o * * alcuni settaggi dependono dal s.o. * ****************************************************************/ void setta_porta() { extern struct termio term,video_old,video_new; if (ioctl(fileno(fp_dev_i),TCGETA,&term) == -1) errore("ioctl inp."); term.c_cc[VINTR] = term.c_cc[VQUIT] = term.c_cc[VERASE] = 0; term.c_cc[VKILL] = term.c_cc[VEOL2] = term.c_cc[VSWTCH] = 0; term.c_iflag = term.c_oflag = term.c_lflag = 0; if (opzioni.pareven) term.c_cflag = (0|velocita()|CREAD|CS7|PARENB|CLOCAL); else term.c_cflag = (0|velocita()|CREAD|CS8|CLOCAL); term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 1; if (opzioni.xon_off_only==0) { #ifdef CTSFLOW /* XENIX-UNIX S.C.O.*/ term.c_cflag |= (CTSFLOW); #endif #ifdef CRTSFL /* XENIX SCO 2.3.2 */ term.c_cflag |= (CRTSFL); term.c_cflag &= (~(RTSFLOW|CTSFLOW)); #endif #ifdef IRTS /* TOWER 32 */ term.c_iflag |= (IRTS); #endif } if (ioctl(fileno(fp_dev_i),TCSETA,&term) == -1) errore("ioctl out."); if (ioctl(fileno(fp_dev_o),TCSETA,&term) == -1) errore("ioctl out."); if (ioctl(fileno(stdin) ,TCGETA,&video_old)== -1) return; if (ioctl(fileno(stdin) ,TCGETA,&video_new)== -1) return; video_new.c_iflag &= (~(ICRNL)); video_new.c_oflag &= (~ONLCR); video_new.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL)); video_new.c_cc[VMIN] = 1; video_new.c_cc[VTIME] = 1; if ( (video_new.c_cflag&CSIZE) == CS7 ) flag_cs7=1; else flag_cs7=0; if (ioctl(fileno(stdin) ,TCSETA,&video_new)== -1) return; } /************************************************************** * de-configurazione porta di i-o * **************************************************************/ void resetta_porta() { if (ioctl(fileno(stdin) ,TCSETA,&video_old)== -1) return; } /************************************************************** * abbasso e rialzo il DTR * **************************************************************/ dtr_off_on() { struct termio term_tmp; if (ioctl(fileno(fp_dev_i),TCGETA,&term_tmp) == -1) errore("ioctl TCGETA"); term.c_cflag = (0|B0); if (ioctl(fileno(fp_dev_i),TCSETA,&term ) == -1) errore("ioctl TCSETA"); if (ioctl(fileno(fp_dev_i),TCFLSH,2 ) == -1) errore("ioctl flush"); sleep( (unsigned) 1 ); if (ioctl(fileno(fp_dev_i),TCSETA,&term_tmp) == -1) errore("ioctl TCSETA"); } /************************************************************** * restituisco la velocita' x TCSETA * **************************************************************/ velocita() { if ( ! strcmp(opzioni.bps,"300") ) return(B300); if ( ! strcmp(opzioni.bps,"1200") ) return(B1200); if ( ! strcmp(opzioni.bps,"2400") ) return(B2400); if ( ! strcmp(opzioni.bps,"9600") ) return(B9600); #ifdef EXTA if ( ! strcmp(opzioni.bps,"exta") ) return(EXTA); #endif #ifdef EXTB if ( ! strcmp(opzioni.bps,"extb") ) return(EXTB); #endif #ifdef B19200 if ( ! strcmp(opzioni.bps,"19200") ) return(B19200); #endif puts("velocita' errata, vado a 9600 bps"); return(B9600); } /************************************************************** * emulazione di terminale * **************************************************************/ terminale() { register int c; count_fine=count_sosp=RIP_FINE; if ((pid=fork()) == 0) while(1) { c=fgetc(fp_dev_i); if (c != EOF) putchar( (flag_cs7) ? c&127 : c ); } while((c=getchar()),1) { if (c == EOF) continue; if (flag_cs7) c&=127; if (c == opzioni.fine) if ( --count_fine == 0 ) break; else ; else count_fine=RIP_FINE; if (c == PAUSA_EMUL) if ( --count_sosp == 0 ) break; else ; else count_sosp=RIP_FINE; fputc(c,fp_dev_o); fflush(fp_dev_o); } return(c); } void rileva_del() { signal(SIGINT,rileva_del); fputc(char_del,fp_dev_o); } /*************************************************************** * Legge e imposta le opzioni da riga di comando * ***************************************************************/ setta_opzioni(argc,argv) int argc; char **argv; { int c,ritorno; opzioni.xon_off_only = 0; opzioni.setta = 0; opzioni.pareven = 0; opzioni.fine = FINE_EMUL; strcpy(opzioni.device,""); strcpy(opzioni.bps,"9600"); for(ritorno=0;((c=getopt(argc,argv,"xesd:b:f:")) != EOF);) switch(c) { case 'x' : opzioni.xon_off_only=1; break; case 's' : opzioni.setta=1; break; case 'e' : opzioni.pareven=1; break; case 'f' : opzioni.fine=(*optarg); break; case 'd' : strcpy(opzioni.device,optarg); break; case 'b' : strcpy(opzioni.bps,optarg); break; case '?' : ritorno=1; break; } return(ritorno); }