0

I'm making a program that reads a text file with different numbers each line and put that numbers in a string. (could be in a array of integer but I need to use the function execvp so I guess i need do as a string). Then it uses a second program to calculate the square of that numbers.

The problem is: I can't pass the arguments to the functions execvp and function execvp is not working. (I guess is something with the fopen)

Edit: I tried with popen instead of execvp and didn't work as well

Here it goes part of my code:

#define LSIZ 128

#define RSIZ 10

char line[RSIZ][LSIZ];
FILE *fptr = NULL;
int i = 0;
int tot = 0;

fptr = fopen("casosproduto.txt", "r");
while(fgets(line[i], LSIZ, fptr)) 
{
    line[i][strlen(line[i]) - 1] = '\0';
    i++;
}
fclose(fptr);

char* argument_list3[]={"produto",&line[i],NULL};
tot = i;    
for(i = 0; i < tot; ++i)
{
    execvp("./produto",argument_list3);
    printf(" %s\n", line[i]);
}
hmls
  • 1
  • 1
  • What does "can't pass the arguments" mean? What error or incorrect behaviour ar you observing? But for starters what do you expect `&line[i]` to refer to considering `i` is past the last index that `fgets` wrote to? It's really not clear what your intended behaviour/result is. – kaylum Apr 05 '22 at 07:42
  • `execvp` does not return if it succeeds. So putting it in a `for` loop makes no sense. Again, it is not clear what your intended behaviour is. You still have not clearly explained what the input is and exactly what you intend to pass the the child process. – kaylum Apr 05 '22 at 07:45
  • I edited the code. What is expected is that the program use an auxiliar program that calculate the square of the numbers in the text file "casosproduto.txt". The input is the name of the auxiliar program and the txt file filled with different numbers each line – hmls Apr 05 '22 at 07:45
  • Yes but what exactly are the command line arguments that the `produto` program takes? That is, please give an exact example text file and the exact command line required. That is show the exact form required for: `./produto ?? ?? ??` – kaylum Apr 05 '22 at 07:49
  • thanks for your help. The produto program just takes a number and calculate his square. example: ./produto 5 . Appearing in the next line 25. the text file is a file with differents numbers per line. like 25 | 24| 3 | 2 etc. – hmls Apr 05 '22 at 07:51
  • So you want to call it multiple times with each number in the file? And does it have to be with `exec`? As I said, exec replaces the current process so you cannot call it like that multiple times. If you must use exec you need to `fork` first. Can you do it with `popen` instead as that will be much simpler? – kaylum Apr 05 '22 at 07:52
  • Yes, multiple times. I guess i can use with popen. will check how to do it. thanks – hmls Apr 05 '22 at 07:59
  • `line[i][strlen(line[i]) - 1] = '\0'` will write outside the buffer if `line[i]` contains a zero-length string `""`, and it will remove the last character if `line[i]` does not end with a newline. See [**Removing trailing newline character from fgets() input**](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – Andrew Henle Apr 05 '22 at 22:40

2 Answers2

0

execvp will load produto to the original process space, and then execute it, which is equivalent to executing the for loop only once, you can first fork a subprocess and call execvp in the subprocess, Like this

for (i = 0; i < tot; ++i) {
    char *argument_list3[] = {"produto", line[i], NULL};
    if (fork() == 0) {
        execvp("./produto", argument_list3);
    }
}

You can also call function system to execute, and you can read a line and execute it once, so it is not limited by the number of lines in the file, e.g:

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

#define LSIZ 128
int main()
{
    char line[LSIZ];
    char cmd[LSIZ + 16];
    FILE *fptr = NULL;

    fptr = fopen("casosproduto.txt", "r");
    if (fptr == NULL)
        return -1;

    while (fgets(line, LSIZ, fptr)) {
        line[strlen(line) - 1] = '\0';
        snprintf(cmd, sizeof(cmd), "./produto %s", line);
        system(cmd);
    }

    fclose(fptr);
    return 0;
}
dulngix
  • 424
  • 1
  • 5
  • Thanks for your explanation. It was very helpfull. Unfortunately I can't use system functions for this exercice. For some reason the product function is not working this way. The product function expect an integer and the numbers are being passed like strings. Any sugestion to solve this? – hmls Apr 05 '22 at 09:24
  • @hmls: if `produto` is a program, all its arguments are strings — all arguments to all programs are strings. If `produto` is a function, then it cannot be executed with `execvp()` — you can only execute programs, not functions. – Jonathan Leffler Apr 05 '22 at 14:17
  • My mistake. It is a program. But for some reason is not working . Do you guys think that is everything ok with the argument list? With the pointers(?) – hmls Apr 05 '22 at 15:06
0

Udpdate. I did some changes in my code but still dont work.

Here it goes the code updated:

#define LSIZ 128 
#define RSIZ 10 

 char line[RSIZ][LSIZ];
 FILE *fptr = NULL; 
 int i = 0;
 int tot = 0;


 fptr = fopen("casosproduto.txt", "rt");
 while(fgets(line[i], LSIZ, fptr)) 
 {
    line[i][strlen(line[i]) - 1] = '\0';  
     i++;
 }
 fclose(fptr);


tot = i;
pid = fork();

for(i = 0; i < tot; i++)
{
char* argument_list3[]={"produto",line[i],NULL};
if (fork() == 0) {
    execvp("./produto", argument_list3);

}
}
 }
return 0;
}

There are two reasons for the execvp not working... first- Something related with the fclose function. If i put the fclose function inside the loop (I know that doesn't make sense but just for tests) then it executes the execvp. Outside the loop it doesnt.

Second- Are my arguments to the execvp alright? (when I tested puting the fclose inside the loop i had to change to this "char* argument_list3[]={"produto","4",NULL};" to test with a number, otherwise the result would be always 1.

hmls
  • 1
  • 1