1

I need to make a server that: 1) compiles a c++ file and saves the errors in a file if they exist; 2) if there are no errors i must run the a.out file and extract the output in another file. The problem resides in the first one.

In order to compile and extract errors i used more methods: 1) system("g++ file.cpp &> err.txt") - not working: it prints the errors in the console but the file remains empty 2) popen - Reference link: C: Run a System Command and Get Output? : the only difference is that i opened another file and instead of printing in the console i used fprintf to write in file. I forgot to add that the first method works if written as command in console but inside the server is problematic.

// This code is to show what i have already tried and if you find any
// syntax errors like ; or ' pls ignore them as i couldn't copy the code
// from the docker console. Thank you very much!
//1
system("g++ file.cpp &> err.txt");
if( access( "a.out", F_OK ) != -1 ) {
    system("./a.out > output.txt");

//2
    FILE *f;
char buff[200];

f = popen("g++ file.cpp", "r");
if (f == NULL) {
    printf("Failed to run command\n" );
    exit(1);
}
FILE *o;
o = fopen("err.txt", "w");
while (fgets(buff, sizeof(buff)-1, f) != NULL) {
    fprintf(o, "%s", buff);
}
fclose(o);
fclose(f);

I expected the errors to be written in the err.txt not to be printed in console and in all the above examples it prints in the console and err.txt remains empty.

Teodor O.
  • 23
  • 7
  • 2
    Depending on where the source for the file comes from, you have possibly introduced a really big security hole into your server. Running foreign code without any kind of filtering or containment could let a hacker into your system. – Some programmer dude Jan 23 '19 at 17:43
  • On a totally unrelated note, the size passed to the [`fgets`](https://en.cppreference.com/w/c/io/fgets) function is *including* the terminator. So no need for that `-1`. – Some programmer dude Jan 23 '19 at 17:44
  • Looks like g++'s output is written to stdout. This is why `popen()` catches it (stdout is the default) whereas you redirect stderr to your textfile when using `system()` – flowit Jan 23 '19 at 17:48
  • @flowit i removed the '&' (system("g++ file.cpp > err.txt");) caracter so that i redirect the stdout insead of stderr and still same problem. It still prints in the console instead of redirecting it. – Teodor O. Jan 23 '19 at 17:50
  • @Someprogrammerdude Thank you for the worries but i've got that covered. :)) The problem is this file compile at the moment -_- – Teodor O. Jan 23 '19 at 17:56

2 Answers2

1

You can accomplish it the old-school way:

  1. fork() and in the child:

  2. Open a file for storing standard output and another one for errors.

  3. Use dup2(oldfd, newfd) to duplicate the two files' descriptors to stdout, and stderr respectively.

  4. Invoke execlp with gcc and its arguments.

  5. In the parent process you can add waitpid call to wait for the child to finish.

ciamej
  • 6,918
  • 2
  • 29
  • 39
  • Does it work for c++ sources too? I mean the difference is gcc to g++ so it should. Also i am already in a thread with this code. – Teodor O. Jan 23 '19 at 18:01
  • @TeodorO. I doesn't matter whether you use c++ or c. These are system calls. Using both threads and processes in the same program is usually a bad idea and difficult to get right, however in this simple scenario where the child pretty much only invokes `dup2` and `execlp` you'll be fine. – ciamej Jan 23 '19 at 18:10
  • You could also move file opening before the `fork()` call. – ciamej Jan 23 '19 at 18:10
  • If you're afraid of using both threads and forks in one program, then you can write a simple c program whose only task is to compile the specified file using gcc and store the results in an appriopriate file (by invoking exec, like I've shown in the answer) and then call `system` to invoke that small program from your main multi-threaded one. – ciamej Jan 23 '19 at 18:15
  • Thank you very much! I will try your solution tomorrow and reply with the conclusion. – Teodor O. Jan 23 '19 at 18:36
0

Ok so in the end apparently this one was pretty close: system("g++ file.cpp &> err.txt"); The solution is: system("g++ file.cpp > err.txt 2>&1");

Teodor O.
  • 23
  • 7