-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShellComp.c
170 lines (145 loc) · 5.34 KB
/
ShellComp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
*
* @author: Anizz Carrillo Alvarado
* ProgramTitle: MiniShell UNIX
* Description:
* Es una mini_consola en lenguaje C,
* que va contando los comandos ingresados
* y te imprime los ultimos 10
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#define MAX_LINE 80
#define HISTORY_COUNT 10 /* Esta define el contador del historial */
#define BUFFER_SIZE 50
#define MAX_HISTORY 50 /* Máximo número de comandos en el historial */
//------------DECLARACIONES-----------------
char buffer[BUFFER_SIZE];
char history[MAX_HISTORY][MAX_LINE]; /* Arreglo de almacenamiento del historial */
int history_index = 0; /* Índice de seguimiento del historial */
int total_commands = 0; /* Total de comandos ingresados */
//------------FUNCIONES UTILIZADAS EN EL PROGRAMA -----------------
/* Función handle_SIGINT */
void handle_SIGINT() {
write(STDOUT_FILENO, buffer, strlen(buffer));
int start = (total_commands < HISTORY_COUNT) ? 0 : total_commands - HISTORY_COUNT;
for (int i = start; i < total_commands; i++) {
int index = i % MAX_HISTORY;
if (strlen(history[index]) > 0) {
char output[MAX_LINE + 20]; // Aumentamos el tamaño del buffer
snprintf(output, sizeof(output), "%d %s\n", i + 1, history[index]);
write(STDOUT_FILENO, output, strlen(output));
}
}
exit(0);
}
/* Función Historial */
void add_history(char inputBuffer[]) {
strncpy(history[history_index], inputBuffer, MAX_LINE);
history_index = (history_index + 1) % MAX_HISTORY;
total_commands++;
}
//imprimir lissta de comandos
void print_last_commands() {
int start = (total_commands < HISTORY_COUNT) ? 0 : total_commands - HISTORY_COUNT;
for (int i = start; i < total_commands; i++) {
int index = i % MAX_HISTORY;
if (strlen(history[index]) > 0) {
printf("%d %s\n", i + 1, history[index]);
}
}
}
// @author: Anizz1
void setup(char inputBuffer[], char *args[], int *background) {
int length, i, start, ct;
ct = 0;
/* leer lo que el usuario escribe en la línea de comandos */
length = read(STDIN_FILENO, inputBuffer, MAX_LINE);
start = -1;
if (length == 0)
exit(0); /* ^d was entered, end of user command stream */
if (length < 0){
perror("error reading the command");
exit(-1); /* terminate with error code of -1 */
}
/* examine every character in the inputBuffer */
for (i = 0; i < length; i++) {
switch (inputBuffer[i]){
case ' ':
case '\t' : /* argument separators */
if (start != -1){
args[ct] = &inputBuffer[start]; /* set up pointer */
ct++;
}
inputBuffer[i] = '\0'; /* add a null char; make a C string */
start = -1;
break;
case '\n': /* should be the final char examined */
if (start != -1){
args[ct] = &inputBuffer[start];
ct++;
}
inputBuffer[i] = '\0';
args[ct] = NULL; /* no more arguments to this command */
break;
default : /* some other character */
if (start == -1)
start = i;
if (inputBuffer[i] == '&'){
*background = 1;
inputBuffer[i] = '\0';
}
}
}
args[ct] = NULL; /* just in case the input line was > 80 */
}
// MAIN
int main(void) {
char inputBuffer[MAX_LINE]; /* búfer para almacenar los comandos introducidos */
int background; /* igual a 1 si el comando termina con '&' */
char *args[MAX_LINE / 2 + 1];
// Estructura de controlador de sigacción (señal)
struct sigaction handler;
handler.sa_handler = SIG_IGN; //ignorar el SIGINT en el proceso hijo
//handler.sa_handler = handle_SIGINT;
//author: Anizz1
sigemptyset(&handler.sa_mask);
handler.sa_flags = 0;
sigaction(SIGINT, &handler, NULL);
strcpy(buffer, "\nSe presionó <ctrl> + <c>\n");
while (1) { /* Program terminates normally inside setup */
background = 0;
printf(" ::myshellsmall-> $$ \n");
setup(inputBuffer, args, &background); /* get next command */
add_history(inputBuffer);
print_last_commands();
// Agregamos un proceso hijo con FORK
pid_t pid = fork(); // Crea un proceso hijo
if (pid < 0) { // Si fork() devuelve un # < 0 da error
perror("Fork failed");
exit(1);
} else if (pid == 0) {
//ignorar el SIGINT en el proceso hijo
struct sigaction child_handler;
child_handler.sa_handler = SIG_IGN; //ignorar el SIGINT en el proceso hijo
sigemptyset(&child_handler.sa_mask);
child_handler.sa_flags = 0;
sigaction(SIGINT, &child_handler, NULL);
//Fin del proceso de ignorar
execvp(args[0], args);
perror("execvp failed");
exit(1);
} else {
if (background == 0) {
waitpid(pid, NULL, 0);
}
}
}
}