Uppercase letter using pipe in C - c

#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
static struct termios old, new;
/* Initialize new terminal i/o settings */
void initTermios(int echo)
{
tcgetattr(0, &old); /* grab old terminal i/o settings */
new = old; /* make new settings same as old settings */
new.c_lflag &= ~ICANON; /* disable buffered i/o */
new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */
}
/* Restore old terminal i/o settings */
void resetTermios(void)
{
tcsetattr(0, TCSANOW, &old);
}
/* Read 1 character - echo defines echo mode */
char getch_(int echo)
{
char ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
/* Read 1 character without echo */
char getch(void)
{
return getch_(0);
}
/* Read 1 character with echo */
char getche(void)
{
return getch_(1);
}
void INThandler(int);
void INThandler(int sig)
{
char c;
signal(sig, SIG_IGN);
printf("\n Ctrl+c foi detetado, clique y para confirmar \n");
c = getchar();
if(c == 'y' || c == 'Y')
exit(0);
else
signal(SIGINT, INThandler);
getchar();
}
int main()
{
signal(SIGINT, INThandler);
int fd[2];
char readbuffer[80];
pipe(fd);
int pid = fork();
char ch;
if(pid < 0)
{
printf("\n Erro");
exit(1);
}
else if(pid == 0)
{
close(fd[0]);
do
{
ch = getch();
write(fd[1], &ch, sizeof(ch));
} while(ch != '\n');
getchar();
}
else
{
close(fd[1]);
while(1)
{
read(fd[0], readbuffer, sizeof(readbuffer));
char upper = toupper(readbuffer[0]);
char down = tolower(readbuffer[0]);
if(readbuffer[0] != upper)
{
printf("%c \n", upper);
}
else
{
printf("%c \n", down);
}
}
}
return(0);
}
So basically this is a task that is: Using communication between processes, convert automatically upper letters to small letters, and small letters to upper letters, without them appearing in input. Basically I don't see my input just the output. And when CTRL+C is hit, the program should recognize it and ask for a confirmation by asking the user to type "y".
My program runs, but when I remove the \n from "printf("%c \n", upper);" and from "printf("%c \n", down);" the program starts acting weird... When I remove it I have to hit enter to see the output, but with it it appears automatically just like I wanted... Can someone explain me why?
I am using ubuntu.

printf doesn't actually print to stdout immediately -- it just puts characters into an output buffer to be flushed to stdout at some later point. That "later point" is generally whenever a newline is printed if the output is a terminal, but you can change that with setbuf:
setbuf(stdout, 0); // set stdout to unbuffered
after which every call to printf will immediately flush the buffer. Alternately, you can use fflush(stdout) to flush the buffer at any specific point in your program.

Related

Fflush does not write buffered text

I'm trying to print a 2D table to my terminal using this code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <sys/wait.h>
char getch()
{
char ch;
struct termios old, new;
tcgetattr(0, &old); // grab old terminal i/o settings
new = old; // new settings = old settings
new.c_lflag &= ~ICANON; // disable buffered i/o
new.c_lflag &= ~ECHO; //set echo mode
tcsetattr(0, TCSANOW, &new); // use these new terminal i/o settings now
ch = getchar();
tcsetattr(0, TCSANOW, &old); //restore old settings
return ch;
}
void readPBM(char *output)
{
char tmp[1024];
int fd[2] = {0,0};
int pid;
//Open the pipe for inter-process communication
pipe(&fd[0]);
//Fork and test if we are child or parent process
pid = fork();
if(pid) //Parent process
{
wait(NULL); //Wait for child's end
close(fd[1]);//Close pipe's write stream
close(0);//Close stdin
dup(fd[0]);//Duplicate stdout
close(fd[0]);//Close old stdout
strcpy(output, "");// Init output at 0
while(fgets(tmp, 1024, stdin) != NULL) //Put remaining entry in output
{
strcat(output, tmp);
}
}
else if(pid == 0) //Child process
{
close(fd[0]);//Close pipe's read stream
close(1);//Close stdout
dup(fd[1]);//Duplicate stdin
close(fd[1]);//Close old stdin
printf("A random string ...\n");
}
else //Print error if fork failed
{
printf("Error creating a new process");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
int i, j;
char *str = NULL;
char c;
str = malloc(512 * sizeof(char*));
readPBM(str);
printf("%s", str);
fflush(stdout);
c = getch();
}
I have a UNIX implementation of getch().
My problem is that my program is waiting for an input to print the table. I tried to fflush(stdout) and to disable terminal buffering with ICANON but it's still not working.
PS: it's not working neither with getchar, scanf, ...
EDIT: So I came up to this minimal example; it seems to be pipe-related.
My problem is that my program is waiting for an input to print the table.
This is because you forgot to terminate the child process when it has done its work, so after printing A random string ... to the pipe it continues, returning from readPBM() and eventually executing the c = getch() at the end of main(). The remedy is to call exit(0) at the end of the if(pid == 0) //Child process block.

Pipe cannot read Enter key (C , Linux)

I a beginner and I am writing a bi-direction communication programme in C, Linux for assignment submission. However, I've test and found that "enter" key is not readable via pipe as it contains 0 byte. If I accidentally press enter before normal characters are typed, the 2 screens turn to deadlock and cannot communicate. I tried getchar() or check the byte=0, but I don't know which position I should put the command to make it works. Any Ideas? Thanks
(Below is sender, I want the programme can send and receive msg)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main()
{ char pipename1[] = "/tmp/pipe1"; /* pathname of the named pipe */
char buf1[80];
char pipename2[] = "/tmp/pipe2"; /* pathname of the named pipe */
char buf2[80];
int i, n1,n2, fd1, fd2;
mkfifo(pipename1,0666);
printf("Please run receiver in other putty. \n");
fd1 = open(pipename1,O_WRONLY);
fd2 = open(pipename2,O_RDONLY);
while(1){
printf("Please enter a message. <To check message, press Enter>\n");
n1 = read(STDIN_FILENO,buf1,80); /* read a line */
if (n1 <= 0) break;
buf1[--n1] = 0;
write(fd1,buf1,n1); /* send the string */
while ((n2 = read(fd2,buf2,80)) > 0) { /* read from pipe */
buf2[n2] = 0;
printf("\n <player2> [%s] \n",buf2,n2);
break;}
}
close(fd1);
close(fd2);
unlink(pipename1);
unlink(pipename2);
exit(0); }
(Edited) Actually I created another end to read msg, code is below
int main()
{ char pipename1[] = "/tmp/pipe1"; /* pathname of the named pipe */
char buf1[80];
char pipename2[] = "/tmp/pipe2"; /* pathname of the named pipe */
char buf2[80];
int i, n1,n2, fd1, fd2;
mkfifo(pipename2,0666); /* make file with the file name defined in pipename1, 0666 is permission every one can read & write */
printf("Please run receiver programme in another browser\n");
fd1 = open(pipename1,O_RDWR);
fd2 = open(pipename2,O_RDWR);
while(1){
printf("<Please enter a message.\n");
n2 = read(STDIN_FILENO,buf2,80); /* read a line */
if (n2 <= 0) break;
buf2[--n2] = 0;
write(fd2,buf2,n2); /* send the string */
while ((n1 = read(fd1,buf1,80)) > 0) { /* read from pipe */
buf1[n1] = 0;
printf("\n <player1>[%s]\n",buf1,n1);
break;}
}
close(fd1);
close(fd2);
exit(0);
}
The problem is that you write to the pipe (using fd1) but you don't read from it. Instead you open a totally unrelated filed and attempt to read from it.
A named pipe in the file-system is the single file initialized by mkfifo, and as all other pipes it has a write-end and a read-end, and both ends are accessed by opening the same file.

Can't seem to find an EOF character?

I have:
#include <stdio.h>
/* Copy input to output; 2nd version. */
main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
I want to terminate the while loop by entering an end-of-line character.
I Have Tried Inputing:
"\t"
"\0"
%d
%f
%c
%x
%n
EOF
"EOF"
\nEOF
int
float
char
long
long long
array
1 => 10
all letters
all symbols on keyboard
.
.
.
Question: What is the magical EOF character that I'm looking for?
*I am Sorry if this is a really easy question for you,but please be nice I'm only a beginner trying to learn something.
On Windows, Ctrl+Z;
on Linux, Ctrl+D.
There is NO EOF character. "EOF" is a logical condition that represents "end of file" has been met.
On Linux machine, you can "signal" the standard input EOF condition by pressing Ctrl+D in the beginning of the line.
Windows systems reserve a character Ctrl+Z, which is 0x1A in hex, to indicate this "end of file" condition. You can input this character by pressing Ctrl+Z. It is still not a real EOF character though. Rather, it is a convention in Windows.
Here ya go #Andy. You just used an int by accident instead of char c.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char c;
while ((c = getchar()) != '\t') // while input != tab, remember to use single
putchar(c); // quotes for characters '\n' etc.
system("pause");
return 0;
}
If you are curious about the signals in UNIX/LINUX system this code might help, wrote it for one of my OS labs. Essentially, the program keep asking for a user input. However, when you try to quit during in the beginning with ctrl+z or ctrl+c it doesn't allow you to because the signal gets ignored by the parent and gets handled by the signal handlers for the child process. Note, the parent is sleeping in the beginning, but when it wakes up it kills the child process and ends the program.
#include <stdio.h>
#include <signal.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/wait.h>
#define maxLength 1024
//****************************************
// Signal Handlers For Child Process
//****************************************
void ctrlchandler(){
signal(SIGINT, SIG_IGN); //Ignore ctrl-c
write(1, "Don't even think about it!", 26);
}
void ctrlzhandler(){
signal(SIGTSTP, SIG_IGN); //Ignore ctrl-z
write(1, "Nice Try.", 9);
}
//****************************************
// Main Program
//****************************************
int main(int argc, char* argv[]){
pid_t pid;
int status;
//Dynamically allocate char array for input line
char *inputLine = (char*)malloc(maxLength*sizeof(char));
//Ignore Ctrl-z and Ctrl-c
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
//Fork Process
if((pid = fork())<0){
//If fork fails
printf("Fork Child Process Faild.\n");
}
//Parent Process
else if(pid != 0){
printf("Parent: My child %d has been spawned.\n",pid);
printf("My pid is %d\n",getpid());
sleep(30);
kill(pid, SIGKILL);
if(waitpid(pid, &status, WUNTRACED))
printf("Child %d has terminated abnormally.\n",pid);
}
//Child Process
else{
sleep(1); //Wait for parent to output first
while(1){
signal(SIGTSTP, ctrlzhandler);
signal(SIGINT, ctrlchandler);
printf("Enter Input:");
fgets(inputLine, maxLength, stdin);
}
}
//Free allocated char array
free(inputLine);
return 0;
}
main()
{
printf ("%d=%x sizeof=%d\n", EOF, EOF, sizeof(EOF));
}
The output is:
-1=ffffffff sizeof=4
EOF is not a char, it is an int
if you type the Control sequence signifying end of file - it will be translated to an int whose value is -1

how to store output from "bc" into a variable?

What this program is supposed to do is ask user a simple arithmetic question, e.g. 5 + 7 and then check the answer with "bc" (whether it's correct).
I have the following code, but I don't understand how to edit it to to store the result from "5 + 7" into a variable (currently the result goes into STDOUT).
Any help is welcome.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main( int argc, char *argv[], char *env[] )
{
char *expr = "5 + 7\n";
int answer;
printf("%s = ", expr);
scanf("%d", &answer);
int pfds[2];
pipe(pfds);
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
printf("%s\n", expr);
/***********************/
/* How to store printf()'s output into a variable? */
exit(0);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
execlp("bc", "bc", NULL);
}
return 0;
}
You need to create a second pipe and redirect stdout to it in the child process.
You can simply read STOUD or read on your pipe's Output. Then a call to Read() and to Atoi might do the work. Atoi man page here
I can't code it for you, but here the logic
`int fds[2];
pipe(fds);
dup2(fds[1], stdout);
read(fds[1], buf, buf_sz);
int ResultOfbc = Atoi(buf)`
Ooof oof, this stuff I remember doing last year.
I was basically a program which used my own telnet clone to communicate with the internet.
Problem is telnet used stdin and stdout to work.
It looks like you have the same situation!
What I did to solve this was to fork a process, grab stdin and stdout and put them in pipes and then overwrite the forked process image with an invocation of telnet (which now instead of stdin and stdout, uses those pipes).
You need ONE pipe to send text to bc and ANOTHER to receive from bc.
If you use a single pipe for everything, chances are you'll end up reading what you sent to bc and mix data.
WARNING: MASSIVE AMOUNT OF CODE INCOMING.
I'm sure you won't need to understand everything, since I use threads to write and read simultaneously and select() to see if there's anything to read in the pipe.
VERY IMPORTANT!!! When communications break, your process will receive SIGPIPE which terminates not cleanly (if you're using dynamic memory or stuff like that).
And you MUST fflush(outpipe) or else bc won't receive it. (This is because system only flushes when it finds '\n' or something like that, if I recall correctly).
I put all the code just in case you want to read what X does. But what you need is only the small fork right after the comment "LOCAL FUNCTIONS END HERE"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <stdbool.h>
#include "irc.h"
#include "coloring.h"
#include "rtsp.h"
#define BUFFERSIZE 255
int main (int argc, char *argv[]) {
/* XXX: When kid dies, program doesn't exit */
char *serverName, *port, *nick, *channel;
int ptelnetin[2];
int ptelnetout[2];
FILE *fpipes[2];
bool running = true;
pid_t kid;
pthread_t pthread_input, pthread_output;
/************************************************
LOCAL FUNCTIONS START HERE
***********************************************/
void *inputprocess(void *pipes) {
bool bracket;
int i;
fd_set rfds;
struct timeval tv;
tv.tv_sec = 0.2;
tv.tv_usec = 0;
char buffer[BUFFERSIZE];
FILE *out = ((FILE **) pipes)[1];
while (running){
FD_ZERO(&rfds);
FD_SET(fileno(stdin), &rfds);
switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) {
case -1:
fprintf(stderr, "Error reading data at select() Line %d, File %s\n", __LINE__, __FILE__);
running = false;
break;
case 0:
/* There's no data avaiable just yet.
Do nothing and keep checking */
break;
default:
/* This check needs to be done;
select isn't completely reliable */
if(!fgets(buffer, BUFFERSIZE, stdin)) {
running = false;
break;
}
/* Check message not to contain brackets*/
for (i = 0, bracket = false; running && !bracket && buffer[i] && i < BUFFERSIZE; i++) {
if (buffer[i] == '[' || buffer[i] == ']') {
PRINT_YELLOW;
printf("Use of brackets not allowed\n");
RESET_COLOR;
fflush(stdout);
bracket = true;
break;
}
}
if (running && !bracket) ircInputWrite(out, buffer);
fflush(out);
}
}
}
void *outputprocess(void *pipes){
fd_set rfds;
struct timeval tv;
tv.tv_sec = 0.2;
tv.tv_usec = 0;
char buffer[BUFFERSIZE];
char from[100];
FILE *in = ((FILE **) pipes)[0];
FILE *out = ((FILE **) pipes)[1];
while (running){
FD_ZERO(&rfds);
FD_SET(fileno(in), &rfds);
switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) {
case -1:
fprintf(stderr, "Error reading data at select() Line %d, File %s\n", __LINE__, __FILE__);
running = false;
break;
case 0:
/* There's no data avaiable just yet. */
/* Select sometimes returns 0 when there IS
data to read so we'll read anyway */
default:
/* This check needs to be done;
select isn't completely reliable */
if(!fgets(buffer, BUFFERSIZE, in)) {
running = false;
break;
}
switch(ircWhatsthis(buffer)) {
case iPING:
PRINT_BLUE;
printf("PingPong!\n");
RESET_COLOR;
ircPingPong(out, buffer); fflush(out);
fflush(stdout);
break;
case iROOMMSG:
if (ircUnpackPRIVMSG(from, buffer, buffer)) {
PRINT_BRIGHT_RED;
fprintf(stdout, "Malformed private message received\n");
RESET_COLOR;
}
else {
PRINT_CYAN;
printf("<%s>: ", from);
puts(buffer);
RESET_COLOR;
}
fflush(stdout);
break;
case iPRIVMSG:
fflush(stdout);
if (ircUnpackPRIVMSG(from, buffer, buffer)) {
PRINT_BRIGHT_RED;
fprintf(stdout, "Malformed private message received\n");
RESET_COLOR;
fflush(stdout);
}
else {
if (rtspExecBrackets(out, from, buffer)) {
PRINT_BRIGHT_MAGENTA;
printf("[%s]: ", from);
puts(buffer);
RESET_COLOR;
fflush(stdout);
}
}
break;
case iERROR:
PRINT_BRIGHT_RED;
fwrite(buffer, sizeof(char), strlen(buffer)+1, stdout);
RESET_COLOR;
break;
case iOK:
PRINT_BRIGHT_CYAN;
fwrite(buffer, sizeof(char), strlen(buffer)+1, stdout);
RESET_COLOR;
break;
default:
PRINT_BRIGHT_BLACK;
fwrite(buffer, sizeof(char), strlen(buffer)+1, stdout);
RESET_COLOR;
}
fflush(stdout);
}
}
}
void terminate(int signum) {
/* XXX irc.c calls rtsp.c which uses threads.
These threads never clean up if exiting via ^C
*/
RESET_COLOR;
running = false;
/*Close IO*/
fclose(fpipes[0]);
fclose(fpipes[1]);
/* Call child */
kill(kid, SIGINT);
wait(NULL);
exit(0);
}
/************************************************
LOCAL FUNCTIONS END HERE
***********************************************/
signal(SIGPIPE, terminate);
signal(SIGINT, terminate);
/* Get parameters */
if (argc != 5) {
fprintf(stderr, "Usage:\n %s <server> <port> <nick> <channel>\n", argv[0]);
return -1;
}
serverName = argv[1];
port = argv[2];
nick = argv[3];
channel = argv[4];
/* Startup pipes */
pipe(ptelnetin);
pipe(ptelnetout);
/* Launch telnete */
switch (kid = fork()) {
case -1:
perror("OMG ABORTION at main");
exit(-2);
case 0: /* CHILD */
/*Overwrite stdin with pipein and discard pipe*/
dup2(ptelnetin[0], 0);
close(ptelnetin[0]);
close(ptelnetin[1]);
/*Overwrite stdout with pipeout and discard pipe*/
dup2(ptelnetout[1], 1);
close(ptelnetout[0]);
close(ptelnetout[1]);
/*Overwrite process image with telnete*/
execlp("./telnete", "./telnete", argv[1], argv[2], (char *) NULL);
perror("Call to exec failed at main");
exit(-3);
default: /* PARENT */
/* Close reading end of pipein */
close(ptelnetin[0]);
/* Close writing end on pipeout */
close(ptelnetout[1]);
}
/* Turn (fileno) into (FILE *) */
fpipes[1] = fdopen(ptelnetin[1],"w");
if(!fpipes[1]) {
perror("Error at fdopen(in) at main");
kill(kid, SIGINT);
abort();
}
fpipes[0] = fdopen(ptelnetout[0],"r");
if(!fpipes[0]) {
perror("Error at fdopen(out) at main");
kill(kid, SIGINT);
abort();
}
/* Sleep for a few seconds so server doesn't ignore it */
PRINT_YELLOW;
printf("Logging in IRC...\n");
RESET_COLOR;
fflush(stdout);
if (ircRegister(argv[3], fpipes[1], fpipes[0])) {
fprintf(stderr, "Error registering in IRC.\n");
terminate(-1);
}
PRINT_YELLOW;
printf("Joining room %s\n", argv[4]);
RESET_COLOR;
ircJOIN(fpipes[1], argv[4]);
fflush(fpipes[1]);
/* Launch threads */
if (pthread_create(&pthread_input, NULL, inputprocess, fpipes)){
fprintf(stderr,"Couldn't launch input thread");
kill(kid, SIGINT);
abort();
}
if (pthread_create(&pthread_output, NULL, outputprocess, fpipes)){
fprintf(stderr,"Couldn't launch output thread");
kill(kid, SIGINT);
abort();
}
/* Wait for threads */
if (pthread_join(pthread_input,NULL)){
fprintf(stderr, "Error joining thread.\n");
}
if (pthread_join(pthread_output,NULL)){
fprintf(stderr,"Error joining thread.\n");
}
terminate(0);
}
I'll put the key fragment here so it's clearer:
/* Startup pipes */
pipe(ptelnetin);
pipe(ptelnetout);
/* Launch telnete */
switch (kid = fork()) {
case -1:
perror("OMG ABORTION at main");
exit(-2);
case 0: /* CHILD */
/*Overwrite stdin with pipein and discard pipe*/
dup2(ptelnetin[0], 0);
close(ptelnetin[0]);
close(ptelnetin[1]);
/*Overwrite stdout with pipeout and discard pipe*/
dup2(ptelnetout[1], 1);
close(ptelnetout[0]);
close(ptelnetout[1]);
/*Overwrite process image with telnete*/
execlp("./telnete", "./telnete", argv[1], argv[2], (char *) NULL);
perror("Call to exec failed at main");
exit(-3);
default: /* PARENT */
/* Close reading end of pipein */
close(ptelnetin[0]);
/* Close writing end on pipeout */
close(ptelnetout[1]);
}
/* Turn (fileno) into (FILE *) */
fpipes[1] = fdopen(ptelnetin[1],"w");
if(!fpipes[1]) {
perror("Error at fdopen(in) at main");
kill(kid, SIGINT);
abort();
}
fpipes[0] = fdopen(ptelnetout[0],"r");
if(!fpipes[0]) {
perror("Error at fdopen(out) at main");
kill(kid, SIGINT);
abort();
}
After doing this you can read bc's result from the (FILE *) fpipes[0] and write to it in fpipes[1].
Remember to fflush(fpipes[1]) after each write.
Treat those two as you would with any file.

how use the select function in c for read from stdin one more time?

i use this code for test
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
fd_set rfds;
struct timeval tv;
int retval, len;
char buff[255] = {0};
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
do{
/* Wait up to five seconds. */
tv.tv_sec = 2;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1){
perror("select()");
exit(EXIT_FAILURE);
}
else if (retval){
/* FD_ISSET(0, &rfds) is true so input is available now. */
/* Read data from stdin using fgets. */
fgets(buff, sizeof(buff), stdin);
/* Remove trailing newline character from the input buffer if needed. */
len = strlen(buff) - 1;
if (buff[len] == '\n')
buff[len] = '\0';
printf("'%s' was read from stdin.\n", buff);
}
else
printf("No data within five seconds.\n");
}while(1);
exit(EXIT_SUCCESS);
}
i need that if the program read from stdin use printf, else if not use a printf with other string. The problem arises in the input
'd' enter
none enter
'd' enter
the program respond with the printf text of the none enter

Resources