background jobs & stdout,in,err redirect
This commit is contained in:
parent
93979512d9
commit
44a74c50f2
8 changed files with 377 additions and 42 deletions
2
Makefile
2
Makefile
|
@ -6,7 +6,7 @@ MANPREFIX = ${PREFIX}/share/man
|
||||||
|
|
||||||
CFLAGS = -std=gnu11 -O0 -Wall -DVERSION=\"${VERSION}\"
|
CFLAGS = -std=gnu11 -O0 -Wall -DVERSION=\"${VERSION}\"
|
||||||
|
|
||||||
SRC = rush.c color.c constants.h history.c commands.c
|
SRC = rush.c color.c constants.h history.c commands.c job.c
|
||||||
OBJ = ${SRC:.c=.o}
|
OBJ = ${SRC:.c=.o}
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
|
|
|
@ -14,6 +14,7 @@ rush is a minimalistic shell for Unix systems written in C.
|
||||||
# Building
|
# Building
|
||||||
```sh
|
```sh
|
||||||
$ make
|
$ make
|
||||||
|
$ sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
@ -30,6 +31,9 @@ $ ./rush
|
||||||
- Editing using left and right arrow keys
|
- Editing using left and right arrow keys
|
||||||
- !! to repeat last command
|
- !! to repeat last command
|
||||||
- Pipes
|
- Pipes
|
||||||
|
- autojump to directorys
|
||||||
|
- stdin, stdout, stderr redirect
|
||||||
|
- background jobs
|
||||||
|
|
||||||
# Built in commands
|
# Built in commands
|
||||||
- cd
|
- cd
|
||||||
|
@ -38,10 +42,10 @@ $ ./rush
|
||||||
- history
|
- history
|
||||||
- export
|
- export
|
||||||
- source
|
- source
|
||||||
|
- j
|
||||||
|
- bg
|
||||||
|
|
||||||
# Todo Features
|
# Todo Features
|
||||||
- stdin, stdout, stderr redirect
|
|
||||||
- background jobs
|
|
||||||
- tab completion
|
- tab completion
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
296
commands.c
296
commands.c
|
@ -9,6 +9,7 @@
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
#include "rush.h"
|
#include "rush.h"
|
||||||
|
#include "job.h"
|
||||||
|
|
||||||
int execute(char **args);
|
int execute(char **args);
|
||||||
|
|
||||||
|
@ -19,6 +20,8 @@ int quit(char **args);
|
||||||
int history(char **args);
|
int history(char **args);
|
||||||
int export(char **args);
|
int export(char **args);
|
||||||
int source(char **args);
|
int source(char **args);
|
||||||
|
int j(char **args);
|
||||||
|
int bg(char **args);
|
||||||
|
|
||||||
// List of builtin commands' names
|
// List of builtin commands' names
|
||||||
char *builtin_cmds[] = {
|
char *builtin_cmds[] = {
|
||||||
|
@ -27,7 +30,9 @@ char *builtin_cmds[] = {
|
||||||
"exit",
|
"exit",
|
||||||
"history",
|
"history",
|
||||||
"export",
|
"export",
|
||||||
"source"
|
"source",
|
||||||
|
"j",
|
||||||
|
"bg",
|
||||||
};
|
};
|
||||||
|
|
||||||
int (*builtin_func[]) (char **) = {
|
int (*builtin_func[]) (char **) = {
|
||||||
|
@ -36,26 +41,124 @@ int (*builtin_func[]) (char **) = {
|
||||||
&quit, // cant name it exit as it is taken
|
&quit, // cant name it exit as it is taken
|
||||||
&history,
|
&history,
|
||||||
&export,
|
&export,
|
||||||
&source
|
&source,
|
||||||
|
&j,
|
||||||
|
&bg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *shortcut_dirs[] = {
|
||||||
|
"rush",
|
||||||
|
"bin",
|
||||||
|
"localbin",
|
||||||
|
};
|
||||||
|
|
||||||
|
char *shortcut_expand_dirs[] = {
|
||||||
|
"~/.nky/Coding/C/rush",
|
||||||
|
"~/.local/bin",
|
||||||
|
"/usr/local/bin",
|
||||||
|
};
|
||||||
|
|
||||||
|
char *gethome() {
|
||||||
|
char *home = getenv("HOME");
|
||||||
|
if (home == NULL) {
|
||||||
|
fprintf(stderr, "Error: HOME environment variable not set.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return home;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *replace_home_dir(char *str) {
|
||||||
|
char *home_path = gethome();
|
||||||
|
|
||||||
|
int path_len = strlen(str);
|
||||||
|
int home_len = strlen(home_path);
|
||||||
|
|
||||||
|
// Allocate memory for the new path
|
||||||
|
char* new_path = memalloc(sizeof(char) * (path_len + home_len + 1));
|
||||||
|
|
||||||
|
int i = 0, j = 0;
|
||||||
|
while (str[i] != '\0') {
|
||||||
|
if (str[i] == '~') {
|
||||||
|
// Copy HOME environment variable value
|
||||||
|
for (int k = 0; k < home_len; k++) {
|
||||||
|
new_path[j++] = home_path[k];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
new_path[j++] = str[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_path[j] = '\0';
|
||||||
|
return new_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *replace_absolute_home(char *str) {
|
||||||
|
char *home_path = gethome();
|
||||||
|
|
||||||
|
int path_len = strlen(str);
|
||||||
|
int home_len = strlen(home_path);
|
||||||
|
|
||||||
|
// Allocate memory for the new path
|
||||||
|
char* new_path = memalloc(sizeof(char) * (path_len - home_len + 2));
|
||||||
|
|
||||||
|
int i = 0, j = 0;
|
||||||
|
while (str[i] != '\0') {
|
||||||
|
if (strncmp(&str[i], home_path, home_len) == 0) {
|
||||||
|
// Copy HOME environment variable value
|
||||||
|
new_path[j++] = '~';
|
||||||
|
i += home_len;
|
||||||
|
} else {
|
||||||
|
new_path[j++] = str[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_path[j] = '\0';
|
||||||
|
return new_path;
|
||||||
|
}
|
||||||
|
|
||||||
// number of built in commands
|
// number of built in commands
|
||||||
int num_builtins() {
|
int num_builtins() {
|
||||||
return sizeof(builtin_cmds) / sizeof(char *);
|
return sizeof(builtin_cmds) / sizeof(char *);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// autojump
|
||||||
|
int j(char **args) {
|
||||||
|
if (args[1] == NULL) {
|
||||||
|
fprintf(stderr, "rush: not enough arguments\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < sizeof(shortcut_dirs) / sizeof(char *); i++) {
|
||||||
|
int len = strlen(shortcut_dirs[i]);
|
||||||
|
if (strncmp(args[1], shortcut_dirs[i], len) == 0) {
|
||||||
|
char **merged_cd = memalloc(sizeof(char *) * 3);
|
||||||
|
merged_cd[0] = "cd";
|
||||||
|
merged_cd[1] = shortcut_expand_dirs[i];
|
||||||
|
merged_cd[2] = NULL;
|
||||||
|
cd(merged_cd);
|
||||||
|
printf("jumped to %s\n", shortcut_expand_dirs[i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// change directory
|
// change directory
|
||||||
int cd(char **args) {
|
int cd(char **args) {
|
||||||
|
int i = 0;
|
||||||
if (args[1] == NULL) {
|
if (args[1] == NULL) {
|
||||||
char *home = getenv("HOME");
|
char *home = gethome();
|
||||||
if (home == NULL) {
|
|
||||||
fprintf(stderr, "rush: HOME environment variable is missing\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (chdir(home) != 0) {
|
if (chdir(home) != 0) {
|
||||||
perror("rush");
|
perror("rush");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
while (args[1][i] != '\0') {
|
||||||
|
if (args[1][i] == '~') {
|
||||||
|
args[1] = replace_home_dir(args[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
if (chdir(args[1]) != 0) {
|
if (chdir(args[1]) != 0) {
|
||||||
perror("rush");
|
perror("rush");
|
||||||
}
|
}
|
||||||
|
@ -144,6 +247,24 @@ int source(char **args) {
|
||||||
return status; // Indicate success
|
return status; // Indicate success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bg(char **args) {
|
||||||
|
if (args[1] == NULL) {
|
||||||
|
fprintf(stderr, "rush: not enough arguments\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int job_index = atoi(args[1]);
|
||||||
|
if (job_index == 0) {
|
||||||
|
fprintf(stderr, "rush: invalid job index\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
job *search = get_job(job_index - 1);
|
||||||
|
if (search == NULL) {
|
||||||
|
fprintf(stderr, "rush: no such job\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("Job %i: %s\n", job_index, search->command);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
bool is_builtin(char *command) {
|
bool is_builtin(char *command) {
|
||||||
for (int i = 0; i < num_builtins(); i++) {
|
for (int i = 0; i < num_builtins(); i++) {
|
||||||
if (strcmp(command, builtin_cmds[i]) == 0) {
|
if (strcmp(command, builtin_cmds[i]) == 0) {
|
||||||
|
@ -153,6 +274,58 @@ bool is_builtin(char *command) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int launch(char **args, int fd, int options) {
|
||||||
|
int is_bgj = (options & OPT_BGJ) ? 1 : 0;
|
||||||
|
int redirect_stdout = (options & OPT_STDOUT) ? 1 : 0;
|
||||||
|
int redirect_stdin = (options & OPT_STDIN) ? 1 : 0;
|
||||||
|
int redirect_stderr = (options & OPT_STDERR) ? 1 : 0;
|
||||||
|
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
int status;
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
// Child process
|
||||||
|
if (fd > 2) {
|
||||||
|
// not stdin, stdout, or stderr
|
||||||
|
if (redirect_stdout) {
|
||||||
|
if (dup2(fd, STDOUT_FILENO) == -1) {
|
||||||
|
perror("rush");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (redirect_stdin) {
|
||||||
|
if (dup2(fd, STDIN_FILENO) == -1) {
|
||||||
|
perror("rush");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (redirect_stderr) {
|
||||||
|
if (dup2(fd, STDERR_FILENO) == -1) {
|
||||||
|
perror("rush");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd); // close fd as it is duplicated already
|
||||||
|
}
|
||||||
|
if (execvp(args[0], args) == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
fprintf(stderr, "rush: command not found: %s\n", args[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE); // exit the child
|
||||||
|
} else if (pid < 0) {
|
||||||
|
perror("fork failed");
|
||||||
|
} else {
|
||||||
|
// Parent process
|
||||||
|
if (is_bgj) {
|
||||||
|
int job_index = add_job(pid, args[0], true);
|
||||||
|
printf("[Job: %i] [Process ID: %i] [Command: %s]\n", job_index + 1, pid, args[0]);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
waitpid(pid, &status, WUNTRACED); // wait child to be exited to return to prompt
|
||||||
|
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
// execute built in commands or launch commands and wait it to terminate, return 1 to keep shell running
|
// execute built in commands or launch commands and wait it to terminate, return 1 to keep shell running
|
||||||
int execute(char **args) {
|
int execute(char **args) {
|
||||||
if (args[0] == NULL) { // An empty command was entered.
|
if (args[0] == NULL) { // An empty command was entered.
|
||||||
|
@ -165,52 +338,94 @@ int execute(char **args) {
|
||||||
return (*builtin_func[i])(args);
|
return (*builtin_func[i])(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_arg = 0;
|
int num_arg = 0;
|
||||||
|
|
||||||
while (*args != NULL) {
|
while (args[num_arg] != NULL) {
|
||||||
num_arg++; // count number of args
|
if (strncmp(args[num_arg], "&", 1) == 0) {
|
||||||
args++;
|
args[num_arg] = NULL;
|
||||||
|
if (args[num_arg + 1] != NULL) {
|
||||||
|
// have commands after &
|
||||||
|
execute(&args[num_arg + 1]);
|
||||||
}
|
}
|
||||||
|
launch(args, STDOUT_FILENO, OPT_BGJ);
|
||||||
args -= num_arg;
|
|
||||||
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
int status;
|
|
||||||
if ((pid = fork()) == 0) {
|
|
||||||
// Child process
|
|
||||||
if (execvp(args[0], args) == -1) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
fprintf(stderr, "rush: command not found: %s\n", args[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit(EXIT_FAILURE); // exit the child
|
|
||||||
} else if (pid < 0) {
|
|
||||||
perror("fork failed");
|
|
||||||
} else {
|
|
||||||
// Parent process
|
|
||||||
do {
|
|
||||||
waitpid(pid, &status, WUNTRACED); // wait child to be exited to return to prompt
|
|
||||||
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
if (strncmp(args[num_arg], ">", 1) == 0) {
|
||||||
|
int fd = fileno(fopen(args[num_arg + 1], "w+"));
|
||||||
|
if (fd == -1) {
|
||||||
|
perror("rush");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args[num_arg] = NULL;
|
||||||
|
int asdf = 0;
|
||||||
|
while (args[asdf] != NULL) {
|
||||||
|
fprintf(stderr, "args[%i]: %s\n", asdf, args[asdf]);
|
||||||
|
asdf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return launch(args, fd, OPT_FGJ | OPT_STDOUT);
|
||||||
|
}
|
||||||
|
if (strncmp(args[num_arg], "<", 1) == 0) {
|
||||||
|
int fd = fileno(fopen(args[num_arg + 1], "r"));
|
||||||
|
if (fd == -1) {
|
||||||
|
perror("rush");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args[num_arg] = NULL;
|
||||||
|
return launch(args, fd, OPT_FGJ | OPT_STDIN);
|
||||||
|
}
|
||||||
|
if (strncmp(args[num_arg], "2>", 2) == 0) {
|
||||||
|
int fd = fileno(fopen(args[num_arg + 1], "w+"));
|
||||||
|
if (fd == -1) {
|
||||||
|
perror("rush");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args[num_arg] = NULL;
|
||||||
|
return launch(args, fd, OPT_FGJ | OPT_STDERR);
|
||||||
|
}
|
||||||
|
if (strncmp(args[num_arg], ">&", 2) == 0) {
|
||||||
|
int fd = fileno(fopen(args[num_arg + 1], "w+"));
|
||||||
|
if (fd == -1) {
|
||||||
|
perror("rush");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args[num_arg] = NULL;
|
||||||
|
return launch(args, fd, OPT_FGJ | OPT_STDOUT | OPT_STDERR);
|
||||||
|
}
|
||||||
|
if (strncmp(args[num_arg], ">>", 2) == 0) {
|
||||||
|
int fd = fileno(fopen(args[num_arg + 1], "a+"));
|
||||||
|
if (fd == -1) {
|
||||||
|
perror("rush");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args[num_arg] = NULL;
|
||||||
|
return launch(args, fd, OPT_FGJ | OPT_STDOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_arg++; // count number of args
|
||||||
|
}
|
||||||
|
|
||||||
|
return launch(args, STDOUT_FILENO, OPT_FGJ);
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute_pipe with as many pipes as needed
|
// execute_pipe with as many pipes as needed
|
||||||
int execute_pipe(char ***args) {
|
int execute_pipe(char ***args) {
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
int status;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int in = 0;
|
int in = 0;
|
||||||
|
|
||||||
int num_cmds = 0;
|
int num_cmds = 0;
|
||||||
while (args[num_cmds] != NULL) {
|
while (args[num_cmds] != NULL) {
|
||||||
|
int num_args = 0;
|
||||||
|
while (args[num_cmds][num_args] != NULL) {
|
||||||
|
//printf("args [%i]: %s\n", num_cmds, args[num_cmds][num_args]);
|
||||||
|
num_args++;
|
||||||
|
}
|
||||||
num_cmds++;
|
num_cmds++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_cmds - 1; i++) {
|
for (int i = 0; i < num_cmds - 1; i++) {
|
||||||
|
//printf("i: %d\n", i);
|
||||||
pipe(pipefd);
|
pipe(pipefd);
|
||||||
if ((pid = fork()) == 0) {
|
if ((pid = fork()) == 0) {
|
||||||
// then this (child)
|
// then this (child)
|
||||||
|
@ -219,8 +434,8 @@ int execute_pipe(char ***args) {
|
||||||
dup2(pipefd[1], STDOUT_FILENO); // make output go to pipe (next output)
|
dup2(pipefd[1], STDOUT_FILENO); // make output go to pipe (next output)
|
||||||
}
|
}
|
||||||
close(pipefd[0]); // close original input
|
close(pipefd[0]); // close original input
|
||||||
status = execute(args[i]);
|
execute(args[i]);
|
||||||
exit(status);
|
exit(EXIT_SUCCESS);
|
||||||
} else if (pid < 0) {
|
} else if (pid < 0) {
|
||||||
perror("fork failed");
|
perror("fork failed");
|
||||||
}
|
}
|
||||||
|
@ -230,16 +445,17 @@ int execute_pipe(char ***args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pid = fork()) == 0) {
|
if ((pid = fork()) == 0) {
|
||||||
|
// printf("last command\n");
|
||||||
dup2(in, STDIN_FILENO); // get input from pipe
|
dup2(in, STDIN_FILENO); // get input from pipe
|
||||||
status = execute(args[num_cmds - 1]);
|
execute(args[num_cmds - 1]);
|
||||||
exit(status);
|
exit(EXIT_SUCCESS);
|
||||||
} else if (pid < 0) {
|
} else if (pid < 0) {
|
||||||
perror("fork failed");
|
perror("fork failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
close(in);
|
close(in);
|
||||||
for (int i = 0; i < num_cmds; i++) {
|
for (int i = 0; i < num_cmds; i++) {
|
||||||
wait(&status);
|
waitpid(pid, NULL, 0);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#ifndef COMMANDS_H_
|
#ifndef COMMANDS_H_
|
||||||
#define COMMANDS_H_
|
#define COMMANDS_H_
|
||||||
|
|
||||||
|
char *replace_absolute_home(char *str);
|
||||||
int num_builtins();
|
int num_builtins();
|
||||||
bool is_builtin(char *command);
|
bool is_builtin(char *command);
|
||||||
int execute(char **args);
|
int execute(char **args, int fd, int options);
|
||||||
int execute_pipe(char ***args);
|
int execute_pipe(char ***args);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,4 +6,11 @@
|
||||||
#define RL_BUFSIZE 1024 // size of each command
|
#define RL_BUFSIZE 1024 // size of each command
|
||||||
#define TOK_DELIM " \t\r\n\a" // delimiter for token
|
#define TOK_DELIM " \t\r\n\a" // delimiter for token
|
||||||
#define MAX_HISTORY 8192 // maximum lines of reading history
|
#define MAX_HISTORY 8192 // maximum lines of reading history
|
||||||
|
|
||||||
|
#define MAX_JOBS 64 // maximum number of jobs
|
||||||
|
#define OPT_STDIN 0x01 // option for stdin
|
||||||
|
#define OPT_STDOUT 0x02 // option for stdout
|
||||||
|
#define OPT_STDERR 0x04 // option for stderr
|
||||||
|
#define OPT_FGJ 0x08 // option for foreground job
|
||||||
|
#define OPT_BGJ 0x10 // option for background job
|
||||||
#endif
|
#endif
|
||||||
|
|
62
job.c
Normal file
62
job.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "rush.h"
|
||||||
|
|
||||||
|
typedef struct job {
|
||||||
|
pid_t pid;
|
||||||
|
char *command;
|
||||||
|
bool status;
|
||||||
|
struct job *next;
|
||||||
|
} job;
|
||||||
|
|
||||||
|
job *jobs = NULL;
|
||||||
|
|
||||||
|
int num_jobs() {
|
||||||
|
job *current = jobs;
|
||||||
|
int count = 0;
|
||||||
|
while (current != NULL) {
|
||||||
|
count++;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_job(pid_t pid, char *command, bool status) {
|
||||||
|
job *current = jobs;
|
||||||
|
job *new_job = memalloc(sizeof(job));
|
||||||
|
new_job->pid = pid;
|
||||||
|
char *buf = memalloc(strlen(command) + 1);
|
||||||
|
strcpy(buf, command);
|
||||||
|
new_job->command = buf;
|
||||||
|
new_job->status = status;
|
||||||
|
new_job->next = NULL;
|
||||||
|
if (current == NULL) {
|
||||||
|
jobs = new_job;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int index = 1;
|
||||||
|
while (current->next != NULL) {
|
||||||
|
current = current->next;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
current->next = new_job;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
job *get_job(int index) {
|
||||||
|
job *current = jobs;
|
||||||
|
if (index == 0) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
if (index > num_jobs()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < index; i++) {
|
||||||
|
printf("current: %s\n", current->command);
|
||||||
|
current = current->next;
|
||||||
|
printf("next: %s\n", current->command);
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
17
job.h
Normal file
17
job.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef JOB_H_
|
||||||
|
#define JOB_H_
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct job {
|
||||||
|
pid_t pid;
|
||||||
|
char *command;
|
||||||
|
bool status;
|
||||||
|
struct job *next;
|
||||||
|
} job;
|
||||||
|
|
||||||
|
int add_job(pid_t pid, char *command, bool status);
|
||||||
|
job *get_job(pid_t pid);
|
||||||
|
|
||||||
|
#endif
|
28
log
Normal file
28
log
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
drwxr-xr-x 3 n n 4.0K Feb 11 00:04 .
|
||||||
|
drwxr-xr-x 13 n n 4.0K Feb 6 21:29 ..
|
||||||
|
-rw-r--r-- 1 n n 522 Feb 10 22:42 color.c
|
||||||
|
-rw-r--r-- 1 n n 199 Feb 10 22:42 color.h
|
||||||
|
-rw-r--r-- 1 n n 6.0K Feb 10 22:44 color.o
|
||||||
|
-rw-r--r-- 1 n n 12K Feb 11 00:04 commands.c
|
||||||
|
-rw-r--r-- 1 n n 220 Feb 10 19:17 commands.h
|
||||||
|
-rw-r--r-- 1 n n 15K Feb 11 00:02 commands.o
|
||||||
|
-rw-r--r-- 1 n n 598 Feb 10 23:23 constants.h
|
||||||
|
drwxr-xr-x 8 n n 4.0K Feb 10 23:31 .git
|
||||||
|
-rw-r--r-- 1 n n 18 Feb 6 18:42 .gitignore
|
||||||
|
-rw-r--r-- 1 n n 4.0K Feb 10 16:10 history.c
|
||||||
|
-rw-r--r-- 1 n n 207 Feb 9 18:36 history.h
|
||||||
|
-rw-r--r-- 1 n n 13K Feb 10 22:19 history.o
|
||||||
|
-rw-r--r-- 1 n n 938 Feb 10 23:24 job.c
|
||||||
|
-rw-r--r-- 1 n n 133 Feb 10 19:06 job.h
|
||||||
|
-rw-r--r-- 1 n n 4.6K Feb 10 23:26 job.o
|
||||||
|
-rw-r--r-- 1 n n 35K Feb 6 18:24 LICENSE
|
||||||
|
-rw-r--r-- 1 n n 0 Feb 11 00:05 log
|
||||||
|
-rw-r--r-- 1 n n 878 Feb 10 23:27 Makefile
|
||||||
|
-rw-r--r-- 1 n n 1.3K Feb 10 19:11 README.md
|
||||||
|
-rwxr-xr-x 1 n n 43K Feb 11 00:02 rush
|
||||||
|
-rw-r--r-- 1 n n 23K Feb 8 22:25 rush-0.1.tar.gz
|
||||||
|
-rw-r--r-- 1 n n 373 Feb 6 18:56 rush.1
|
||||||
|
-rw-r--r-- 1 n n 17K Feb 10 23:30 rush.c
|
||||||
|
-rw-r--r-- 1 n n 119 Feb 10 16:06 rush.h
|
||||||
|
-rw-r--r-- 1 n n 15K Feb 10 23:50 rush.o
|
||||||
|
[Job: 1] [Process ID: 2150241] [Command: firefox]
|
Loading…
Reference in a new issue