Skip to content

Instantly share code, notes, and snippets.

@Minoru
Created October 27, 2010 23:19
Show Gist options
  • Save Minoru/650228 to your computer and use it in GitHub Desktop.
Save Minoru/650228 to your computer and use it in GitHub Desktop.
C implementation of simple shell script
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // sleep()
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int make_redirection(int stream, const char* file) {
/* Redirects file to ctream
* Return value:
* 0 success
* 1 wrong stream specified
* 2 can't open specified file
* 3 loop in symbolic links encountered during filename resolution
* 4 name is too long
* 5 too many files open in system
*/
int fd;
if(stream == 0 || stream == 1 || stream == 2) {
if(stream) {
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
} else {
fd = open(file, O_RDONLY, 0666);
}
if(fd == -1) {
if(errno == EACCES) {
return 2;
}
}
dup2(fd, stream);
close(fd);
return 0;
} else {
return 1;
}
}
int main() {
// if ! [ -e a.txt ]
pid_t pid = fork();
if(pid) {
int retval;
waitpid(pid, &retval, 0);
if(WIFEXITED(retval) && WEXITSTATUS(retval) == 1) {
pid = fork();
if(pid) {
waitpid(pid, NULL, WNOHANG); // non-blocking call
// sleep 1
sleep(1);
pid_t pid2 = fork();
if(pid2) {
waitpid(pid2, NULL, 0); // waiting for backgrounded ping
} else {
// tail -f a.txt
char* process2[] = { "tail", "-f", "a.txt", NULL };
execvp(process2[0], process2);
}
} else {
// ping google.com > a.txt 2 > /dev/null &
char* process3[] = { "ping", "google.com", NULL };
make_redirection(1, "a.txt");
make_redirection(2, "/dev/null");
execvp(process3[0], process3);
}
}
} else {
// [ -e a.txt ]
char* process1[] = { "[", "-e", "a.txt", "]", NULL };
execvp(process1[0], process1);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment