#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define LOG(format, ...) \
fprintf(stderr, format, __VA_ARGS__); \
if (ferror (stderr)) \
perror("\nError while printing to stderr\n")
#define LOG_FUNC(function_name) LOG ("\nF: " #function_name " = %s \t", function_name)
#define LOG_EXIT(function_name, info, status) \
LOG_FUNC(function_name); \
LOG("\ninfo = %s\n exit status = %d\n", (info), (status)); \
exit(status)
int execute(const char **argv) {
pid_t pid;
int status;
LOG_FUNC(__FUNCTION__);
if (! argv || ! *argv) {
LOG_EXIT(__FUNCTION__, "Array of pointers is null / name of executable is null", EXIT_FAILURE);
}
if ((pid = fork()) < 0) {
LOG_EXIT(__FUNCTION__, "forking child process failed ", EXIT_FAILURE);
}
else if (pid == 0) {
LOG("Child process pid = %d, parent process pid = %d\n", getpid(), getppid());
if (execvp(*argv, argv) < 0) {
LOG("Call of execvp failed. Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
else {
LOG("Parent process: pid = %d\n", getpid());
LOG("Parent process: waiting for completion of child process with pid = %d\n", pid);
pid_t result;
do {
result = wait(&status);
} while (result != pid && result != -1);
LOG("status of child process: %d\n", status);
LOG("wait(&status) on success returns the process ID of the terminated child - on failure, -1 is returned.\n \
Result of waiting for child process: %d\n", result);
LOG("result of waiting for child process %s child pid\n", result == pid ? "==" : "!=");
if (result == -1) {
LOG("Call of wait(&status) failed. Error: %s\n", strerror(errno));
}
LOG("Parent process: pid = %d\nGoodbye!\n", getpid());
return result;
}
}
void open_file( const char ** filename, const char * mode ) {
FILE * pFile;
pFile = fopen (filename, mode);
if (pFile != NULL) {
LOG("open file of %s\n", filename);
fclose (pFile);
}
else
LOG("file of %s is not exist\n", filename);
}
int system_remove(const char *arg) {
LOG_FUNC(__FUNCTION__);
if (! arg ) {
LOG_EXIT(__FUNCTION__, "C-string arguments is null ", EXIT_FAILURE);
}
int result = system(arg);
if (-1 == result) {
LOG("Call of system(\"%s\") failed. Error: %s\n", arg, strerror(errno));
}
else if (127 == result) {
LOG("Call of system(\"%s\") failed. Shell could not be executed in the child process. \
Error: %s\n", arg, strerror(errno));
}
else if (0 == result) {
LOG("Call of system(\"%s\") succeed. Return value is the termination status of the child \n \
shell used to execute command. The termination status of a shell is the termination status of the last command it executes.\n \
result: %d\n", arg, result);
}
else {
LOG(" result: %d\n", result);
}
return result;
}
void open_files() {
open_file("f1", "r");
open_file("f2", "r");
open_file("f3", "r");
open_file("f4", "r");
}
int main(void) {
system("touch f1 f2 f3 f4");
open_files();
char *exec_args[] = { "rm", "f1", "rm_test.out", "f2", NULL };
execute (exec_args);
system_remove("rm f3 rm_test.out f4");
open_files();
system("ls -lt");
return 0;
}
/* gcc -Wfatal-errors -Wall -Wextra -Wconversion -std=c11 -o rm_test.out rm_test.c */
W konsoli na wyjsciu:
./rm_test.out
open file of f1
open file of f2
open file of f3
open file of f4
F: FUNCTION = execute Parent process: pid = 3442
Parent process: waiting for completion of child process with pid = 3445
Child process pid = 3445, parent process pid = 3442
status of child process: 0
wait(&status) on success returns the process ID of the terminated child - on failure, -1 is returned.
Result of waiting for child process: 3445
result of waiting for child process == child pid
Parent process: pid = 3442
Goodbye!
F: FUNCTION = system_remove rm: cannot remove 'rm_test.out': No such file or directory
result: 256
file of f1 is not exist
file of f2 is not exist
file of f3 is not exist
file of f4 is not exist
/* w folderze nie ma pliku rm_test.out */