Send Linux command from C program - c

I'm writing a C program to run in Linux shell.
Now I got a problem with such command.
#include <stdio.h>
void main()
{
char* command="history>>history";
system(command);
}
I want it to write the result of command "history" into a document, but it failed with a blank one.
If I change it to "date>>history", current system time will be written into the document.
Is there any problem with "history>>history"?
What should I do if I want to get that work?
Thanks!

The problem is that history is not a real command but a shell builtin. Thus you can't call it from a C program[1].
Depending on the shell the user is using, you can instead get the history from ~/.bash_history, ~/.zsh_history and so on. Note however that zsh only write to this file at the end of a session.
[1] Well, you could theorically try system("bash -c history"), but you won't get the actual history because the builtin isn't run in the context of the current session.

Related

Why is this C program doing nothing in Ubuntu?

My very simple C program just hangs and I don’t know why.
I am trying to make a simple executable to handle multiple monotonous actions for me every time I start a new programming session.
So I decided with something simple (below) yet every time I run it, the app just hangs, never returns. So I have to Ctrl-C out of it. I have added printf commands to see if it goes anywhere, but those never appear.
My build command returns no error messages:
gcc -o tail tail.c
Just curious what I am missing.
#include <stdio.h>
#include <unistd.h>
int main() {
chdir("\\var\\www");
return 0;
}
There are at least two problems with the source code:
It is unlikely that you have a sub-directory called \var\www in your current directory — Ubuntu uses / and not \ for path separators.
Even if there was a sub-directory with the right name, your program would change directory to it but that wouldn't affect the calling program.
You should check the return value from chdir() — at minimum:
if (chdir("/var/www") != 0)
{
perror("chdir");
exit(EXIT_FAILURE);
}
And, as Max pointed out, calling your program by the name of a well-known utility such as tail is likely to lead to confusion. Use a different name.
Incidentally, don't use test as a program name either. That, too, will lead to confusion as it is a shell built-in as well as an executable in either /bin or /usr/bin. There is also a program /bin/cd or /usr/bin/cd on your machine — it will check that it can change directory, but won't affect the current directory of your shell. You have to invoke it explicitly by the full pathname to get it to run at all because cd is another shell built-in.
Two things:
First, that's not what Linux paths look like
Second, check the return value from chdir()
ie
if (chdir("/var/www") != 0)
printf("failed to change directory");
Finally, the effect of chdir() lasts for the duration of the program. It will not change the current directory of your shell once this program finishes.
The other answers adequately cover the issues in your C code. However, the reason you are seeing it hang is because you chose the name tail for your program.
In Linux, tail is a command in /usr/bin in most setups, and if you just type tail at the command line, the shell searches the $PATH first, and runs this. Without any parameters, it waits for input on its stdin. You can end it by pressing control-d to mark the end of file.
You can bypass the $PATH lookup by typing ./tail instead.
$ tail
[system tail]
$ ./tail
[tail in your current directory]
It is a good idea to use ./ as a habit, but you can also avoid confusion by not naming your program the same as common commands. Another name to avoid is test which is a shell built-in for testing various aspects of files, but appears to do nothing as it reports results in its system return code.

C programming - execute another program with sudo privileges

i have a C program that opens an mp3 and extract the jpg artwork in the same folder. If i execute this program with no root privileges i get a crash. If i execute it with sudo it works normally.
Now, i need another C programs who launch the previous program when it needs a jpg artwork for the selected mp3.
I tried to call popen("./firstProgram test.mp3" , "r") function or system("/(absolute path)/firstProgram test.mp3") function by calling them even with sudo in the command or not and either with relative or absolute paths. But no version seems to work.
How can i launch the first program from the second one with success?
Thanks!
fork and then use execl
char sudo[]="/usr/bin/sudo";
char pbin[]="/usr/local/bin/puppet";
NOTICE("running puppet: %s %s",sudo,pbin);
errno=0;
execl(sudo,sudo,pbin,(char *)NULL);
/* we should never get as far as this */
obviously I recommend reading man execl for further info
Unix (Linux) systems have contained a C Programming Manual in them since possibly forever. Look in Section 2, "System Calls".
This Wikipedia Page explains the Unix Manual "sections"
It is section 2 of the manual you can read about "System Calls"
Try the command: man 2 setuid
This will give you the manual for the setuid() system call which I think is what you want.
That manual page will also list references to other related system calls that may be what you want.
Remember when compiling C programs and using system calls that do low-level hardware access, to use the -O2, or -O3 option to gcc. There is a mention of it in the manual.
Ultimately the setuid() system call makes a running process started by one user change the UID of that running process to be running as some other user. (For example, you may see the Apache running as "apache", even though it was started by root).
setuid(0) lets you be root.

run a C program at startup [Red Pitaya]

