How do i get this to properly exit the program? - c

So i am trying to get this program to simply exit but i can seem to get it to work.
i tried a lot of things. one thing i found odd as well is if i made x = 0 in the while loop it would immediately exit the program so i had to make it x !=0. i dont understand what that is so if you can answer that as well that would be nice.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char a[256];
int x = 0;
while (x != 0) {
int y = strcmp(fgets(a, 256, stdin), "exit");
if (y==0) {
exit(0);
}
else {
printf("Line read:%s\n",a);
}
}
return 0;
}
so it should output right now something like this(i am also running this in a linux terminal):
//input://
hello
//output://
Line read: hello
//(program stays open for more inputs)//
//input//
exit
//(the program now closes in the terminal and you return to directory)//

The keyboard input contains a new line at the end. Change "exit" to "exit\n" in call to strcmp.

Related

How is the speed of printf affected by a presence of a forked process and '\n'?

I had this simple shell like program that works both in interactive and non-interactive mode. I have simplified the code as much as I can to present my question, but it is still a bit long, so sorry for that!
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/**
*main-entry point for gbk
*Return: returns the index of 0 on sucess
*/
int main(void)
{
char *cmd = malloc(1 * sizeof(char)), *cmdargs[2];
size_t cmdlen = 0;
int childid, len;
struct stat cmdinfo;
while (1)
{
printf("#cisfun$ ");
len = getline(&cmd, &cmdlen, stdin);
if (len == -1)
{
free(cmd);
exit(-1);
}
/*replace the ending new line with \0*/
cmd[len - 1] = '\0';
cmdargs[0] = cmd;
cmdargs[1] = NULL;
childid = fork();
if (childid == 0)
{
if (stat(*cmdargs, &cmdinfo) == 0 && cmdinfo.st_mode & S_IXUSR)
execve(cmdargs[0], cmdargs, NULL);
else
printf("%s: command not found\n", *cmdargs);
exit(0);
}
else
wait(NULL);
}
free(cmd);
exit(EXIT_SUCCESS);
}
To summarize what this program does, it will first print the prompt #cisfun$ , waits for an input in interactive mode and takes the piped value in non-interactive mode, creates a child process, the child process checks if the string passed is a valid executable binary, and if it is, it executes it other wise it prints a command not found message and prompts again.
I have got this program to work fine for most of the scenarios in interactive mode, but when I run it in non-interactive mode all sorts of crazy (unexpected) things start to happen.
For example, when I run echo "/bin/ls"|./a.out, (a.out is the name of the compiled program)
you would first expect the #cisfun$ message to be printed since that is the first thing performed in the while loop, and then the output of the /bin/ls command, and finally #cisfun$ prompt, but that isn't what actually happens. Here is what happens,
It is very weird the ls command is run even before the first print message. I, at first, thought there was some threading going on and the printf was slower than the child process executing the ls command. But I am not sure if that is true as I am a noob. and also things get a bit crazier if I was printing a message with '\n' at the end rather than just a string. (if I change printf("#cisfun$ "); to printf("#cisfun$\n");) the following happens,
It works as it should, so it got me thinking what is the relation between '\n', fork and speed of printf. Just in short what is the explanation for this.
The second question I have is, why doesn't my program execute the first command and go to an interactive mode, I don't understand why it terminates after printing the second #cisfun$ message. By checking the status code (255) after exit I have realized that the effect is the same as pressing ctr+D in the interactive mode, which I believe is exited by the getline function. But I dont understand why EOF is being inserted in the second prompt.

Why isn't my code terminating within a loop when checking for 'exit' string?

My program is supposed to exit when the user types in exit similar to how its done in a shell. First I checked online to see if syscall could be called in a loop, but then I noticed the indices of the characters in the array are wrong. Why are these changing; when I ran the program and typed in exit I had my program shoot out the 3rd index for testing purposes and it returned 'e'. So I thought it might've been flipped and flipped all values and my exit still did not work. Any thoughts on what the underlying issue may be?
#include <stdio.h>
//Abstract: This program runs a script to emulate shell behavior
#define MAX_BIN_SIZE 100
int main() { //Memory allocation
char * entry[MAX_BIN_SIZE];
while(1)
{
printf("msh>");
fgets(entry,MAX_BIN_SIZE,stdin); //Getting user input
if(entry[0]=='t' && entry[1]=='i' && entry[2]=='x' && entry[3]=='e')
{
//printf("Exiting");
exit(0); //exit(system call)
break;
printf("Inside of exit");
}
printf("msh> you typed %s %c %c %c %c",entry,entry[3],entry[2],entry[1],entry[0]); //returning user input
}
return 0;
}
I am sorry I don't have enough reputation points to add a comment, but #lundman is correct. I don't think you need to create a pointer to entry. Also, you are checking for "exit" in the reverse order. I tried and edited the code; this seems to work:
#include <stdio.h>
//Abstract: This program runs a script to emulate shell behavior
#define MAX_BIN_SIZE 100
int main()
{ //Memory allocation
char entry[MAX_BIN_SIZE];
while(1)
{
printf("msh>");
fgets(entry,MAX_BIN_SIZE,stdin); //Getting user input
if(entry[0]=='e' && entry[1]=='x' && entry[2]=='i' && entry[3]=='t')
{
printf("Inside of exit");//printf("Exiting");
exit(0); //exit(system call)
}
printf("msh> you typed %s %c %c %c %c\n",entry,entry[3],entry[2],entry[1],entry[0]); //returning user input
}
return 0;
}

