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
Related
I'm trying to solve some simple example of process synchronization; in this particular example I want three processes: one prints "A", another prints "B" and the last prints "C". I want to print "A" first, then "B" or "C" and again "A", "B" or "C". To be more clear I want an output pattern like "ABACACABACABABACA...."
Below there is my symple code, termination is not managed because this is just an example to understand how things work.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void semaphore_init (int* sw){
if (pipe(sw) == -1) {
printf ("Error\n");
exit (-1);
}
}
void semaphore_wait (int* sw){
char buffer;
if (read(sw[0],&buffer,1) != 1) {
printf ("Error\n");
exit (-1);
}
}
void semaphore_signal (int* sw){
if (write(sw[1],"X",1) != 1) {
printf ("Error\n");
exit (-1);
}
}
int s1[2];
int s2[2];
void childA();
void childB();
void childC();
int main(){
pid_t pid;
semaphore_init(s1);
semaphore_init(s2);
semaphore_signal(s1);
pid=fork();
if(pid==0) childA();
else{
pid=fork();
if (pid==0) childB();
else {
pid=fork();
if(pid==0) childC();
}
}
wait(NULL);
return 0;
}
void childA(){
while(1){
semaphore_wait(s1);
printf("A-");
semaphore_signal(s2);
}
exit(0);
}
void childB(){
while(1){
semaphore_wait(s2);
printf("B-");
semaphore_signal(s1);
}
exit(0);
}
void childC(){
while(1){
semaphore_wait(s2);
printf("C-");
semaphore_signal(s1);
}
exit(0);
}
I don't understand why the output of this code is something like:
A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B
If, instead, I put the "\n" after the char I get the right output.
Could someone, kindly, explain me the reason of that?
In many implementations, including Linux, stdout is line buffered. This means any printf characters are stored to a (memory) buffer until a newline is encountered or the line buffer fills or the stream is flushed. In the example code this results in each process writing to their own local buffer every time it gains the semaphore. So even though the sequencing is correct as you intended but because there are three seperate buffers the final output result is not as you expect. Each process eventually flushes their buffer to stdout but each of those buffers only contain the same letter repeatedly.
The solution is to either add a newline to the printf (as you have found) or to do an explicit fflush(stdout). Another alternative is to use stderr which is not buffered by default: e.g. fprintf(stderr, "A-");
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int ch;
pid_t p = fork();
if (p == 0) {
do {
ch = getchar();
} while (ch >= 0);
return 0;
}
int s;
waitpid(p, &s, 0);
printf("A done\n");
p = 0;
do {
ch = getchar();
} while (ch >= 0 && (++p));
printf("chars: %d\n", p);
return 0;
}
Here's a minimal example code. Theoretically it should read some characters until EOF, and print A done, and read some more characters, and show you how many there are after A done.
However, on my Windows Subsystem for Linux (Ubuntu 18.04), when I hit Ctrl-D for the first time, both the child and parent processes quit (receives an EOF). The output I get is something like
asdfghjkl
^DA done
chars: 0
Why is that? And how do I fix this?
In a fork(2), file descriptors are dup(2)ed, so they share the same file pointer, and what one of the process reads, is not read by the other, as a consequence of this.
A minimalistic example of a program that
reads char by char by getchar, until EOF
starts a child process when an "a" is encountered.
Curiously, installing a signal handler causes getchar to return an EOF whenever a child exits. A rather unwanted side-effect.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void handler() {
//
}
void action() {
if (fork() == 0) {
printf("(action)\n");
sleep(1);
exit(0);
}
}
int main(int argc, char** argv) {
char c;
signal(SIGCHLD, handler); // signal
while (EOF != (c = getchar())) {
if (c == 'a') action();
}
printf("End Of Data\n");
}
The problem disappears when the signal ligne is commented out.
Can someone please explain why this happens?
Seems the same problem as Handling SIGCHLD will return EOF to the father, why?
which has no clear answer about why, and how to avoid this.
EDIT 1: Was not clear to me doesn't mean that much (friday evening...)
The cause is, the system call under getchar() was interrupted, causing it to return EOF (as written in the manual page).
(Ad hoc) Solution: check errno for EINTR.
On this example
while (EOF != (c = getchar()) || errno == EINTR) {
EDIT 2: checking errno works with getchar(), but doesn't make you out of the woods with getline().
The real solution is to forget about the obsolete signal(), and use sigaction() with the SA_RESTART flag.
I have to write a little C program that does the following:
read from stdin
create a child process using fork and encrypt the input with crypt in that child process
use sleep with some random time to simulate the encrypting process and the asynchronous work of the child processes
in my parent process I should catch all the exit-codes of my child processes (using the singal SIGCHLD)
if the user presses Ctrl+C my program should wait for all child processes to finish, then terminate
if the user presses Ctrl+D, I should "ignore" that and read again from stdin
I'm reading from stdin using fgets and I also should catch the EINTR error (I think that's the Ctrl+D "signal"?)
Here is my code so far:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "crypt.h"
#include "signal.h"
#include "errno.h"
#include "sys/wait.h"
char * encryptWord(char* word);
void childTerminated(int sig);
void terminateAllAndExit(int sig);
void nop(int sig);
void readFromStdin();
int childPIDs[1024];
int childProcesses = 0;
int main(int argc, char ** argv) {
readFromStdin();
}
void readFromStdin(void) {
char buffer[1024];
int pid;
while(fgets(buffer, 1024, stdin) != NULL) {
pid = fork();
if(pid == 0) {
signal(SIGINT, nop);
char * encrypted = encryptWord(buffer);
sleep(rand() % 10);
printf("ecnr: %s -> %s\n", buffer, encrypted);
exit(EXIT_SUCCESS);
}
else if(pid > 0) {
signal(SIGCHLD, childTerminated);
signal(SIGINT, terminateAllAndExit);
childPIDs[childProcesses] = pid;
childProcesses++;
}
}
//printf("childProcesses: %d", childProcesses);
}
char * encryptWord(char* word) {
// remove the \n at the end of the input
word[strlen(word)-1] = 0;
word = crypt(word,"sr");
return word;
}
void childTerminated(int sig) {
childProcesses--;
//printf("child terminated.\n");
}
void terminateAllAndExit(int sig) {
//pid_t p;
int status;
//printf("childProcesses: %d\n", childProcesses);
while(childProcesses > 0) {
(void)wait(&status);
if(WEXITSTATUS(status) == EXIT_SUCCESS) {
childProcesses--;
}
}
printf("All child processes terminated. Exiting...\n");
exit(EXIT_SUCCESS);
}
void nop(int sig) {
//signal(SIGINT, nop);
}
The code is working pretty nice now, encrypting works in my child processes and simulating the time they need to encrypt the input.
But, if I press Ctrl+C it's not working how it should. All child processes terminate immediately instead of waiting the time I've set in sleep.
And the last one, how can I catch the EINTR error?
Thank's for your help!
Does anyone know why the printf("Type q to quit") line prints twice in the terminal when I run this code:
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
char run[2];
run[0]='a';
int pid=0;
while (run[0]!= 'q')
{
printf("Type q to quit \n");
fgets (run, 2, stdin);
pid=fork();
//wait();
if(pid==0) { break;}
}
}
I would like the child to break from the loop and the parent to continue looping (to create new children). If I call wait() the execution ends after the first iteration regardless of whether I enter 'q' or not. Otherwise it works as expected but prints the "Type q to quit" line twice every time. Why does this happen?
You have three bugs. First, the carriage return that the user types, after whatever letter, counts as input. Assuming the user types only one character per line, your fgets calls will alternate between returning the character you care about, and returning '\n'. You need to read and discard characters until you reach the end of each line of input, on each iteration. This is what is causing the double printouts.
Second, you need to test for 'q' in between reading from stdin and calling fork; right now, you fork once more after reading the 'q'. Right now this is invisible, but once the child process starts doing something useful it won't be.
Third, this program will go into an infinite loop if the user types ^D at it, because you're not checking for EOF.
Putting that together, corrected code looks like this. I've also fixed some style nits, and arranged so that the parent process exits immediately rather than dropping out of the for loop; this means that when control reaches the point marked with a comment, you know you're in a child process, rather than in the parent on its way out.
#include <stdio.h>
#include <unistd.h>
int
main(void)
{
pid_t pid;
int c;
for (;;)
{
puts("Type q to quit");
c = getchar();
if (c == 'q')
return 0;
if (c == '\n')
continue;
while (c != EOF && c != '\n')
c = getchar();
if (c == EOF)
return 0;
pid = fork();
if (pid == 0)
break;
else if (pid == -1)
{
perror("fork");
return 1;
}
}
/* control reaches this point only in child processes */
return 0;
}
When you type x<enter> on your terminal, you'll get (assuming ordinary encodings all over) two bytes sent to your process: one for the x, one for the newline.
Your fgets call reads at most one byte (so, the x), forks of a child that dies "instantly", prints the messages and calls fgets. fgets picks up where it left: it reads the newline char without blocking, your code forks again for no reason, and loops back.
At that point there's nothing left in the input stream, so fgets waits for I/O.
See for example: I am not able to flush stdin for ways to "clear out" the input stream that you could use here.
You need to wait for these forked process down the line:
int main (int argc, char *argv[])
{
char run[2];
run[0]='a';
int pid=0;
int pids[256]; // should be enough.
int j,i = 0;
while (run[0]!= 'q')
{
printf("Type q to quit \n");
fgets (run, 2, stdin);
pid=fork();
//wait();
if(pid==0) { break;}
else { pids[i] = pid; i++; }
}
for (j = 0 ; j < i && pid != 0 ; j++)
wait(pids[j]);
if(pid == 0){
// do something
}
}
You could instead have the child call another function (such as a program wrapper or even itself in non-forkable version) instead of breaking. The waiting would remain the same i.e. wait only once all forks are, well, forked.