Skip to content

Instantly share code, notes, and snippets.

@ahmpro
Last active August 29, 2015 14:01
Show Gist options
  • Save ahmpro/682ffdc869ba8e68f58e to your computer and use it in GitHub Desktop.
Save ahmpro/682ffdc869ba8e68f58e to your computer and use it in GitHub Desktop.
terminal emulator - lab 3 on "Operating Systems" in MAI
all:
gcc -Wall -std=gnu99 zhell.c -o zhell
clean:
rm zhell
/*
* File: zhell.c (14.03.2014)
* thx for source code shell dwhitney67 (http://ubuntuforums.org/showthread.php?t=931794&p=5869326#post5869326)
* Copyright 2014 L1S & ahmpro
*/
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <malloc.h>
#include <setjmp.h>
pid_t child_pid, back_pid = 0;
pid_t child_active_pid;
void ctrl_c(int sig) {
switch(sig) {
case SIGINT:
if (child_active_pid > 0) {
kill(child_active_pid, SIGTERM);
child_active_pid = 0;
}
break;
default:
break;
//exit(0);
}
}
int main()
{
int status = 0;
char cmd[512] = {0};
char **argv = malloc(10 * sizeof(char*));
int argc;
char *arg;
int is_bgr = 0;
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = ctrl_c;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sa.sa_mask = set;
sigaction(SIGINT, &sa, 0);
while (1) {
for (int i = 0; i < argc; ++i) {
free(argv[i]);
}
free(argv);
is_bgr = 0;
child_active_pid = 0;
argc = 0;
argv = malloc(10 * sizeof(char*));
printf("zhell (%s) > ",getenv("PWD"));
if (fgets(cmd, sizeof(cmd), stdin ) == NULL) {
printf("\n");
continue;
}
cmd[strlen(cmd)-1] = '\0';
if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) {
break;
}
if (!strcmp(cmd, "kill")) {
back_pid = 0;
}
arg = strtok(cmd, " ");
while (arg != 0 && argc < 9) {
argv[argc++] = strdup(arg);
arg = strtok(NULL, " ");
}
argv[argc] = 0;
if (argc > 0) {
char *last_arg = argv[argc-1];
if (!strcmp(last_arg, "&")) {
printf("1\n");
is_bgr = 1;
argc--;
argv[argc] = 0;
} else if (last_arg[strlen(last_arg)-1] == '&') {
last_arg[strlen(last_arg)-1] = 0;
is_bgr = 1;
}
} else {
continue;
}
child_pid = fork();
if (child_pid < 0) {
perror("Fork failed");
break;
} else if (child_pid > 0) {
if (is_bgr) {
back_pid = child_pid;
child_active_pid = 0;
waitpid(-1, &status, WNOWAIT);
} else {
child_active_pid = child_pid;
waitpid(-1, &status, 0);
child_active_pid = 0;
//printf("Exit status of PID%d was %d\n", (int)child_pid, status);
}
continue;
} else if (child_pid == 0) {
// execute shell command
if (argc>0) {
setpgid(0, 0);
execvp(argv[0], argv);
}
exit(0);
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment