PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label fgets. Show all posts
Showing posts with label fgets. Show all posts

Monday, October 31, 2022

[FIXED] How do you detect ctrl+D in C?

 October 31, 2022     c, eof, fgets, segmentation-fault, stdin     No comments   

Issue

So I read in a line using fgets

line = fgets(l, BUFSIZ, stdin);

And I from what I understand control+d is EOF so I tried

if(line[0] == EOF)
     continue;

to get back to the top of the loop. But this led to segfaults... Is there another way?


Solution

Since the machine generates EOF on Ctrl + D, you should be checking fgets() for NULL, as fgets() is obliged to return NULL on end of file.

line = fgets(l, BUFFSIZ, stdin)
if (line == NULL)
    continue;

In your code, you are trying to dereference a pointer that's NULL leading to segfault.



Answered By - Arjun Sreedharan
Answer Checked By - Mildred Charles (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] Why does EOF behave differently in fgets and read

 October 31, 2022     c, eof, fgets, linux     No comments   

Issue

#include <stdio.h>

#define MAXLINE 4096

int 
main(int argc, char **argv)
{
    char           *s;
    char            buf[MAXLINE];

    s = fgets(buf, MAXLINE, stdin);    // here, if replaced with read(0, buf, MAXLINE);        

    return 0;
}

Input is:12ctrl+d

  1. fgets doesn't return until input ctrl+d again(That is: 12ctrl+dctrl+d). Why doesn't fgets return when it encounts the first EOF? It seems 12ctrl+d doesn't work.

  2. But when s = fgets(buf, MAXLINE, stdin); is replaced with read(0, buf, MAXLINE); read will return(input is also: 12ctrl+d).


Solution

Hitting CTRL+d on the terminal:

  • simply means flush all the characters in stdin (the input buffer) immediately
  • it does NOT trigger an EOF condition on stdin
    (unless the current line/buffer is co-incidentally empty.)

So hitting CTRL+D while running a program,

  • a blocked fgetc() will return if you do it twice consecutively.
    1st = flush currently buffered characters,
    2nd = flush empty buffer; i.e. EOF condition is valid for fgetc() and it returns
    .
  • a blocked fgetc() will return if you do it once on an empty-line.
    flushes an already empty stdin buffer, i.e. EOF condition is valid for fgetc() and it returns.
  • a blockedread() returns immediately as soon as the input is flushed.

Checkout the answers to this question for more details.



Answered By - TheCodeArtist
Answer Checked By - Willingham (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, October 29, 2022

[FIXED] Why do i have to input EOF 3 times when using fgets?

 October 29, 2022     c, eof, fgets, stdin, while-loop     No comments   

Issue

So basically I want to copy everything i write to stdin (including newline char) to string for hash purposes. I managed to accomplish that and made small code to represent my problem.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUFFERSIZE 10000

int main()
{
char *myStr = calloc(1,1);
char buffer[BUFFERSIZE];

while( fgets(buffer, BUFFERSIZE , stdin) != NULL ){
  myStr = realloc(myStr, strlen(myStr)+1+strlen(buffer) );
  strcat( myStr, buffer );
}
printf("\n%s\n",myStr);

}

everything works when I enter some text then press ENTER and after I call EOF.

But when I start program enter "a" then I try to call EOF (using Ctrl Z + ⏎ (Windows cmd prompt), Ctrl D (Linux)) I have to do it three times for program to actually break the loop. I was expecting maximum of 2 times.

Can someone explain how using EOF, stdin and fgets works? Or should I use something else (for example getline)? I am sorry if I am not clear about my problem, just ask anything you need.

Thank you.


Solution

First of all, ^Z or ^D are control characters that mean something to the terminal you are using, and sometimes that means for the terminal to signal end-of-file condition.

Anyway, your three keypresses are processed by the terminal to take the following actions, after entering text:

  1. Flush the input (i.e. send the characters that have been input so far from the terminal to the program - by default this doesn't happen as the terminal uses line buffering)
  2. Set end-of-file condition
  3. Set end-of-file condition again

Inside your program that corresponds to:

  1. Nothing happens: even though a is received, fgets keeps reading until end-of-file or newline
  2. fgets completes because of end-of file. However it does not return NULL because characters were read, "a" to be specific.
  3. A bug in old versions of glibc causes fgets to try to read again, even though it previously reached end-of-file. fgets completes because of end-of-file, and returns NULL because there were no characters read.


Answered By - M.M
Answer Checked By - David Goodson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Friday, July 22, 2022

[FIXED] What is wrong with my execvp usage?

 July 22, 2022     c, exec, execvp, fgets, linux     No comments   

Issue

I'm writing a small shell to learn C. Now I want to execute custom commands but it is not working.

$ ./a.out 
OS>ls
10357: executing ls

failed to execute ls
: (2: No such file or directory)

I must not use system call to execute custom command, I should use execvp and fork. But why is it now working? The entire code is

#include<sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
int mystrcmp(char const *, char const *);

struct command
{
    char * const *argv;
};
static _Noreturn void err_syserr(char *fmt, ...)
{
    int errnum = errno;
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
    exit(EXIT_FAILURE);
}
/* Helper function that spawns processes */
static int spawn_proc(int in, int out, struct command *cmd)
{
    pid_t pid;
    if ((pid = fork()) == 0)
    {
        if (in != 0)
        {
            if (dup2(in, 0) < 0)
                err_syserr("dup2() failed on stdin for %s: ", cmd->argv[0]);
            ;
            close(in);
        }
        if (out != 1)
        {
            if (dup2(out, 1) < 0)
                err_syserr("dup2() failed on stdout for %s: ", cmd->argv[0]);
            close(out);
        }
        fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd->argv[0]);
        execvp(cmd->argv[0], cmd->argv);
        err_syserr("failed to execute %s: ", cmd->argv[0]);
    }
    else if (pid < 0)   {
        err_syserr("fork failed: ");
    }
    return pid;
}

/* Helper function that forks pipes */
static void fork_pipes(int n, struct command *cmd)
{
    int i;
    int in = 0;
    int fd[2];
    for (i = 0; i < n - 1; ++i)
    {
        pipe(fd);
        spawn_proc(in, fd[1], cmd + i);
        close(fd[1]);
        in = fd[0];
    }
    if (dup2(in, 0) < 0)    {
        err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]);
    }
    fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd[i].argv[0]);
    execvp(cmd[i].argv[0], cmd[i].argv);
    err_syserr("failed to execute %s: ", cmd[i].argv[0]);
}

#define BUFFERSIZE 200
int main() {

    char *args[80];
    char buffer[BUFFERSIZE];
    char *prompt = "OS";
    char *a = ">";

    char *tok;
    tok = strtok (buffer," ");


    while(buffer != NULL) {
        bzero(buffer, BUFFERSIZE);
        printf("%s%s",prompt,a);
        fgets(buffer, BUFFERSIZE, stdin);



        if(mystrcmp(buffer,"cd") == 0) {
            tok = strchr(buffer,' ')+1; //use something more powerful
            *strchr(tok, '\n')='\0';
            cd(tok);
        }
        else if(mystrcmp(buffer,"exit") == 0) {
            return 0;
        }
        else {
            //system("ls"); //for testing the CWD/PWD

            char *commandbuffer[] = { buffer, 0 };
            //char *less[] = { "less", 0 };
            struct command cmd[] = { {commandbuffer} };
            fork_pipes(1, cmd);
            printf("Spawned foreground process: %d\n", getpid());
        }
    }
    return 0;
}

int mystrcmp(char const *p, char const *q)
{
    int i = 0;
    for(i = 0; q[i]; i++)
    {
        if(p[i] != q[i])
            return -1;
    }
    return 0;
}

int cd(char *pth) {
    char path[BUFFERSIZE];
    strcpy(path,pth);

    char *token;

    char cwd[BUFFERSIZE];
    if(pth[0] != '/')
    {   // true for the dir in cwd
        getcwd(cwd,sizeof(cwd));
        strcat(cwd,"/");
        strcat(cwd,path);
        chdir(cwd);
    } else { //true for dir w.r.t. /
        chdir(pth);
    }
    printf("Spawned foreground process: %d\n", getpid());
    return 0;
}

Solution

After

fgets(buffer, BUFFERSIZE, stdin);

the buffer always ends with an '\n' since you end your input with a return.

Thus if you just pass ls as a command you program gets ls\n and obviously there's no such command or binary in PATH.

To fix this you can simply do the following:

fgets(buffer, BUFFERSIZE, stdin);

if (buffer[strlen(buffer)-1] == '\n')
    buffer[strlen(buffer)-1] = '\0';

....


Answered By - dekkard
Answer Checked By - Candace Johnson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home
View mobile version

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing