10-16-2007
1,
0
Join Date: Oct 2007
Last Activity: 16 October 2007, 2:01 PM EDT
Posts: 1
Thanks Given: 0
Thanked 0 Times in 0 Posts
Help with stdin and non-canonical mode
I am writing a more command for my class, and have it most of the way done, but with my current implimentation when I pipe stdin to my code it doesnt use my non-canonical/non echo settings I set for the terminal window. Do I need to specify a different terminal in order for this to work ? It works great when I just use the program on an file.
I will paste the code below
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#define PAGELEN 24
#define LINELEN 512
int FILE_SIZE = 0; //holds the global file size for my %'s
int READ_SIZE = 0;
int FIRST_READ = 0; //flag to decide wether to display first time info, or just %
void do_more( FILE *fp, char *file_read,int);
int see_more(FILE *cmd, char *file_read,int);
void cbreak(struct termios tty)
{
tty.c_lflag = tty.c_lflag & ~(ECHO | ECHOK | ICANON);
tty.c_cc[VTIME] = 1;
tcsetattr(0, TCSANOW, &tty);
}
int main(int argc, char **argv)
{
FILE *fp;
struct termios tty, otty;
int i, j;
struct stat file_info; //buffer for file info
tcgetattr(0, &otty); // Get original tty settings and save them in otty
tty = otty;
cbreak(tty); //turns off echo and on non-canonical
if ( argc == 1 ){
fp = stdin;
do_more( fp,argv[0],1 );
}else
while ( --argc ){
if ( (fp = fopen( *++argv , "r" )) != NULL )
{
if (stat(argv[0],&file_info) == -1){ //error condition
perror(argv[0]);
}else{
FILE_SIZE = file_info.st_size;
do_more( fp,argv[0],0 ) ;
fclose( fp );
}
}
else
printf("%s: No such file or directory.\n",argv[0]);
}
tcsetattr(0, TCSANOW, &otty); // Reset to the original settings
return (0);
}
void do_more( FILE *fp, char *file_read,int is_stdin)
{
char line[LINELEN];
int num_of_lines = 0;
int see_more(FILE *, char*,int), reply;
FILE *fp_tty;
fp_tty = fopen( "/dev/tty", "r" ); /* NEW: cmd stream */
if ( fp_tty == NULL ) /* if open fails */
exit(1); /* no use in running */
while ( fgets( line, LINELEN, fp ) ){ /* more input */
if ( num_of_lines == PAGELEN ) { /* full screen? */
reply = see_more(fp_tty, file_read,is_stdin); /* NEW: pass FILE * */
if ( reply == 0 ){ /* n: done */
printf("\n");
break;
}
num_of_lines -= reply; /* reset count */
}
if ( fputs( line, stdout ) == EOF ) /* show line */
exit(1); /* or die */
else
READ_SIZE += strlen(line); //adds the total
num_of_lines++; /* count it */
}
}
int see_more(FILE *cmd, char *file_read, int is_stdin) /* NEW: accepts arg */
{
int c;
if (is_stdin == 0){
if (FIRST_READ == 0){
printf("\033[7m%s: %.1f%%\033[m",file_read,((float)READ_SIZE/(float)FILE_SIZE)*100); /* reverse on a vt100 */
FIRST_READ++;
}else
printf("\033[7m%.1f%%\033[m",((float)READ_SIZE/(float)FILE_SIZE)*100); /* reverse on a vt100 */
}else{
printf("\033[7mbytes %d\033[m",READ_SIZE);
}
while( (c=getc(cmd)) != EOF ) // NEW: reads from tty
{
if ( c == 'q' ) // q -> N
return 0;
if ( c == ' ' ) // ' ' => next p
return PAGELEN; // how many to show
if ( c == '\n' ) // Enter key => 1 line
return 1;
}
}