-1

Hi i need to take only 5 bytes from stdin, i've tried this but i have problem while executing it since it keeps asking me for input and at the end the string contained in buffer is wrong. Also i'd like to know how to synchronize N processes while the parent is sleeping.

buffers[] is an array of buffers.

#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define fflush(stdin) while (getchar() != '\n')

char **filenames;
int *files;
char **buffers;
int n_proc;

int main(int argc, char **argv) {
    long i;
    pid_t pid;
    int status;

    if(argc < 2) {
        puts("Usage error: prog file1 ... fileN.\n");
        exit(1);
    }

    filenames = argv + 1;

    n_proc = argc - 1;

    puts("Bef malloc buff.\n");

    if((buffers = malloc(sizeof(char *) * n_proc)) == NULL) {
        puts("Buffers' malloc error.\n");
        exit(1);
    }

    if((files = malloc(sizeof(int) * n_proc)) == NULL) {
        puts("Files' malloc error.\n");
        exit(1);
    }

    puts("After malloc buff.\n");

    for(i = 0; i < n_proc; i++) {
        if((files[i] = open(filenames[i], O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
            printf("Error while opening file %ld.\n", i);
            exit(1);
        }
    }

    puts("After file open.\n");

    for(i = 0; i < n_proc; i++) {
        if((buffers[i] = (char *) mmap(NULL, 1028, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0)) == NULL) {
            printf("Error in mapping buffer %ld.\n", i);
            exit(1);
        }
    }

    puts("After mapping.\n");

    i = 0;

    while(i < n_proc) {

        printf("Fork %ld started.\n", i);

        pid = fork();

        if(pid < 0) {
            printf("Error while forking %ld.\n", i);
            exit(1);
        } else if(pid == 0) {

            puts("Please insert an input of max 5 characters.\n");

            printf("Son %ld.\n", i);

            fflush(stdout);

            fgets(buffers[i], 6, stdin);

            buffers[i][strcspn(buffers[i], "\n")] = 0;

            //int j;

            //for(j = 0; j < 5; j++)
                  //buffers[i][j] = getchar();

            //printf("Buff has %s inside.\n", buff);

            //fflush(stdout);

            fflush(stdin);

            //strcpy(buffers[i], buff);

            printf("Buffer %d has string %s inside.\n", i, buffers[i]);

            fflush(stdout);

            write(files[i], buffers[i], 6);
        } else {
            printf("Parent %ld.\n", i);
            wait(&status);
        }

        i++;
    }


}

This is only a prototype of the code, since there's still synchronization needed and signal handling

Code requires when to write on command line N files and creating N processes that each take 5 bytes from stdin and put in their own file.

As an example if i try with

./a.out hello.txt hello1.txt

Bef malloc buff.

After malloc buff.

After file open.

After mapping.

Fork 0 started.
Parent 0.
Please insert an input of max 5 characters.

Son 0.
Hello
Hello
Buffer 0 has string Hello inside.
Hello
Fork 1 started.
Parent 1.
Please insert an input of max 5 characters.

Son 1.
Hello
Hello
Buffer 1 has string Hello inside.
Hello
Fork 1 started.
Parent 1.
Please insert an input of max 5 characters.

Son 1.

As you can see it doesn't take the input and keeps asking for it, same problem with the getchar().

amixakir
  • 1
  • 1
  • Please provide a [mre]. Also include the exact input, expected result and actual result. Without seeing complete code it is difficult to say for sure but at a guess your `buffers` data are not NUL terminated so are not valid strings but you then print them as strings. – kaylum Sep 17 '22 at 21:49
  • yeah sorry i changed it – amixakir Sep 17 '22 at 22:04
  • fflush(stdout) is non-standard (i.e. it works on linux, it may not do anything useful elsewhere). – Allan Wind Sep 17 '22 at 22:08
  • oh ok , i just wanted to try if something changed – amixakir Sep 17 '22 at 22:09
  • You still have not given us the exact input, expected result and actual result. And it's extra confusing that the new code you have shown does not even contain the lines of code in your original post. – kaylum Sep 17 '22 at 22:11
  • i was actually trying different things since it wasn't working, i'll fix it with the input and result – amixakir Sep 17 '22 at 22:12
  • 2
    `#define fflush(stdin)` Don't do that. That causes this code `fflush(stdout);` to be replaced by the `getchar` loop which consumes the input line before `fgets` gets a chance to read it. – kaylum Sep 17 '22 at 22:28

1 Answers1

-1

Note that in case stdin is associated with a terminal, there may also be input buffering in the terminal driver, entirely unrelated to stdio buffering. (Indeed, normally terminal input is line buffered in the kernel.) This kernel input handling can be modified using calls like tcsetattr(3); (stdin(3) man page)

If you give it the input "12345\n":

#include <stdio.h>

int main(void) {
    char buffers[1][5];
    unsigned i = 0;
    for(unsigned j = 0; j < 5; j++)
        buffers[i][j] = getchar();
    printf("%.5s", buffers[i]);
    // read the newline.  You may need to discard others.
    int ch = getchar();
    if(ch == '\n')
        printf("\n");
    return 0;
}

it will print:

12345
Allan Wind
  • 23,068
  • 5
  • 28
  • 38
  • i see, i tried this but when i input like hello it keeps me asking for other inputs even if i fflush stdin eliminating everything else that might be on it but still i have this error – amixakir Sep 17 '22 at 22:10
  • Did you run my program with `echo hello | ./a.out` (note that echo adds the '\n'). Tweaked it a bit to handle non-'\n', for example, EOF if you call it with `echo -n hello | ./a.out` – Allan Wind Sep 17 '22 at 22:11
  • Yours also works without any additional stuff, but my code doesn't – amixakir Sep 17 '22 at 22:20
  • I wrote this up before you posted more than a few lines code. If it's remains a negative score I will delete it. Hope it helped in either case. – Allan Wind Sep 17 '22 at 22:31
  • Re "*stdin, by default, is line buffered.*", That's completely wrong. For starters, buffering is something fount on output handles. Correct: By default, *stdout* is line buffered if connected to a terminal and block buffered if not. – ikegami Sep 17 '22 at 23:28
  • I updated answer to clarify the difference between kernel and stdio buffering with a quote from the man page. "complete wrong", I don't know, you get stdin buffering when talking to the terminal, and to me it's an implementation detail as to who does the buffering. Let me know if I am still missing something. Thanks. – Allan Wind Sep 18 '22 at 01:38