How to tell if a call to system() has exited? - c

In C I wrote a code using system() to start another application , say abc.exe .Now how do I find if abc.exe has exited and when it has done so , I want to run another application, say xyz.exe .

system() is synchronous i.e. when it is done you simply get to the next instruction of your code, so basically it should be :
system("abc");
system("xyz");
also system returns the exit status of executed program, so if there is a dependency between programs and xyz can't be executed without successful execution of abc, you should check ret status of abc
if(system("abc") != -1 )
system("xyz");

Call the application after the first system(). System() is synchronous.
system("abc");
system("xyz");
Like anthropomorphic notice,
synchronous means that a call to system("abc") will only return after
"abc" is done.
You are able to verify the execution with the return value. Generally a non zero value is returned, if the program was not execute currently.
In many systems, 0 is used to indicate that the command was
successfully executed and other values to indicate some sort of error.
If command is a null pointer, the function returns a non-zero value in
case a command processor is available and a zero value if it is not.
If command is not a null pointer, the value returned depends on the
system and library implementations, but it is generally expected to be
the status code returned by the called command, if supported.

You can check whether system executed correctly by looking what it has returned to you. If it executed successfully, the return value will be zero (null pointer).
From C++ Reference:
If command is a null pointer, the function returns a non-zero value in case a command processor is available and a zero value if it is not.
If command is not a null pointer, the value returned depends on the system and library implementations, but it is generally expected to be the status code returned by the called command, if supported.

Related

what exactly return 0 does internally in a c program?

I came to know that while writing a c program we write "return 0" to tell the os that the program is executed successfully. My question is how can we tell the os while writing the program itself without even executing the program that the program had executed successfully. Can someone tell me what exactly "return 0" does.
The return value of the main function is passed to the exit() function by the C startup code, providing the OS an exit status available to its parent process.
The OS itself does not do anything with this exit status, but shell scripts and other programs invoking multiple processes may use the exit status to determine what to do next. For example the make utility uses the exit status of the commands, eg: when invoking the C compiler, to proceed with the next command or stop the build process with an error status.
Returning 0 or EXIT_SUCCESS at the end of the main function is a convention to tell the calling process that the program completed successfully. It has become implicit in C99 so legacy programs that do not have a return statement can be considered to have completed successfully when recompiled with a C99 compiler. Nevertheless, it is considered good style to provide the exit status explicitly.
return 0 means returning the integer value 0 from a function, which is generally done inside a program.
You are referring to exit(0), which means that you stop a program successfully. Generally, when you do exit(i) with i an integer value, then that i value is the error code, explaining what happened wrongly. More information can be found here.
Once you finish writing your code and compiling it you could execute it wherever you want correct?
Once it is finished executing that piece of software you made will return a number (in your example zero).
In most cases that do absolutely nothing because there is nobody actively looking for that return code.
But you might find yourself in situations where you want to execute that software in an automated environment or something like that. let's say a script, that calls your software, and if everything goes ok, it goes on to do something else, but if it is not ok it tries again. That script or other software that is calling your first software has the power to read and interpret that return.
You can also do that manually to actually see that a certain software return code is:
Windows:
open cmd
run the software
run echo Return Code: %errorlevel%
Linux:
open terminal
run software
run echo Return Code: $?
Those pre-defined variables will give you the value your last command returned and you can do something about it.
By convention (as mentioned before) 0 means that everything was ok, and anything other than that indicates that there has been an error. If you write your code with multiple error checks, and when something goes wrong return different values. you will know straight away what went wrong with your execution.

Return value of system() function

#include<stdio.h>
#include<stdlib.h>
main()
{
printf("Hello World..\n");
system("ls");
}
Here...ON SUCCESSFUL execution system function returns the statys of "ls" command..and ON FAILURE it returns -1..
so can anyone help me to get this FAILURE condition for system function that gives return value as "-1"
The system function returns -1 if system itself fails, not if the command it invokes fails. For example, system returns -1 if the fork call fails. This can happen if your system is very short on resources, such as memory, or if your system imposes a limit on the number of processes you can run.
If the command fails (for example if you call system("false")), the value returned by system isn't simply the return value of the command; it's the value returned by the wait system call; man 2 wait for more information. (This assumes a Unix-like system; the behavior of system() on other operating systems differs.)
Of course if you want to see the value returned by a call to system, you'll need to store that value in a variable:
int result = system("ls");
You should read the documentation for the system function.
If you're trying to cause system to fail and return -1, one way to do it is to use it to invoke your program recursively. This can consume a lot of memory, and may interfere with your system. Do this only if you're the only person using the system, and you don't mind possibly interfering with its operation.
(Incidentally, the definition for main should be int main(void), not just main(), though that's not directly relevant. Prior 1999, omitting the return type would default to int; that's no longer permitted, but many compiler still support the old form. Empty parentheses do not specify the number of parameters; (void) explicitly says that there are no parameters, and is the preferred form.)

