I have a program which hacks around in the user's shell configuration file (by placing a . (execute) command for an auto-generated alias file) and I'm having trouble figuring out how to run commands in the parent shell, i.e. without forking into a new shell.
I only need to run a command to execute the alias file so that the "program" can be used without logging in and out. Surely there must be another way to interact with the shell beside forking.
N.B.: When I say "forking" I mean both using system() and execl() - as I said, I want to send the command to the shell hosting the program, not a new instance of it.
After some thinking about your use case, I suppose what you want to do, that is, to signal your parent shell to reload the configuration, is impossible, but what you can do here is to reverse the control.
What I mean is, don't think how to make your parent shell do something, but let it do it for you. If you have a program that fixes shell configuration, make a shell wrapper for it:
/path/to/program
. ~/.bashrc # or any other way to reload the shell config
and call your program using . wrapper.sh to make sure it will be executed in the context of the current shell. In this way the program will make changes to the configuration but will not bother with interacting with its parent, and the calling shell will just reload itself after the program finishes.
Related
I'm working on a C program that invokes some other programs from the same directory. The idea is to call fork, and make the child processes execute the desired programs, each one on a new terminal window, I'm using WSL from windows and I can't seem to make it work.
On a regular Linux machine, I've seen something similar to the following working, which is just calling a terminal emulator which creates a new window:
execlp("/usr/bin/x-terminal-emulator", "/usr/bin/x-terminal-emulator", "-e",
"./programname.exe", NULL);
But in WSL isn't possible to just execute a command on a new window like that, instead, executing this command directly in a WSL terminal does spawn a new window and allows to execute a given program on it:
cmd.exe /c start cmd.exe /c wsl.exe ls
Using ls in the line above is just illustrative. Trying to use execlp to run cmd.exe and passing the rest of the command as arguments doesn't work, it just runs cmd in the same terminal used to run the program. Is there any way to achieve this?, preferably using C. I'm aware that just using a bash script to execute those programs on separated windows using the command from above would work, I'm just wondering if there's any solution for a use case like this one.
I'm sure my question has probably been answered previously but I didn't find anything specific to my situation after searching for a while.
Background:
I have written a suite of data acquisition tools in C that run on an embedded system running Debian Wheezy. There is a main module, called Dispatch, whose job is to launch the rest of the modules and pass messages between them. I put a trivial bash script in /etc/init.d that executes Dispatch when the system boots since this system runs unattended. This system runs without any local user interaction so Dispatch should really be written to function as a daemon but it is not. The startup script simply executes /opt/bcdispatch &.
There's a bug in one of the other modules that causes it to crash every few days. I'm trying to hunt down that bug but in the meantime I am trying to write a watchdog program that will detect the crash, kill off all of my processes, then relaunch Dispatch. For reasons I won't go into it is not sufficient to just relaunch the crashed process, the whole suite of tools needs to be restarted.
What I'm trying to do:
I wrote a simple watchdog program that periodically executes popen("ps aux | grep bc") (all of my process names start with "bc" which makes it easy to find them with grep), finds that one of the modules has crashed by looking for anything with a "zombie" status in any of the lines read from popen(), kills all of my processes by calling system("kill <PID>"), then executes the startup script in /etc/init.d and exits. I modified the startup script so that it launches the watchdog after launching Dispatch. The startup script now looks like:
/opt/bcdispatch &
/opt/mywatchdog &
Everything is being run as root. There are no other user accounts on the system.
Problem
The watchdog process works fine if I run it from the command line. It kills off all of the processes it's supposed to, launches the startup script, then exits. However, when the watchdog is launched by the startup script at boot time it doesn't do its thing. It's running, one of the processes it's monitoring has crashed, but it doesn't kill the rest of them off. It just sits there like a giant turd. I can start another instance of it from the command line and that one works just fine.
Question
So my question (finally!) is: why can't my program kill other processes when launched via a startup script? I suspect it has something to do with the fact that the watchdog process no longer has a terminal associated with it? I tried substituting the call to system("kill <PID>") with kill(PID) but that didn't change anything.
EDIT
It just occurred to me that it's not the kill()ing part that doesn't work (well, that might be broken as well), the call to popen("ps aux | grep bc") must not be working since the watchdog should exit after it finds the zombie process but it isn't. Its PID is still the same as it was when the system booted. I guess this means the title of this question isn't very good.
Found the problem. The output of my watchdog's call to popen("ps aux | grep bc") was being truncated to 80 columns, presumably because it was no longer attached to a terminal and that's the default terminal width. That truncation was causing problems for the way the program was parsing the results of the ps command so it never found the crashed process. Changing the command to popen("ps -w aux | grep bc") was all that was needed to fix it.
How to make an application to prevent itself from launching from the command line?
I have a binary which should be launched by a daemon; but when somebody tries to launch the binary from command line, I should error out stating "cannot be launched from command line".
Tried googling but in vain.
PS. http://www.daniweb.com/software-development/c/threads/449682/stop-launching-from-command-line
I wanted to check if there are better ways than those mentioned in the link..
I am not sure there is a bullet proof answer (to how to prevent a program to be started from command line). You could consider
testing with isatty(3) that STDIN_FILENO (i.e. 0) is not a tty
try to open /dev/tty (it should fail) see tty(4)
testing with getsid(2) that your are not in the same session than your parent, or starting a new session with setsid(2)
calling yourself daemon(3)
And I am not sure that you always want to reject being started from a terminal. For debugging, you surely want to be able to be started from a terminal. I actually would just warn, not quit, if started from a terminal.
And you probably want to install your program outside of standard paths, maybe in some libexec/ or sbin/ directory.
See also capabilities(7), pty(7), termios(3)
For the record, testing with isatty(3) only works if you are writing that binary files yourself. The method would fail if you are trying to prevent people from starting a third-party binary files.
Generally speaking, to prevent people from starting the specific program(s) from command line, the *nix way is to chown the binary file(s) to be owned by the daemon that launches it, and also to be of owned by the group say no_command_line. Then chmod 705 binary_executables, and put all those people not allowed to run the binary_executables from command line in the group no_command_line.
HTH
I was hesitant to post this question because I assumed someone somewhere had asked it already but after much scouring, I've come up empty, so here it is.
BACKGROUND: I'm running a local agent (written in C, listening via TCP) which allows for execution of a small number of scripts/commands remotely. (Via a web interface, to be specific.) The scripts themselves are a mixture of binaries, bash, or perl scripts and the agent itself doesn't really care, as long as they are allowed in the list.
(This is on a corporate, internal network and this is in the very early stages, so please don't debate the merits of security at this time.)
The C agent code to launch processes is this:
sprintf(mrun, "%s %s 2>&1", file, args);
mexec = popen(mrun, "r");
[read some returned buffer]
pclose(mexec);
This approach works well for both external bash and perl scripts, provided the scripts just execute commands (or do things in the foreground). However, I recently had a need to expand a script to include a restart of a daemon, in this case, named.
The script itself (bash) is simple:
#!/bin/bash
pkill -9 named
/local/mnt/named/sbin/named -c /local/mnt/named/var/named.conf &
echo "restarted"
The problem I am running into is that the script never finishes (i.e. restarted is never echo'd) when run via the C agent, so the control is never returned and the TCP socket never gets free'd up. As far as the agent is concerned, the process is still running. If I run the script from a terminal, it works fine and control is returned back to me.
Am I missing something that would allow the script to execute normally when being forked off from a C daemon versus just being called from the bash terminal?
I know of nohup and I guess could use that if all else fails but I was curious if there is some other kind of workaround for doing this.
Based on feedback from the comments above, I was able to get the script to continue working after launching the daemon process, thanks to some additional redirects:
/local/mnt/named/sbin/named -c /local/mnt/named/var/named.conf </dev/null &> /dev/null &
So, thanks to fork0 for that bit of knowledge.
Afterward, I noticed that the TCP socket connection wouldn't close properly, even though the script was done working. After some more info below and doing a lot of research, it turns out that child processes will inherit (and keep open) file descriptors from the parent process (which includes sockets).
I looked all over for methods to disown the child process but didn't really find any that would work for me (or didn't constitute an entire rewrite of the agent).
Finally, I stumbled upon this question, which is related but not in a programming language I use:
os.execute without inheriting parent's fds
This basically involved the child process closing any open file descriptors inside the code, thus freeing them to be closed by the parent. (I think?)
I added a few lines to the bash script to do this prior to starting named and it does work.
for i in `nawk 'BEGIN{ for(i=1;i<=255;i++) print i}'`
do
eval exec `echo $i | sed -e 's/.*/&<\&-/'`
done
(I would up using nawk instead of seq because I need it to run on Solaris and Linux.)
Some basic testing shows that this has solved the major issue of the socket not being able to close but I'll need to do some more research on whether this will have any other ramifications that I am not aware of. There may also be a better, safer way to achieve this but at least I'm on the right track.
I've coded a program in c for an embedded system (Devkit8000, which is a clone of the well known BeagleBoard) running Angstrom Linux.
The program creates a couple of threads, on of them is responsible of taking pictures with a camera connected to the board, and right now the second thread only moves that images to another path. The program should be running during the whole day, and the only way to stop it is sending a signal.
I edited the crontab to launch the program in a specific hour and to send a signal when it has to stop, the issue is that launching the program in this way cause the process to be killed after some time running, but, if i launch the program manually (through the command line), it works perfectly and dont get stopped.
I have no idea about the reason of this different behaviour between crontab and command line. I've checked the system logs but didnt find anything useful. I've also been reading a little and find that the OS can kill a process if it is using so much resources, but doesnt make sense that this happens in only 1 scenario (crontab vs manually)...
Any clue about what is happening?
Thank you in advance!
The main difference is that running a job through cron invokes a non-interactive non-login shell. The effect of that depends on the default shell for your user. For example, if you are using Korn shell or Bash then your .profile will not be executed, as it would on an interactive login shell. Korn shell 88 will execute .kshrc (the $ENV file) but ksh93 will not.
So, a good start might be to call your program from a script, after first "sourcing" your .profile file:
. $HOME/.profile
Failing that... When you say that the process is "killed", do you get such a message? If so, then that sounds like someone sending SIGKILL, i.e. kill -9. If not, then maybe you could run strace or ltrace to find out at what point it dies.