Added run_scripts exercises
This commit is contained in:
24
exercises/run_scripts/Makefile
Normal file
24
exercises/run_scripts/Makefile
Normal 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
73
exercises/run_scripts/README.md
Executable 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
|
||||
|
||||
59
exercises/run_scripts/main.c
Normal file
59
exercises/run_scripts/main.c
Normal 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;
|
||||
}
|
||||
4
exercises/run_scripts/tests/fail.sh
Executable file
4
exercises/run_scripts/tests/fail.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
# fail.sh
|
||||
#!/bin/bash
|
||||
exit 1
|
||||
|
||||
5
exercises/run_scripts/tests/hello.sh
Executable file
5
exercises/run_scripts/tests/hello.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
# hello.sh
|
||||
#!/bin/bash
|
||||
echo "Hello, world!"
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user