How do I explain 'main()'?

I'm creating a presentation on how to program in C, and since I'm fairly new to C, I want to check whether my assumptions are correct, and what am I missing.
Every C program has to have an entry point for the OS to know where to begin execution. This is defined by the main() function. This function always has a return value, whether it be user defined or an implicit return 0;.
Since this function is returning something, we must define the type of the thing it returns.
This is where my understand starts to get hazy...
Why does the entry point needs to have a return value?
Why does it have to be an int?
What does the OS do with the address of int main() after the program executes?
What happens in that address when say a segfault or some other error halts the program without reaching a return statement?
Every program terminates with an exit code. This exit code is determined by the return of main().
Programs typically return 0 for success or 1 for failure, but you can choose to use exit codes for other purposes.
1 and 2 are because the language says so.
For 3: Most operating systems have some sort of process management, and a process exits by invoking a suitable operating system service to do so, which takes a status value as an argument. For example, both DOS and Linux have "exit" system calls which accept one numeric argument.
For 4: Following from the above, operating systems typically also allow processes to die in response to receiving a signal which is not ignored or handled. In a decent OS you should be able to distinguish whether a process has exited normally (and retrieve its exit status) or been killed because of a signal (and retrieve the signal number). For instance, in Linux the wait system call provides this service.
Exit statuses and signals provide a simple mechanism for processes to communicate with one another in a generic way without the need for a custom communications infrastructure. It would be significantly more tedious and cumbersome to use an OS which didn't have such facilities or something equivalent.

What's the purpose of exit(0) ?

I understand that exit(1) indicated an error , for example :
if (something went wrong)
exit(EXIT_FAILURE);
But what's the purpose of using exit(EXIT_SUCCESS); ?
When handling with processes maybe ? e.g. for fork() ?
thanks
This gives the part of the system that invokes the program (usually the command shell) a way to check if the program terminated normally or not.
Edit - start -
By the way, it is possible to query the exit code of an interactive command as well through the use of the $? shell variable. For instance this failed ls command yields an exit code of value 2.
$ ls -3
ls: invalid option -- '3'
Try `ls --help' for more information.
$ echo $?
2
Edit - end -
Imagine a batch file (or shell script) that invokes a series of programs and depending on the outcome of each run may choose some action or the other. This action may consist of a simple message to the user, or the invocation of some other program or set of programs.
This is a way for a program to return a status of its run.
Also, note that zero denotes no problem, any non-zero value indicates a problem.
Programs will often use different non-zero values to pass more information back (other than just non-normal termination). So the non-zero exit value then serves as a more specific error code that can identify a particular problem. This of course depends on the meanings of the code being available (usually/hopefully in the documentation)
For instance, the ls man page has this bit of information at the bottom:
Exit status is 0 if OK, 1 if minor problems, 2 if serious trouble.
For Unix/Linux man pages, look for the section titled EXIT STATUS to get this information.
you can only exit your program from the main function by calling return. To exit the program from anywhere else, you can call exit(EXIT_SUCCESS). For example, when the user clicks an exit button.
It's a system call. There's always good information on system calls if you check the man pages:
http://linux.die.net/man/3/exit
On a Linux box, you can simply type man exit into a terminal and this information will come up.
There are two ways of 'normally' exiting a program: returning from main(), or calling exit(). Normally exit() is used, and thought of, for signalling a failure. However, if you are not in main(), you must still exit somehow. exit(0) is usually used to terminate the process when not in main().
main() is actually not a special function to the operating system, only to the runtime environment. The 'function' that actually gets loaded is normally defined as _start() (this is handled by the linker, and beyond the scope of this answer), written in assembly, which simply prepares the environment and calls main(). Upon return from main(), it also calls exit() with the return value from main().

C program calling shell script

I have a small C program calling a shell script myScript.sh. I am getting the value of ret as 256. Please help me in knowing what went wrong with the system call?
int main()
{
int ret;
ret = system (myScript.sh);
ret >>= ret;
if (ret != 0)
{
printf("ret is [%d]",ret);
}
}
Working on 64 bit UNIX operating system and using ksh shell
On my system, man system says:
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.
The waitpid man page describes a set of macros such as WEXITSTATUS() that extract the actual exit code from the return value.
I'm not quite sure what you're intending to do with ret >>= ret, but that can't be right.
The way that the system function usually works on *nix is that it calls fork and then the child calls one of the exec functions with /bin/sh -c and then the string you passed to system in the child, which turns the child process into an instance of the /bin/sh program which runs the command. The parent calls one of the wait functions, which waits for the /bin/sh to exit, which it does with the same exit status as the shell script, and then system also returns that value.
If you look at the man pages for the wait system call(s):
main 3 wait
You should get some information about what gets returns and some macro functions that help you make sense of it.
The WIFEXITED(stat_val) macro can be used to test if the program exited normally as opposed to with a signal. Normal exits involve calling the exit system call. If this function returns a non-zero value then you can use the WEXITSTATUS(stat_val) macro to get the value that it actually returned.
The WIFSIGNALED(stat_val) macro can be used to test if the program was terminated with a signal, and if so the WTERMSIG(stat_val) macro will return the signal number that caused the termination.
There are some other macros that can tell you if the process were stopped or continued, rather than terminated, but I don't think that they are overly helpful to you for this purpose, but you may want to look into them.
As far as what is actually happening in this case, it can be difficult to tell. If the fork call fails then system will be able to return -1 and set errno to reflect the error. If the fork did not fail then the error may have happened in the child and be more difficult to locate. It may be possible that on your platform system might do some tests before forking to insure that you have permission to execute the appropriate files and set errno to reflect that, but maybe not.
You should look into the perror function to print out error messages in the case that errno is set.
If the failure happens after fork and within the child then you either need to get the shell to tell you more about what is happening, or get the shell script to. This may be by including echo statements in the script similarly to using print statements in your C programs.
You should also look into the access function to test if you have permission to read and/or execute files.
If you are using Linux then you should be able to do:
strace -o my_program.strace -f ./my_program
or
ltrace -o my_program.ltrace -f -S ./my_program
and then examine the trace files (after the -o) to look at what the programs and kernel say to each other. ltrace looks at how the program talks to library function, while strace looks at system calls, but the -S tells ltrace to also look at system calls. The -f argument tells them both to trace children of the program as they are created.
I just noticed that you said that you were using ksh
As I mentioned system under a Posix system should use /bin/sh or a compatible shell. This doesn't mean that /bin/sh won't run /bin/ksh to run your script (or that the kernel won't use the #! line at the beginning of the script file to do this), but it could be a problem. There are ways to run shell scripts so that this line is not used to know which shell is to be used. The most notable is:
. myshell.sh
The period and space essentially tries to dump the text of the file into the current shell session rather than run it in another process (this is useful for setting up an environment). If you were to be doing:
int x = system(". myshell.sh");
Then that could be a problem.
The exit status of the command is encoded as two bytes:
The high-order byte contains the exit status.
The low-order byte contains the signal that killed it (if any).
Since 0x0100 is 256 decimal, your shell script exited with status 1. Review your shell script and ensure it exits with status 0 when it is successful.
From the Standard (emphasis is mine):
6.5.7/3
If the value of the right operand [of the >> operator] is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
So, when you do
ret >>= ret;
and ret < 0 or ret >= CHAR_BIT * sizeof (int) ... anything goes
The return value of the system function can be -1 on error.
If your call returned in such a negative value, the next operation ret >>= ret; (same as ret = -1 >> -1;) results in something that has no meaning: you cannot right shift by a negative number of bits.
When you try to do things with no meaning, C is allowed to do anything ... anything at all (that includes doing nothing, doing what you expect, reformatting your hard disk, transferring your bank account to mine, making demons fly out your nose, ..., ..., ...)
Make sure your script is executable and in the path, or use the full path instead.
Nothing went wrong. Did you read the documentation? See:
RETURN VALUE
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).
Since 256 is not -1, the call did not fail.
Why do you shift the result? Just remove the line ret >>= ret, and it will work.
I am working on linux and it helped to call the script with system("sh script.sh")

Resources