Returning string from C system() function [duplicate] - c

This question already has an answer here:
Getting output of a system command from stdout in C
(1 answer)
Closed 4 years ago.
I just learned C and fascinates with pointers. Recently I discovered C function system(). I am able to get return values from a program I executed via system ("program.exe"). Eg, program.c:
#include <stdio.h>
int main(){
printf("hello world\n");
return 123;
}
and this code calls program.exe, called call.c
#include <stdio.h>
#include <stdlib.h>
int main(){
int a;
printf("calling program.exe:\n");
a=system("program.exe");
printf("program.exe returned %d at exit\n",a);
return 0;
}
When I execute call.exe, I get this
calling program.exe:
hello world
pm returned 123 at exit
I was like, wow! This return value and system() function thing is like a new way to interprocess communication for me. But my question is, can I get a string return from the system() function?
Ii tried changing program.c "int main()" to "char * main()", and return 123 to return "bohemian rhapsody" and change "int a;" to "char *a;", printf format %d to %s in call.c, but I only get funny characters when I execute call.exe. I wonder what's wrong?

No you can't return a string from system(), and indeed a program under most modern desktop operating systems can only "return" an integer exit code when it terminates.
If you do want to get a string back from the executed program, one way would be to use popen() to invoke the program, and then have that program write the string to stdout.

The program that you call 'call.c' calls system(3), which does the following,
suspends the current process,
starts a child process,
and waits for the child process to complete
The return value from the called process, 'program.c/exe' is an integer (size is system dependent usually 16-bit), and what is happening behind the scenes is that the system(3) call uses the wait(2) call to (blocking) suspend execution until the child process returns.
Note that the string is not returned, but the child process prints to stdout. See the popen(3) call if you want to obtain the string (or binary) output from the child process.
See the manual page for wait(3) to see how to process the results returned by the called program, e.g. 'man -s2 wait',
WAIT(2) System Calls Manual WAIT(2)
NAME
wait, wait3, wait4, waitpid -- wait for process termination
SYNOPSIS
#include <sys/wait.h>
pid_t
wait(int *stat_loc);
pid_t
wait3(int *stat_loc, int options, struct rusage *rusage);
pid_t
wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage);
pid_t
waitpid(pid_t pid, int *stat_loc, int options);

Related

Why exit_group flushes output buffer?

From the manual page I know that:
exit() flushes output buffers while _exit,_Exit,exit_group don't.
In the code below, the content of test.log will be hello\nhello\n only if exit() was called in child process, which is the same as I tested.
But when there's no statements in child process, it will behave like it's calling exit(), the content of test.log will be hello\nhello\n too.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pid;
FILE *fp = fopen("test.log", "w");
fprintf(fp, "hello\n");
pid = fork();
if (pid == 0)
{
// do something
;
}
else
{
wait(NULL);
exit(1);
}
}
Through ltrace and strace I can see both parent and child called exit_group.
Since I called exit in parent, so it can be judged by using ltrace that exit will call exit_group.
But in the opposite I can't judge whether child process called exit.
Does gcc called exit in child process implicitly? It may be harmful to call exit in child process as many people said. If not, then why the buffer was flushed?
Testing gcc and glibc version:
gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
GNU C Library (Debian GLIBC 2.24-11+deb9u4) stable release version
2.24
Promoting PSkocik's comment to an answer:
Returning from main is always equivalent to calling exit(). Either way is supposed to represent "normal" termination of a process, where you want for all the data you buffered to actually get written out, all atexit() cleanup functions called, and so on.
Indeed, the C library's startup code is often written simply as exit(main(argc, argv));
If you want the "harsher" effect of _exit() or _Exit() then you have to call them explicitly. And a forked child process is a common instance where this is what you do want.
But when there's no statements in child process, it will behave like it's calling exit(), the content of test.log will be hello\nhello\n too.
You have a statement in child process (implicit):
When child process returns from main(), the C runtime makes a call to exit(0); (or better, something equivalent to exit(main(arc, argv, envp));, indeed) that implies the flushing of buffers you are trying to avoid.
If you want to eliminate one of the hello\ns, just fflush(fp); before calling to fork() system call, as the call will duplicate fp in both processes, each with a partially full buffer the same way, and this is the reason you get the buffer contents duplicated. Or better flush all output buffers with fflush(NULL);.

I have tries to write a c program using alarm function I am using it for first time but my ouput is not as per desired can someone help me with that

