3

I have bash script where I ask the user for some inputs, and then I want to call a C program a few times, and sum the return value. Please note that the main function inside my C program has some printf statements also, and it returns an integer value. Here is the part of my bash script:

 #!/bin/bash

encBER=0

// Some other code where I read the values from the user

for i in $frames;
do
    tempEncBER=$(./enc_ber $bytes $snr $modulation $channel $alamouti)
    encBER=$((encBER + tempEncBER))
done

echo "Total BER is:" $encBER

The point is that I ask it to execute 10 times, meaning the frames variables has the value of 10, but it executes once, it shows some syntax error, and then executes again, and for the final result, the value of encBER is 0. It simply doesn't store anything there. How can I get the value of the return statement in my main function in my C program and use it in bash?

  • 2
    The fact that `enc_ber` is a C program is not relevant at all. – Quentin Jan 14 '15 at 10:44
  • 5
    When you say "return value" about the C program, do you mean what is returned using `return` at the end of `main()`? Because what you're doing is storing *the standard output* emitted by the program, which is something completely different. – unwind Jan 14 '15 at 10:45
  • 1
    Where do you set value of `$frames` with which value? – Cyrus Jan 14 '15 at 10:47
  • 1
    If `frame` has the value `10` then `for i in $frames` will loop exactly once with `$i` having the value `10`. – Etan Reisner Jan 14 '15 at 10:48
  • @unwind Yes, that's exactly what I mean. `return` at the end of `main()` –  Jan 14 '15 at 10:49
  • 1
    Be ware, that although `main()` returns `int` the OS only returns the lowest byte vlaue of the `int` returned by `main()`. So `return 257;` from `int main()` whould end up in the shell with `1`. – alk Jan 14 '15 at 10:51
  • possible duplicate of [How to set a BASH variable equal to the output from a command?](http://stackoverflow.com/questions/4651437/how-to-set-a-bash-variable-equal-to-the-output-from-a-command) – tripleee Jan 14 '15 at 12:02

4 Answers4

6

The return value of a program is store in the $? variable. So you only need to add each $?:

for i in $frames;
do
    ./enc_ber $bytes $snr $modulation $channel $alamouti
    encBER=$((encBER + $?))
done

Note that the value is restricted to eight bits, so the maximum value is 255.


If you want to capture an integer greater than 255 or a float for instance, use stderr for all the things you don't want (fprintf(stderr, "Things I don't want\n");) and stdout to print the return value you want to catch.

fredtantini
  • 15,966
  • 8
  • 49
  • 55
  • This works. But is there any way to work around the 255 restriction? –  Jan 14 '15 at 10:51
  • 3
    The only way I see is use what you have done, but print to stderr what you don't want and to stdout what you want to capture. – fredtantini Jan 14 '15 at 10:53
5

The output from a program is different from its return code. The return code should generally be 0, indicating success, or non zero, indicating failure. If you want the return code then you can simply run the program and check the variable $? afterwards:

./enc_ber $bytes $snr $modulation $channel $alamouti
retVal=$?
# retVal now contains the value passed back from the exit of your program.

Be careful not to do anything in between running your program and checking the result otherwise the value of $? will change again.

On the other hand, if you want your program to write a value to stdout and that's the output you need to obtain then you'll have to redirect the output to a file and then read the content of file:

./enc_ber $bytes $snr $modulation $channel $alamouti >./my_file.txt
output=$( cat my_file.txt )
# output now contains whatever enc_ber wrote to stdio

Naturally, you program will have to write only those things you wish to capture. Log lines and other extra formatting will cause you problems. The above is a simple example - it's up to you to parse whatever your program outputs, but the above should work for a simple number output.

Component 10
  • 10,247
  • 7
  • 47
  • 64
  • i was about to upvote this but the temporary file is completely superfluous. Just `output=$(./enc_ber ...)` is the way to go, once you have fixed `enc_ber` to print, rather than `return()`, the result. – tripleee Jan 14 '15 at 12:01
  • @tripleee: Yes, that's a fair point. If the output was complex and needed filtering / parsing, I'd normally write to a temporary file - deleted later - and process separately, but for a simple case, it makes perfect sense to combine the two lines. Thanks. – Component 10 Jan 14 '15 at 16:15
1

You don't need to store it's return value, it's stored in the special variable ? so just

./cprogram
echo $?

that will output the exit code of cprogram, you could of course assign it to a variable now, if you need to call another program and retain this value.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
0

If you have an out file,

gcc abc.c -o abc

Then you can do this,

output=`./abc <agr1> <agr2> <arg3>`

echo $output
Arnab Nandy
  • 6,472
  • 5
  • 44
  • 50
  • what do you mean by `object file`? a _binary_ one? – Sourav Ghosh Jan 14 '15 at 10:46
  • If it take command line arguments then you should send it through same, but i don't think more than one line output can be stored like this. – Arnab Nandy Jan 14 '15 at 10:46
  • object file is the compiled code file which can be run like the way i shown – Arnab Nandy Jan 14 '15 at 10:47
  • Can you please show some reference where it is mentioned like you said above? I'm really interested. Also, please use `@` to notify about the updates in comment. :-) – Sourav Ghosh Jan 14 '15 at 10:48
  • Thanks for the link. The _very first line_ of that reads like _An object file is a file containing object code, meaning relocatable format machine code that is ___usually not directly executable___ _ Please correct me. – Sourav Ghosh Jan 14 '15 at 10:53
  • @SouravGhosh here is more [information](http://stackoverflow.com/questions/7718299/whats-an-object-file-in-c) – Arnab Nandy Jan 14 '15 at 10:55
  • Please. stop sharing links until you _read and understand_ them. None of the two links supports your version. if `abc` is object file, `./abc` is not possible. `abc` should be an executable. If you think otherwise, enlight me please. – Sourav Ghosh Jan 14 '15 at 10:58
  • @SouravGhosh if this is not directly executable how can I running it?? http://prntscr.com/5sb9s2 – Arnab Nandy Jan 14 '15 at 11:14
  • Aghh. Who told you `-o` creates _object_ files? Heard anything called `-c` option of `gcc`? Please, do read them [type `man gcc`]. And, you're welcome. :-) – Sourav Ghosh Jan 14 '15 at 11:18
  • Ok thanks for all the information @SouravGhosh i will edit it to appropriate info – Arnab Nandy Jan 14 '15 at 11:24