So I am trying to call a program from within a c file I am making but the only way I've been able to do that is by using the system() function which causes error on its own. To run the program in terminal I use;
~/odas/bin/odaslive -vc ~/odas/config/odaslive/matrix_creator.cfg
This is what I am currently trying to use to run that same program, it compiles and will run in terminal but nothing happens.
pid_t pid=fork();
if (pid==0){
//static char *argv[] ={"echo","-vc ~/odas/config/odaslive/matrix_creator.cfg", NULL};
execl("~/odas/bin", "~/odas/bin/odaslive", "-vc", "~/odas/config/odaslive/matrix_creator.cfg", (char *)NULL);
exit(127);
} else {
waitpid(pid,0,0);
}
execl requires file path in the first argument.
It doesn't expand ~ with the home for path. The full path must be supplied.
Check a returned value and errno. It will inform you about a failure reason if any.
int ret = execl("/home/username/odas/bin/odaslive", "/home/username/odas/bin/odaslive", "-vc", "/home/username/odas/config/odaslive/matrix_creator.cfg", (char *)NULL);
Related
The following code works in stand alone (non-debugging) mode. However gdb debugging stops when I tried to step over popen(), meaning a breakpoint at the fgets() can never be reached.
#include <stdio.h>
int main()
{
char buff[10];
FILE *f = popen("echo blah", "r");
// program and debugger exit before this line
// so that fgets() and printf() were never called
fgets(buff, 5, f);
printf("%s\n", buff);
}
GDB reports Program terminated with signal SIGTRAP, Trace/breakpoint trap. I dug into glibc's popen() and this is where it quits,
// internal-signal.h
/* Block all signals, including internal glibc ones. */
static inline void
__libc_signal_block_all (sigset_t *set)
{
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigall_set, set,
__NSIG_BYTES);
}
Does anyone knows what is going on here? thanks!
Turned out to be a kernel issue, at least when I reverted back from 5.15.x to 5.14.x, the issue went away. I thought kernel update were never meant to break userspace.
I'm unable to get command line argument with int main(int argc, char* argv[]), No errors occurs but when further manipulation want to happen i see that argv[ ] and other related variables dont have any value and says Error reading characters of string then an Acces violation reading location error happens.
This is the sample code of my issue, I had to downsize it to make it readable:
#include "CommonHeaders.h"
void Start(char *input)
{
lstrcpyA(host, input);
// In this point i see in my Debugger "Locals/Autos" that nothing
// is passed to function then a "Access violation ... " happens.
// ...
}
int main(int argc, char *argv[])
{
Start(argv[1]);
return 0;
}
I always use this int main(int argc, char* argv[]) and pass command arg with ProjectProperties->Debugging->Command Argument and works perfect everytime. Is it possible that proper headers aren't included or any changes in project configuration could make a conflict?
Be sure to set the subsystem to console Linker -> SubSytem -> Console (/SUBSYSTEM:CONSOLE) and dont set an Entry point set the Whole Program Optimization to No Whole Program Optimization and turn SDL check to off.
I want to replace the calls to system() function made by my program using LD_PRELOAD.
So I created the following wrapper functions in a shared library for testing.
// syshook.c
int system(const char * command)
{
printf("system() called for %s ************************************\n", command);
return 55;
}
char * getenv (const char* name)
{
printf("my getenv() *********************");
return 0;
}
And compiled and linked to a shared object libsyshook.so with gcc.
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libsyshook.so -o libsyshook.so.1.0
ln -s libsyshook.so libsyshook.so.1.0
However, when I run the program with with LD_PRELOAD as shown below, my wrapper function for system() is not called, but the wrapper for getenv() called.
LD_PRELOAD="libsyshook.so" myprog
When I attach the debugger, I can see that system() call, calls the implementation in libpthread.so. So why is redirecting system() not working. I don't think there is any limitation on that ??
Edit:
My test program compiled to myprog above looks like this. Comments indicate my observations.
void TestClass::testMethod()
{
string cmdLine = "date";
if (!mainWin) cmdLine = "time";
int retFromSys = system(cmdLine.c_str()); // goes into libpthread when stepped in.
cout << "return from system " << retFromSys << endl; // prints 0, not 55
getenv("DEBUG_SYS"); // Wrapper function called for this. Prints "my getenv ****** ..."
The most usual case of bad linking with LD_PRELOAD is when GCC replace your function by another one, when he think it can make your code faster to execute.
For instance, if GCC read this line in your code :
printf("%d", strlen("toto"));
It will replace with this line before compiling it :
puts("4");
Because it knows the printf and strlen functions, and think the output would be the same with puts function.
In this example, if you made your own printf or strlen function in a library loaded with LD_PRELOAD, your function won't be called after compilation, because GCC would have replaced function calls.
I think your problem is for the same reason. system is a very heavy function, and GCC may replaced your function call by another. For instance, if you tried :
system("ls");
GCC might replaced your line by :
execlp("ls", "ls");
That would do the same, but in less heavy. It couldn't know that you wanted to use your own system function. Try to disassemble your code to check if this is the problem.
As solution, I suggest you to try to call system with a more "random" parameter, to make GCC think it should not try to replace it. Maybe something like :
int main(int argc, char** argv)
{
char* line = NULL;
// Useless condition to make GCC think the parameter is variable
if (argc == 1)
line = "ls";
return (system(line));
}
I am just porting a code to Mac OS X which is using _tspawnl on Windows.
Is there anything equivalent to _tspawnl on Mac OS X or Linux?
Or is there any posix equivalent to _tspawnl
You can use fork and execv system call together in the following way :
if (!fork()){ // create the new process
execl(path, *arg, ...); // execute the new program
}
The fork system call creates a new process, while the execv system call starts the execution of the application specify in path.
For example, you can use the following function spawn whose argument are the name of the application to be executed and the list of its arguments.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int spawn (char* program, char** arg_list)
{
pid_t child_pid;
/* Duplicate this process. */
child_pid = fork ();
if (child_pid != 0)
/* This is the parent process. */
return child_pid;
else {
/* Now execute PROGRAM, searching for it in the path. */
execvp (program, arg_list);
/* The execvp function returns only if an error occurs. */
fprintf (stderr, “an error occurred in execvp\n”);
abort ();
}
}
int main ()
{
/* The argument list to pass to the “ls” command. */
char* arg_list[] = {
“ls”, /* argv[0], the name of the program. */
“-l”,
“/”,
NULL /* The argument list must end with a NULL. */
};
spawn (“ls”, arg_list);
printf (“done with main program\n”);
return 0;
}
This example has been taken from the chapter 3.2.2 of this book. (Really good reference for development in Linux).
You can use fork()/exec(), as already pointed out, however a closer system call is posix_spawn() (manpage).
It can be a bit of a pain to set-up, however, but there is some example code using it is here (note that this code also provides functionality for Windows using the CreateProcess() API, which is probably what you should be using under Windows anyway).
I have a piece of C++ code that calls the system command.. I want to pass the file name of my own C++ executable to the system command.. anyone know how to do this?
So for example my C++ code is called "switch-5".. what I want to do is something like;
system("./script.sh switch-5");
Anyone have any clue?
Your executable name is the first argument passed in argv.
To test this just run:
int main(int argc, char **argv)
{
printf("My program name: '%s'\n", argv[0]);
return 0;
}
(I am assuming you know how to combine it with your script name to get the string to pass to system().)
argv[0] as passed to main is the name of your executable.
Store it in a global variable during app startup:
static char *selfname;
int main(int argc, char **argv)
{
selfname = argv[0];
// etc.
}
Beware, argv[0] contains exactly what was used to start the program, including relative or absolute path, for example: "./programname".