Write a C program simulating alarm clock. In the main function, you fork a child process,
and the child process sleeps for 5 seconds (the number of seconds is an command line
argument, see below for a sample run) , after which the child process sends the signal
(SIGALRM) to its parent process. The parent process, after forking the child process,
pause, upon receiving the SIGALRM signal, and prints out a message “Ding!”. The
following is a sample run
$ ./alarm 5
alarm application starting
waiting for alarm to go off
<5 second pause>
Ding!
done
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
#include <stdlib.h>
void Dingdong()
{
printf("Ding!");
exit(1);
}
int main(int argc, char *argv[])
{
if(argc!=3)
{
printf("How much seconds you want to sleep the child process\n");
}
int PauseSecond=(argv[1]);
{
if(fork()==0)
{
printf("waiting for alarm to go off\n");
printf("%d second pause",PauseSecond);
sleep(PauseSecond);
kill(getpid(),SIGALRM);
}
else {
printf("Alarm application starting\n", getpid());
signal(SIGALRM,Dingdong);
printf("done");
}
}
}
Here's what's keeping it from working at all:
int PauseSecond=(argv[1]); That puts the address of the first argument in PauseSecond, which will usually be some really big number. You probably wanted to parse the value of the first argument instead. You need to use something like atoi or strtol on it to do that.
You're calling getpid() after forking, so the child is sending the signal to itself instead of to the parent. Either call getpid() before the fork and save it to a variable, or call getppid() instead.
The parent process is finishing execution and exiting before the child process's sleep ends. You can add the pause() function to the parent process to make it wait for a signal handler to run.
If you want done to print, you can't call exit from the signal handler.
Just fixing the above will get the program sort of working, but there's other things you should consider fixing too:
Since you're not using argv[2] for anything, you should see if argc is 2 instead of 3.
If there aren't enough arguments, you should exit/return instead of continuing and trying to use one that's not there.
You should either put a \n on the end of "%d second pause" or do a manual fflush, or you won't see that until after the sleep.
printf("Alarm application starting\n", getpid()); Your format string won't actually show the result of that getpid().
If you do want to exit from the signal handler, you need to use _Exit, not exit, as the latter isn't async-signal-safe.

Why is tzset() a lot slower after forking on Mac OS X?

