5

I'm trying to make a program that a bash script runs. I want the bash script to be able to change the state of the c++ program, and the only thing I could find was to use environment variables. Thing is, its seems getenv only gets the value at the time when the program was run.

Bash

export BLINK=1
./blink &
sleep 5s
unset BLINK

C++

int main(int args, char **argv) {

    char *blink = getenv("BLINK");

    while(blink && blink[0] == '1')
    {
        std::cout << getenv("BLINK") << std::endl;
        usleep(500000);
    }

    return 1;
}

So what this does is run the blink program, wait 5 seconds then unset the environment. The C++ program however always sees the enviorment value as 1 and never stops. How do I get an updated environment variable while the program is running? Or is there a better way to have a bash script control the state of a c++ program.

EDIT I should note, I do not want to just kill the process either because it has to turn off hardware when it ends.

Joe Jankowiak
  • 1,059
  • 12
  • 37
  • 4
    That's not how the environment works. A spawned process gets a copy of its parent's environment when it starts and then the two are not connected anymore. If you want to talk to your application then you need a communications channel. Signals, pipes, sockets, standard input, control files that the program polls for, etc. – Etan Reisner Jun 10 '15 at 17:29
  • For reference: since the current question is "how do I do this impossible thing, or any other thing", I'm voting to close. A complete survey of UNIX IPC mechanisms is way too big. Do read up on the stuff Etan mentioned though, figure out what you need, and come back when you have a new question. – Useless Jun 10 '15 at 17:45

2 Answers2

3

It is not possible to modify program environment after it is started. You have to use another method of interprocess communication. The simplest one is to register handler for some signal to your app (e.g. SIGUSR1), and then send it using kill -SIGUSR1 <pid> command.

There are also other solutions available, e.g. create named pipe (using pipe shell command), and check periodically if someone wrote something to it. If yes, exit loop.

You can also use sockets if you want, but this could be more complicated.

Daniel Frużyński
  • 2,091
  • 19
  • 28
1

The C++ programs environment is not changing when you change it in bash - since when you start your program it gets a copy of the parent's environment and has no access to the parent process's environment.

You can use a file to easily share data, however.

Bash

echo "1" > blink.txt
./blink &
sleep 5s
echo "0" > blink.txt

C++

#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <unistd.h>
using namespace std;

string getfile(const string& filename) {
    ifstream in(filename.c_str(), ios_base::binary);
    in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit);
    return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
}

int main(int argc, char* argv[]) {
    string blink = getfile("blink.txt");
    while(blink[0] == '1')
    {
        std::cout << getfile("blink.txt") << std::endl;
        usleep(500000);
    }

    return 1;
}
Scott 'scm6079'
  • 1,517
  • 13
  • 25