System call return value in C - c

I am using system function in C code to invoke cp command.
I want to know whether it got executed successfully or not?

Use system() function. It returns the status of command executed. If this is 0, then it would seem this is successfull.

Should be enought to check the return value of system call.
From man system on Mac:
The system() function returns the exit
status of the shell as returned by
waitpid(2), or -1 if an error occurred
when invoking fork(2) or waitpid(2). A return value of 127
means the execution of the shell
failed.

Related

Exec function in c is not returning -1 when it should

I am using an execv function to run a program called code.x.
code.x has a part where it guarantees its failure by Assertion.
My code that runs execl is:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
int main()
{
pid_t pid;
char *args[] = { "./code.x",NULL };
pid = fork();
if (pid > 0) {
wait(NULL);
printf("%s\n", strerror(errno));
printf("done\n");
}
else if (pid == 0) {
printf("%s\n", strerror(errno));
execv(args[0], args);
printf("should fail");
}
else {
printf("forkfail");
}
return 1;
}
the code prints
Success
code.x: code.c:15: main: Assertion '0 == 1' failed.
Success
done
"should fail" is never printed and WEXITSTATUS(status) shows that the exit status is 0.
The exec family of functions replace the calling process with a new program in its initial state loaded from an executable file. They can only fail if this replacement fails, e.g. due to the requested file not existing or the invoking user not having permissions to access/execute it.
If an assertion failure in the program ./code.x you're invoking happens, this is long past the point where execv could have failed; at this point, the original program state where execv was performed no longer exists, because it was already replaced. The parent process will see it exit via a wait-family function, and can inspect the status reported by the wait-family function to determine why it exited.
exec* functions succeed if the program starts running. Your program did start running.
An assertion failure causes the program to abort, exit with a signal. The Linux manual page wait(2) explains that:
WEXITSTATUS(wstatus)
returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as
the argument for a return statement in main(). This macro should be employed only if WIFEXITED returned true.
If you didn't check that WIFEXITED(status) is true, then WEXITSTATUS(status) is garbage.
Instead, check WIFSIGNALED(status) and if true, get the signal - WTERMSIG(status), which should equal to SIGABRT.
execv successfully did its job. The process ./code.x executed, then exited because of an assertiong.
The exec family of functions don't care about the process's return value. Once the process starts, the calling process is effectively terminated and gone.
Exec will only return if for some reason the process couldn't be started at all. Specifically, only these errors (taken from the man page) will cause exec to return and set errno to one of these values:
E2BIG The total number of bytes in the environment (envp) and argument list (argv) is too large.
EACCES Search permission is denied on a component of the path prefix of filename or the name of a script interpreter. (See also path_resolution(7).)
EACCES The file or a script interpreter is not a regular file.
EACCES Execute permission is denied for the file or a script or ELF interpreter.
EACCES The filesystem is mounted noexec.
EAGAIN (since Linux 3.1)
Having changed its real UID using one of the set*uid() calls, the caller was—and is now still—above its RLIMIT_NPROC resource limit (see
setrlimit(2)). For a more detailed explanation of this error, see NOTES.
EFAULT filename or one of the pointers in the vectors argv or envp points outside your accessible address space.
EINVAL An ELF executable had more than one PT_INTERP segment (i.e., tried to name more than one interpreter).
EIO An I/O error occurred.
EISDIR An ELF interpreter was a directory.
ELIBBAD An ELF interpreter was not in a recognized format.
ELOOP Too many symbolic links were encountered in resolving filename or the name of a script or ELF interpreter.
ELOOP The maximum recursion limit was reached during recursive script interpretation (see "Interpreter scripts", above). Before Linux 3.8, the
error produced for this case was ENOEXEC.
EMFILE The per-process limit on the number of open file descriptors has been reached.
ENAMETOOLONG filename is too long.
ENFILE The system-wide limit on the total number of open files has been reached.
ENOENT The file filename or a script or ELF interpreter does not exist, or a shared library needed for the file or interpreter cannot be found.
ENOEXEC An executable is not in a recognized format, is for the wrong architecture, or has some other format error that means it cannot be executed.
ENOMEM Insufficient kernel memory was available.
ENOTDIR A component of the path prefix of filename or a script or ELF interpreter is not a directory.
EPERM The filesystem is mounted nosuid, the user is not the superuser, and the file has the set-user-ID or set-group-ID bit set.
EPERM The process is being traced, the user is not the superuser and the file has the set-user-ID or set-group-ID bit set.
EPERM A "capability-dumb" applications would not obtain the full set of permitted capabilities granted by the executable file. See capabilities(7).
ETXTBSY The specified executable was open for writing by one or more processes.
The Exec function family replaces the existing process image with a new process image. This is why it is required to fork before spawning another process, because the currently running process is completely replaced, this includes the program counter, which keeps track of the next instruction to execute.
printf("should fail");
is never excecuted because the instant you called execv(args[0], args), the program counter was moved to execute args[0], thus leaving behind the execution path that would have resulted in that print statement.
Exec returns -1 on the condition that it encountered an error while replacing the image, and has absolutely no relation to the return value of the program being executed. This is because the two processes, after Exec is called, are not coordinating with each other at all. Remember: the fork() command created a new address space, which means that these processes are now running in separate domains on separate executables.
Some documentation may be of help:
http://man7.org/linux/man-pages/man3/exec.3.html
Hope this helped.