Calling tzset() after forking appears to be very slow. I only see the slowness if I first call tzset() in the parent process before forking. My TZ environment variable is not set. I dtruss'd my test program and it revealed the child process reads /etc/localtime for every tzset() invocation, while the parent process only reads it once. This file access seems to be the source of the slowness, but I wasn't able to determine why it's accessing it every time in the child process.
Here is my test program foo.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
void check(char *msg);
int main(int argc, char **argv) {
check("before");
pid_t c = fork();
if (c == 0) {
check("fork");
exit(0);
}
wait(NULL);
check("after");
}
void check(char *msg) {
struct timeval tv;
gettimeofday(&tv, NULL);
time_t start = tv.tv_sec;
suseconds_t mstart = tv.tv_usec;
for (int i = 0; i < 10000; i++) {
tzset();
}
gettimeofday(&tv, NULL);
double delta = (double)(tv.tv_sec - start);
delta += (double)(tv.tv_usec - mstart)/1000000.0;
printf("%s took: %fs\n", msg, delta);
}
I compiled and executed foo.c like this:
[muir#muir-work-mb scratch]$ clang -o foo foo.c
[muir#muir-work-mb scratch]$ env -i ./foo
before took: 0.002135s
fork took: 1.122254s
after took: 0.001120s
I'm running Mac OS X 10.10.1 (also reproduced on 10.9.5).
I originally noticed the slowness via ruby (Time#localtime slow in child process).
Ken Thomases's response may be correct, but I was curious about a more specific answer because I still find the slowness unexpected behavior for a single-threaded program performing such a simple/common operation after forking. After examining http://opensource.apple.com/source/Libc/Libc-997.1.1/stdtime/FreeBSD/localtime.c (not 100% sure this is the correct source), I think I have an answer.
The code uses passive notifications to determine if the time zone has changed (as opposed to stating /etc/localtime every time). It appears that the registered notification token becomes invalid in the child process after forking. Furthermore, the code treats the error from using an invalid token as a positive notification that the timezone has changed, and proceeds to read /etc/localtime every time. I guess this is the kind of undefined behavior you can get after forking? It would be nice if the library noticed the error and re-registered for the notification, though.
Here is the snippet of code from localtime.c that mixes the error value with the status value:
nstat = notify_check(p->token, &ncheck);
if (nstat || ncheck) {
I demonstrated that the registration token becomes invalid after fork using this program:
#include <notify.h>
#include <stdio.h>
#include <stdlib.h>
void bail(char *msg) {
printf("Error: %s\n", msg);
exit(1);
}
int main(int argc, char **argv) {
int token, something_changed, ret;
notify_register_check("com.apple.system.timezone", &token);
ret = notify_check(token, &something_changed);
if (ret)
bail("notify_check #1 failed");
if (!something_changed)
bail("expected change on first call");
ret = notify_check(token, &something_changed);
if (ret)
bail("notify_check #2 failed");
if (something_changed)
bail("expected no change");
pid_t c = fork();
if (c == 0) {
ret = notify_check(token, &something_changed);
if (ret) {
if (ret == NOTIFY_STATUS_INVALID_TOKEN)
printf("ret is invalid token\n");
if (!notify_is_valid_token(token))
printf("token is not valid\n");
bail("notify_check in fork failed");
}
if (something_changed)
bail("expected not changed");
exit(0);
}
wait(NULL);
}
And ran it like this:
muir-mb:projects muir$ clang -o notify_test notify_test.c
muir-mb:projects muir$ ./notify_test
ret is invalid token
token is not valid
Error: notify_check in fork failed
You're lucky you didn't experience nasal demons!
POSIX states that only async-signal-safe functions are legal to call in the child process after the fork() and before a call to an exec*() function. From the standard (emphasis added):
… the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
…
There are two reasons why POSIX programmers call fork(). One reason is
to create a new thread of control within the same program (which was
originally only possible in POSIX by creating a new process); the
other is to create a new process running a different program. In the
latter case, the call to fork() is soon followed by a call to one of
the exec functions.
The general problem with making fork() work in a multi-threaded world
is what to do with all of the threads. There are two alternatives. One
is to copy all of the threads into the new process. This causes the
programmer or implementation to deal with threads that are suspended
on system calls or that might be about to execute system calls that
should not be executed in the new process. The other alternative is to
copy only the thread that calls fork(). This creates the difficulty
that the state of process-local resources is usually held in process
memory. If a thread that is not calling fork() holds a resource, that
resource is never released in the child process because the thread
whose job it is to release the resource does not exist in the child
process.
When a programmer is writing a multi-threaded program, the first
described use of fork(), creating new threads in the same program, is
provided by the pthread_create() function. The fork() function is thus
used only to run new programs, and the effects of calling functions
that require certain resources between the call to fork() and the call
to an exec function are undefined.
There are lists of async-signal-safe functions here and here. For any other function, if it's not specifically documented that the implementations on the platforms to which you're deploying add a non-standard safety guarantee, then you must consider it unsafe and its behavior on the child side of a fork() to be undefined.

execl return - Ubuntu

My question is: after finishing the execution of the new process image, the function
execl()
would return the execution to the caller process or to the father process?
When using one of the exec family of functions, you do not expect the function to return at all. The program counter begins at the first instruction of the binary image that replaced the calling process.
From the Darwin man page:
If any of the exec() functions returns, an error will have occurred.
The return value is -1, and the global variable errno will be set to
indicate the error.
There was a comment asking about the following, but it was deleted:
If you are in a child process, and execl succeeds, then the child process is replaced by the new binary. If it fails, then control returns to that child process (the caller). There's no strict relationship between fork and exec, if that's what you're asking. If you are in a child process, and exec fails, then you have a "forked" child process, which is a copy of the original parent process. At this point you probably want to print some error message and exit from the child process.
If you want to know why it failed, you can use the following pattern:
if (execl(...)) {
perror(NULL);
exit(errno);
}
For example, try running this program, the error message will indicate how to fix the program:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (const int argc, char * const argv[]) {
if (execl("ls", "ls", "-la", NULL)) {
perror(NULL);
exit(errno);
}
return 0;
}
The solution, use execlp instead of execl in this case.

Exit Handler in C

All,
I want to develop an exit handler in my program.
I'm really new to C; is it all about managing signals in C?
How do I know if my program ended in a good way or not?
If not, how do I get the maximum information when exiting?
C (C89 and C99 standards) provides atexit() to register function to be called when the program exits. This has nothing to do with signals. Unlike signal handlers, you can register multiple exit handlers. The exit handlers are called in reverse order of how they were registered with atexit().
The convention is that when program exits cleanly it returns exit status 0. This can be done by return 0 from main() or exit(0) from anywhere in your program.
In Unix/Linux/POSIX type operating system (not sure of Windows), the parent process get exit status information about the child process using wait() system call or its variants.
Example: Here is a simple program and its output to demonstrate atexit():
#include <stdlib.h>
#include <stdio.h>
static void exit_handler1(void)
{
printf("Inside exit_handler1()!n");
}
static void exit_handler2(void)
{
printf("Inside exit_handler2()!n");
}
int main(int argc, char *argv[])
{
atexit(exit_handler1);
atexit(exit_handler2);
return 0;
}
Output generated by the program:
Inside exit_handler2()!
Inside exit_handler1()!
Look here you will find all what you want:
http://www.cplusplus.com/reference/cstdlib/exit/
I added a new link here take a look:
Exception libraries for C (not C++)
If i am not get wrong you ask about giving back results from program when exiting. You should use exit(x); function to return value from your program. You can put any integer value as parameter x. And dont forget to use #include <stdlib.h> in your program start.

Resources