Added run_scripts exercises

This commit is contained in:
Fabio Scotto di Santolo
2025-07-07 18:01:53 +02:00
parent a3ad418d82
commit 32acc0954f
5 changed files with 165 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# Makefile for sequential script executor project
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -g
TARGET = run_scripts
SRC = main.c
.PHONY: all clean run test valgrind
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $@ $^
run: $(TARGET)
./$(TARGET) tests/hello.sh tests/fail.sh
test: run
valgrind: $(TARGET)
valgrind --leak-check=full ./$(TARGET) scripts/test1.sh scripts/test2.sh
clean:
rm -f $(TARGET)

73
exercises/run_scripts/README.md Executable file
View File

@@ -0,0 +1,73 @@
# Sequential Script Executor
This project contains a simple C program that sequentially executes one or more bash scripts using `fork()` and `execlp()`.
## Features
* Spawns a child process for each script
* Executes scripts using `/bin/bash`
* Waits for each child to finish before proceeding
* Reports exit status or signal termination
## Usage
### Build
```bash
make
```
### Run with example scripts
```bash
make run
```
### Run manually
```bash
./run_scripts script1.sh script2.sh
```
### Run with Valgrind
```bash
make valgrind
```
### Clean build
```bash
make clean
```
## Project Structure
```
run_scripts/ # Root project folder
├── main.c # Main source code
├── Makefile # Build automation
├── README.md # Project documentation
└── tests/ # Example bash scripts for testing
├── hello.sh
└── fail.sh
```
## Example Output
```sh
execute script 1: test1.sh
script test1.sh exited with code 0
execute script 2: test2.sh
script test2.sh exited with code 0
```
## Notes
* You can add as many scripts as needed in the command-line arguments.
* This tool can be used to batch test or automate shell scripts.
## License
MIT License

View File

@@ -0,0 +1,59 @@
/* This program executes a sequence of Bash scripts
* in sequential order. Each script is run in a child
* process, and the parent prints the exit status.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "usage: %s <file1>...\n", argv[0]);
return EXIT_FAILURE;
}
for (int i = 1; i < argc; i++) {
const char *script_name = argv[i];
printf("execute script %d: %s\n", i, script_name);
/* fork process for execute script itself */
pid_t pid = fork();
switch (pid) {
case -1:
perror("fork");
exit(EXIT_FAILURE);
break;
case 0:
// child executes the current script
if (execlp("/bin/bash", "bash", script_name,
(char *)NULL) == -1) {
perror("execlp");
exit(EXIT_FAILURE);
}
break;
default:
// parent waits for the child process
int status;
if (waitpid(pid, &status, 0) == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("script %s exited with code %d\n",
script_name, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("script %s terminated by signal %d\n",
script_name, WTERMSIG(status));
} else {
printf("script %s did not exit normally\n",
script_name);
}
break;
}
}
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,4 @@
# fail.sh
#!/bin/bash
exit 1

View File

@@ -0,0 +1,5 @@
# hello.sh
#!/bin/bash
echo "Hello, world!"
exit 0