-
Notifications
You must be signed in to change notification settings - Fork 0
/
job_control.c
235 lines (211 loc) · 6.49 KB
/
job_control.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*--------------------------------------------------------
UNIX Shell Project
job_control module
Sistemas Operativos
Grados I. Informatica, Computadores & Software
Dept. Arquitectura de Computadores - UMA
Some code adapted from "Fundamentos de Sistemas Operativos", Silberschatz et al.
--------------------------------------------------------*/
#include "job_control.h"
#ifndef __APPLE__
#include <malloc.h>
#endif
#include <string.h>
// -----------------------------------------------------------------------
// get_command() reads in the next command line, separating it into distinct tokens
// using whitespace as delimiters. setup() sets the args parameter as a
// null-terminated string.
// -----------------------------------------------------------------------
void get_command(char inputBuffer[], int size, char *args[],int *background)
{
int length, /* # of characters in the command line */
i, /* loop index for accessing inputBuffer array */
start, /* index where beginning of next command parameter is */
ct; /* index of where to place the next parameter into args[] */
ct = 0;
*background=0;
/* read what the user enters on the command line */
length = read(STDIN_FILENO, inputBuffer, size);
start = -1;
if (length == 0)
{
printf("\nBye\n");
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 (inputBuffer[i] == '&') // background indicator
{
*background = 1;
if (start != -1)
{
args[ct] = &inputBuffer[start];
ct++;
}
inputBuffer[i] = '\0';
args[ct] = NULL; /* no more arguments to this command */
i=length; // make sure the for loop ends now
}
else if (start == -1) start = i; // start of new argument
} // end switch
} // end for
args[ct] = NULL; /* just in case the input line was > MAXLINE */
}
// -----------------------------------------------------------------------
/* devuelve puntero a un nodo con sus valores inicializados,
devuelve NULL si no pudo realizarse la reserva de memoria*/
job * new_job(pid_t pid, const char * command, enum job_state state)
{
job * aux;
aux=(job *) malloc(sizeof(job));
aux->pgid=pid;
aux->state=state;
aux->command=strdup(command);
aux->next=NULL;
return aux;
}
// -----------------------------------------------------------------------
/* inserta elemento en la cabeza de la lista */
void add_job (job * list, job * item)
{
job * aux=list->next;
list->next=item;
item->next=aux;
list->pgid++;
}
// -----------------------------------------------------------------------
/* elimina el elemento indicado de la lista
devuelve 0 si no pudo realizarse con exito */
int delete_job(job * list, job * item)
{
job * aux=list;
while(aux->next!= NULL && aux->next!= item) aux=aux->next;
if(aux->next)
{
aux->next=item->next;
free(item->command);
free(item);
list->pgid--;
return 1;
}
else
return 0;
}
// -----------------------------------------------------------------------
/* busca y devuelve un elemento de la lista cuyo pid coincida con el indicado,
devuelve NULL si no lo encuentra */
job * get_item_bypid (job * list, pid_t pid)
{
job * aux=list;
while(aux->next!= NULL && aux->next->pgid != pid) aux=aux->next;
return aux->next;
}
// -----------------------------------------------------------------------
job * get_item_bypos( job * list, int n)
{
job * aux=list;
if(n<1 || n>list->pgid) return NULL;
n--;
while(aux->next!= NULL && n) { aux=aux->next; n--;}
return aux->next;
}
// -----------------------------------------------------------------------
/*imprime una linea en el terminal con los datos del elemento: pid, nombre ... */
void print_item(job * item)
{
printf("pid: %d, command: %s, state: %s\n", item->pgid, item->command, state_strings[item->state]);
}
// -----------------------------------------------------------------------
/*recorre la lista y le aplica la funcion pintar a cada elemento */
void print_list(job * list, void (*print)(job *))
{
int n=1;
job * aux=list;
printf("Contents of %s:\n",list->command);
while(aux->next!= NULL)
{
printf(" [%d] ",n);
print(aux->next);
n++;
aux=aux->next;
}
}
// -----------------------------------------------------------------------
/* interpretar valor estatus que devuelve wait */
enum status analyze_status(int status, int *info)
{
if (WIFSTOPPED (status))
{
*info=WSTOPSIG(status);
return(SUSPENDED);
}
else if (WIFCONTINUED (status))
{
*info=0;
return(CONTINUED);
}
else
{
// el proceso termio
if (WIFSIGNALED (status))
{ *info=WTERMSIG (status); return(SIGNALED);}
else
{ *info=WEXITSTATUS(status); return(EXITED);}
}
return 0;
}
// -----------------------------------------------------------------------
// cambia la accion de las señales relacionadas con el terminal
void terminal_signals(void (*func) (int))
{
signal (SIGINT, func); // crtl+c interrupt tecleado en el terminal
signal (SIGQUIT, func); // ctrl+\ quit tecleado en el terminal
signal (SIGTSTP, func); // crtl+z Stop tecleado en el terminal
signal (SIGTTIN, func); // proceso en segundo plano quiere leer del terminal
signal (SIGTTOU, func); // proceso en segundo plano quiere escribir en el terminal
}
// -----------------------------------------------------------------------
void block_signal(int signal, int block)
{
/* declara e inicializa máscara */
sigset_t block_sigchld;
sigemptyset(&block_sigchld );
sigaddset(&block_sigchld,signal);
if(block)
{
/* bloquea señal */
sigprocmask(SIG_BLOCK, &block_sigchld, NULL);
}
else
{
/* desbloquea señal */
sigprocmask(SIG_UNBLOCK, &block_sigchld, NULL);
}
}