1

I have a relatively simple problem which I cannot seem to do. What I need to do is retrieve an integer from a bash script using the system function in a C++ program. My understanding is that system by default returns an integer, so I should be bale to do something like

int returnedVal = system ("myscript");

however the main problem is bash scripts do not have return values, just a flag between 0 and 255 for whether they were successful or not. I have tried doing something like writing to a text file in the script and then reading in a file, however this caused some issues and I would like to avoid that if possible. Does anyone know the easiest way to do this? Thanks very much in advance.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
user2551700
  • 89
  • 1
  • 6
  • Shell scripts can return values with `exit` e.g. `exit 1`. – rustyx Sep 26 '17 at 17:18
  • my understanding is that they can only return an integer between 0 and 255 – user2551700 Sep 26 '17 at 17:34
  • 4
    Your understanding is correct. If you need to pass larger integers, modify your question (and title). One solution could be a pipe; many shell scripts write text (like, textual representation of numbers) to stdout which is then captured by calling scripts. For example `lines = $(wc -l $file)`. – Peter - Reinstate Monica Sep 26 '17 at 17:35
  • 3
    Return the value using some other form of IPC than exit codes. For example; use pipes (stdout and stdin can easily be used that way for example). Ohh, and *don't* use `system` it is fraught with bad surprises and security issues (use one of the `exec*` functions instead). – Jesper Juhl Sep 26 '17 at 17:47
  • What is `myscript` doing? In some cases you might not need any script – Basile Starynkevitch Sep 26 '17 at 18:31

3 Answers3

3

POSIX exit(3) says:

The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option Start] or any other value, though only the least significant 8 bits (that is, status & 0377) shall be available to a waiting parent process.

This means that no value greater than what is possible to represent with 8 bits can exit from a normal process termination via call to exit then parent can't catch more.

More on this. Don't use returned value to transmit some data, it is primarily intended to represent a success or failure status. 0 value represent successful, any other a failure.

If you want your processes to communicate something, then you need some communication channel (file, pipe, etc).

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
1

If myscript -like many scripts or programs- write(2)-s something (e.g. some numbers or strings) on its stdout, you might use (on POSIX) popen(3) in your program. When successful popen would give a FILE* stream for <stdio.h> routines (that you could read with fscanf etc).

(I am guessing that you are using some Linux or POSIX system)

But system(3) catches the exit(3) status (actually also other terminations, e.g. signal(7)-s, see waitpid(2)) of myscript. It don't care about the output of myscript which gets inserted in the standard output of your program.

Don't forget to use pclose(3) (not fclose) to close that popen-ed stream. Read also pipe(7).

For example, this code reads the number from the output of the wc -l /etc/fstab command

FILE*p = popen("wc -l /etc/fstab", "r");
if (!p) { perror("popen"); exit(EXIT_FAILURE); };
int n= 0;
if (fscanf(p,"%d", &n)<=0) { perror("fscanf"); exit(EXIT_FAILURE; };
if (pclose(p)>0) /*wc failed*/ exit(EXIT_FAILURE);
printf("your fstab has %d lines\n", n);

You should read Advanced Linux Programming (freely downloadable). You may want to use other things (e.g. some system calls like fork(2), execve(2), waitpid(2), pipe(2), dup2(2); see syscalls(2)).

There are many other ways of doing some Inter-Process Communication, including fifo(7)-s and socket(7)-s.

Beware of code injection when running, with popen or system, some computed string containing a command.

Some libraries (notably Qt or POCO for C++) offer other ways of running programs and communicating with them.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

The system man page says, after discussing all kinds of failures:

If all system calls succeed, then the return value is the termination status of the child shell used to execute command. (The termination status of a shell is the termination status of the last command it executes.)

For clarity one could add that the shell's exit value is either the numerical argument to the exit command, or — if none is encountered — the exit status of the last command which was executed, i.e. the value of $?. That exit value is passed by the operating system to the shell's parent (which may be another shell) via the waitpid() function. That way the exit status of the "leaf" process is propagated until it reaches system, and finally your program.

I do not see why what you want to do should not be possible.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • Add a link to this question and you have a +1: https://stackoverflow.com/questions/17336915/return-value-in-bash-script – Fantastic Mr Fox Sep 26 '17 at 17:29
  • Just make sure that `myscript` is actually setting the appropriate exit code. – 0x5453 Sep 26 '17 at 17:29
  • Sorry I'm not sure if I understand. Are you saying it is not possible? – user2551700 Sep 26 '17 at 17:34
  • Two negations give a positive: I do think it is possible, indeed. Why do you not post a complete test case? A minimal script, a minimal C program containing a `printf` of the `system` call, and a description of your environment. Then we can talk business beyond "I do not see" or "should". – Peter - Reinstate Monica Sep 27 '17 at 11:26