I have a C program that needs to run when I turn on my machine (Red Pitaya).
the beginning of the program presented here:
//my_test program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "redpitaya/rp.h"
int main(int argc, char **argv){
int jj=1;
while(1) {
printf("Ready for experiment number %i\n",jj);
int i, D;
int32_t TrigDly;
and so on...
the program is executable with a run.sh file called uri_test.sh, that contains the following:
cat /opt/redpitaya/fpga/fpga_0.94.bit>/dev/xdevcfg
LD_LIBRARY_PATH=/opt/redpitaya/lib ./my_test
both files are located in a directory under /root. the program is working perfectly when run manually on PuTTY terminal-
/RedPitaya/Examples/C/Uri# ./my_test
or
/RedPitaya/Examples/C/Uri# ./uri_test.sh
I tried to follow the solution presented here :
https://askubuntu.com/questions/9853/how-can-i-make-rc-local-run-on-startup
without success.
any suggestions? Thank you.
There are several ways to have a program running at startup, and it depends upon your init subsystem (are you using systemd or a SysV-style init?).
BTW, a source program in C is not a script and you generally compile it (using gcc -Wall -Wextra -g) into some executable. In your case, you probably want to set up its rpath at build time (in particular to avoid the LD_LIBRARY_PATH madness), perhaps by passing something like -Wl,-rpath,/opt/redpitaya/lib to your linking gcc command.
Perhaps a crontab(5) entry with #reboot could be enough.
Whatever way you are starting your program at startup time, it generally is the case that its stdin, stdout, stderr streams are redirected (e.g. to /dev/null, see null(4)) or not available. So it is likely that your printf output go nowhere. You might redirect stdout in your script, and I would recommend using syslog(3) in your C program, and logger(1) in your shell script (then look also into some *.log file under /var/log/). BTW, its environment is not the same as in some interactive shell (see environ(7)...), so your program is probably failing very early (perhaps at dynamic linking time, see ld-linux.so(8), since LD_LIBRARY_PATH might not be set to what you want it to be...).
You should consider handing program arguments in your C program (perhaps with getopt_long(3)) and might perhaps have some option (e.g. --daemonize) which would call daemon(3).
You certainly should read Advanced Linux Programming or something similar.
I recommend to first be able to successfully build then run some "hello-world" like program at startup which uses syslog(3). Later on, you could improve that program to make it work with your Red Pitaya thing.

Simple C Wrapper Around OpenSSH (with Cygwin on Windows)

I am packaging a program on Windows that expects to be able to externally call OpenSSH. So, I need to package ssh.exe with it and I need to force ssh.exe to always be called with a custom command line parameter (specifically -F to specify a config file it should use). There is no way to force the calling program to do this, and there are no simple ways to do this otherwise in Windows (that I can think of anyway - symlinks or cmd scripts won't work) so I was just going to write a simple wrapper in C to do it.
This is the code I put together:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int ret;
char **newv = malloc((argc + 2) * sizeof(*newv));
memmove(newv, argv, sizeof(*newv) * argc);
newv[argc] = "-F ssh.conf";
newv[argc+1] = 0;
ret = execv("ssh.orig.exe", newv);
printf("execv failed with return value of %i", ret);
return ret;
}
I then compile this code using GCC 4.6.3 in Cygwin and it runs without error; however, there is a strange behavior with regards to input and output. When you go to type at the console (confirming the authenticity of the host and entering in a password, etc) only part of the input appears on the console. For example, if I type in the word 'yes' and press enter, only the 'e' will appear on the console and SSH will display an error about needing to type 'yes' or 'no'. Doing this from the Windows command prompt will result in your input going back to the command propmt, so when you type 'yes' and press enter, you get the ''yes' is not recognized as an internal or external command...' message as if the input were being typed at the command prompt. Eventually SSH will time out after that.
So, I'm obviously missing something here, and I'm assuming it has something to do with the way execv works (at least the POSIX Cygwin version of it).
Is there something I'm missing here or are there any alternatives? I was wondering if maybe I need to fork it and redirect the I/O to the fork (although fork() doesn't seem to work - but there are other issues there on Windows). I tried using _execv from process.h but I was having issues getting the code right for that (also could have been related to trying to use gcc).
It's also possible that there may be a non-programming way to do this that I haven't thought of, but all of the possibilities I've tried don't seem to work.
Thoughts?
I ended up finding a solution to this problem. I'm sure there were other ways to do this, but this seems to fix the issue and works well. I've replaced the execv line with the following code:
ret = spawnv(P_WAIT, "ssh.orig.exe", newv);
You have to use 'P_WAIT' otherwise the parent process completes and exits and you still have the same problem as before. This causes the parent process to wait, but still transfers input and output to the child process.

system calls in C

I have a function in C that calls another software to execute and generate a file then its manipulates the data e.g.
void main()
{
function();
//manipulate data in output.txt
}
void execute()
{
system("./test input.txt output.txt");
}
for some reason the output.txt file is not being generated by full...how does the system call work? will execute return to main before system call ends? if yes how can I solve this? Im working on ubuntu using gcc
Check the result of system() ALWAYS. Ensure that it executed successfully(ie. returns 0 or whatever is a successful result for 'test')
When system executes it runs through /bin/sh (on unix/linux anyway). However since you're specifying it with './test' make sure that you're operating in the working directory that you THINK you are. Complex systems(and poorly designed ones) change directories like underwear.

Resources