Not working properly. What am I missing?

the program is still very empty and "naked" because im just trying to get the logic out of the way before I actually start making functions. For some reason, whatever my argv[1] is, it always prints "The help message". What am I missing? I have a bad feeling about that for statement, but I dont know whats wrong with it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void help()
{
printf("The help message\n");
exit(1);
}
void a()
{
printf("The a screen\n");
exit(1);
}
int main(int argc, char *argv[])
{
char recognised_commands[3] = {help(), a()};
int i;
if (argc != 2)
{
fprintf(stderr, "usage of sake: \"sake [option(s)]\"\nFor a full listing of all available commands type \"-help\" or \"--help\"\n\n");
exit(1);
}
for (i = recognised_commands[0]; i != recognised_commands; i++)
{
printf(argv[1]);
}
}
Edit 1: djikay: Fixed the -1 to 0,
Ricky: How do I correct the help() and the a() to only call the one the user inputs after the program name (EX: sake -a)? I also fixed the exit(0). Thanks
The line:
char recognised_commands[3] = {help(), a()};
causes both help and a to be called. help is called first, and it prints out the help message & exits the program.
char recognised_commands[3] = {help(), a()};
This line is definitely your issue. help() and a() are both being called, thus exiting your program.
Why are you trying to assign those function return values there? Both of the functions are void in return type, meaning they won't return anything anyways.
On a side note, calling exit() with 0 as the argument means your program exited without errors. I'd exit with 1 if it's because of an error (or even better, EXIT_SUCCESS and EXIT_FAILURE, respectively).

why printing to "stdout" not executing sequentially?

My friend gave me a riddle. I run it. but not getting expected output.
Code is:
#include <stdio.h>
#include <unistd.h>
int main()
{
while(1)
{
fprintf(stdout,"hello-out");
fprintf(stderr,"hello-err");
sleep(1);
}
return 0;
}
the output doesn't printing hello-out.
Instead it's printing like this infinitely:
hello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-err
Then I tried like this:
#include <stdio.h>
#include <unistd.h>
int main()
{
int i = 0;
while(i <= 5)
{
fprintf(stdout,"hello-out");
fprintf(stderr,"hello-err");
sleep(1);
i++;
}
return 0;
}
the optput is:
hello-errhello-errhello-errhello-errhello-errhello-errhello-outhello-outhello-outhello-outhello-outhello-out
In C language instructions execute line by line. But why it is not following here?
File IO behavior is determined by the system and if you want to keep that order you must explicitly fflush. See this program below:
while(i <= 5)
{
fprintf(stdout,"hello-out");
fflush(stdout);
fprintf(stderr,"hello-err");
fflush(stderr);
sleep(1);
i++;
}
The reason is output buffering.
By default, stdout is buffered: if it's connected to a terminal it's line-buffered, otherwise it's fully-buffered. When it's line-buffered, that means that nothing is printed until you print a newline, the buffer fills up, or the buffer is flushed explicitly. Since you're not printing newlines, the output doesn't show up until the program exits, because all stdio buffers are flushed at that time.
stderr, on the other hand, is not buffered by default. So anything written to it appears immediately.

Does ncurses getch() with echo() on ensure that the character will be visible on the screen before the next statement in the program is executed?

I have an ncurses program that looks like this
1. int c =0;
2. initscr();
3. timeout(-1);
4. printw("Enter a character");
5. getch();
6. printw("\nOkay\n");
7. c = 5;
I would expect that the output of getch() as well as following printw() should happen (and be visible on the screen) before c is modified to 5. However this does not seem to be happening ( Using qemu-kvm and breaking at that point to verify). Is there any reason why this might be happening or some way to ensure the output being visible on the screen before the next statement is executed ?
does fflush(stdout) guarantee that ?
The OS is virtualized gentoo being run using qemu-kvm. The screen is in console mode ( X not initialized).
You are probably forgetting to issue the refresh() command. See the following example code which appears to work:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <curses.h>
int main(void) {
WINDOW * mainwin;
int c=0;
/* Initialize ncurses */
if ( (mainwin = initscr()) == NULL ) {
fprintf(stderr, "Error initialising ncurses.\n");
exit(EXIT_FAILURE);
}
timeout(-1);
printw("Enter a character: ");
getch();
printw("\nC = %d Ok\n", c);
c = 5;
printw("C is now %d\n",c);
refresh();
sleep(10);
/* Clean up after ourselves */
delwin(mainwin);
endwin();
refresh();
return EXIT_SUCCESS;
}

Resources