system() keeps returning 127

I am developing a shared-library L which is used by an other system service S. In my program I need to call a small program P, which uses Oracle shared libraries.
The small program P is packaged and installed correctly, and the environment variables, such as PATH,LD_LIBRARY_PATH and ORACLE_HOME are set correctly. I can run P on command line without any problem.
But when service S call my library L which runs the small program P via system(), it gives me a return code 127. I've googled, people says it's a command not found error, probably a PATH issue, so I've tried with absolute path like the following
int status = system("/usr/bin/myprog --args");
if (status < 0) { ... }
ret = WEXITSTATUS(status);
ret still equals 127.
Any idea please ? Thank you.
Update
It turns out that the service S is launched via command daemon, in its init.d script, I have found the following line:
daemon /usr/bin/myserv
if I export explicitly all my environment variables (PATH, ORACLE_HOME and LD_LIBRARY_PATH), it works. I don't know if daemon eliminates my environment variables.
this excerpt from the man page for system()
-----------------------------------------------------------------
The value returned is -1 on error (e.g., fork(2) failed), and the
return status of the command otherwise.
This latter return status is
in the format specified in wait(2).
Thus, the exit code of the command
will be WEXITSTATUS(status).
In case /bin/sh could not be executed,
the exit status will be that of a command that does exit(127)."
-----------------------------------------------------------------
indicates the 127 means that /bin/sh could not be executed.
Well, I have found the answer:How to make unix service see environment variables?,the environment variables are removed in init.d script.

I want a function in C on linux to collect core dump without terminating the process

abort() do collect the core dump, but I don't want the process to terminate. dump_core() collects the core dump, but in kernel space. Is there any function equivalent to dump_core() in user space?
A simple way to do it yourself is to fork the process (which creates a complete copy of the parent process) and call abort from the child process.
The child process will be aborted with a core-dump, while the parent process continues as if nothing happened.
Use gcore.
.
.
.
char command[ 1024 ];
sprintf( command, "gcore -o /core/file/name %d", getpid() );
system( command );
.
.
.
Error and bounds checking are omitted.
There is no such Linux C command. However, you may find some third party tools that can do this for you. For example, Google coredumper, which is also supposed to be able to capture all the threads. Another way would be to attach gdb to your running process, and issue the gcore command. This is essentially what the gcore command line utility does.
Kernel generates SIGSEGV signal to the process whenever coredumps, I think you should attach a handler to the SIGSEGV signal(Link) and call fork from that handler function.

How to force to exit if init_module() failed?

I am working on a simple kernel module and I am taking arguments from command line. What I want to do is to check those arguments before loading the module.
I checked the argument and returned 1 to indicate the failure of init_module function so that the kernel module won't be loaded if arguments are not valid.
The problem was that the module was still loaded even if it didn't pass the argument check (took the first if statement). I typed sudo -f rmmod kernel_name, it complained the module is busy. How do I make it to load the module if it passes the argument check?
int init_module(){
//check argument here
if(failed){
//arguments are not valid. Return 1 to indicate the failure of init_module
return 1;
}
else{
register hook function here
return 0;
}
}
void cleanup_module(){
unregister hook here
}
I assume you are working on a Linux kernel module.
A positive return value still can be interpreted as success. A common practice is to return -error_code on error, -EINVAL in your case.

cygwin c sem_init

if((sem_init(sem, 1, 1)) == 1) perror("error initiating sem");
If I include this line of code my program simply starts and exits. I just started learning how to use semaphores. I'm using cygwin and when this line is commented out the printf's ABOVE this print to console but when include this, nothing happens.
I did the following to get cygserver going-
CYGWIN=server
ran /bin/cygserver-config
ran /usr/sbin/cygserver
for the config it said the cygserver is already running
And for the sygserver it saids-
initailaizing complete
failed to created named pipe: is the daemon already running?
fatal error on IPC transport: closing down
Any ideas?
I figured out what was wrong. I was using data(struct) = shmat() before I was assigning any memory to data. That for some reason was stopping my 'printf' from working.

Resources