#c #shell #process
#c #оболочка #процесс
Вопрос:
У меня есть это упражнение:
/* smallsh.c */
#include "smallsh.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
char *prompt = "Scrivere un comando>";
void procline(void) /* tratta una riga di input */
{
char *arg[MAXARG 1]; /* array di puntatori per runcommand */
int toktype; /* tipo del simbolo nel comando */
int narg; /* numero di argomenti considerati finora */
int type; /* FOREGROUND o BACKGROUND */
narg=0;
do {
/* mette un simbolo in arg[narg]
ed esegue un'azione a seconda del tipo di simbolo */
switch (toktype = gettok(amp;arg[narg])) {
case ARG:
/* se argomento: passa al prossimo simbolo */
if (narg < MAXARG) narg ;
break;
case EOL:
case SEMICOLON:
case AMPERSAND:
if(toktype == AMPERSAND) type = BACKGROUND;
else type = FOREGROUND;
/* se fine riga o ';' esegue il comando ora contenuto in arg,
mettendo NULL per indicare la fine degli argomenti:
serve a execvp */
if (narg != 0) {
arg[narg] = NULL;
runcommand(arg, type);
}
/* se non fine riga (descrizione comando finisce con ';')
bisogna ricominciare a riempire arg dall'indice 0 */
if (toktype != EOL) narg = 0;
break;
}
}
while (toktype != EOL); /* fine riga, procline finita */
}
void runcommand(char **cline, int type) /* esegue un comando */
{
pid_t pid;
int exitstat,ret;
pid = fork();
if (pid == (pid_t) -1) {
perror("smallsh: fork fallita");
return;
}
if (pid == (pid_t) 0) { /* processo figlio */
/* esegue il comando il cui nome e' il primo elemento di cline,
passando cline come vettore di argomenti */
//if(type == 1) sleep(2);
execvp(*cline,cline);
perror(*cline);
exit(1);
}
/* non serve "else"... ma bisogna aver capito perche' :-) */
/* qui aspetta sempre e comunque - i comandi in background
richiederebbero un trattamento diverso */
if(type == 1) { //BACKGROUND
/*DO SOMETHING*/
}
else { //FOREGROUND
//PART OF THE ORIGINAL CODE
ret = wait(amp;exitstat);
if (ret == -1) perror("wait");
}
}
int main()
{
while(userin(prompt) != EOF)
procline();
return 0;
}
/* input.c */
#include "smallsh.h"
/* buffers per la riga di input e la sua segmentazione in "tokens";
puntatori per scorrere i buffers */
static char inpbuf[MAXBUF], tokbuf[2*MAXBUF],
*ptr, *tok;
/* array di caratteri che hanno una interpretazione "speciale"
nei comandi */
static char special[]=
{' ', 't', ';', 'n', ''};
int userin(char *p) /* stampa il prompt e legge una riga */
{
int c, count;
/* inizializzazioni per altre routines */
ptr = inpbuf;
tok = tokbuf;
/* stampa il prompt */
printf("%s ",p);
count=0;
while(1) {
if ((c = getchar()) == EOF)
return(EOF);
/* si copia il carattere letto in inpbuf; ma se si raggiunge
e supera MAXBUF, non si scrive piu' in inpbuf,
si continua a leggere fino a newline (si veda sotto) */
if (count < MAXBUF)
inpbuf[count ] = c;
/* se si legge il newline, la riga in input e' finita */
if (c == 'n' amp;amp; count < MAXBUF) {
inpbuf[count] = '';
return(count);
}
/* se e' stato superato MAXBUF, quando si arriva al newline
si avverte che la riga e' troppo lunga e si
va a leggere una nuova riga */
if (c == 'n') { /* implicito se si arriva qui: count >= MAXBUF */
printf("riga in input troppo lungan");
count = 0;
printf("%s ",p);
}
}
}
int gettok(char **outptr) /* legge un simbolo e lo mette in tokbuf */
{
int type;
/* si piazza *outptr in modo che punti al primo byte dove si cominicera'
a scrivere il simbolo letto */
*outptr = tok;
/* salta eventuali spazi */
while (*ptr == ' ' || *ptr == 't') ptr ;
/* copia il primo carattere del simbolo */
*tok = *ptr;
/* a seconda del carattere decide il tipo di simbolo */
switch(*ptr ){
case 'n':
type = EOL; break;
case ';':
type = SEMICOLON; break;
case 'amp;':
type = AMPERSAND; break;
default:
type = ARG;
/* copia gli altri caratteri del simbolo */
while(inarg(*ptr))
*tok = *ptr ;
}
/* aggiunge al fondo */
*tok = '';
return(type);
}
int inarg(char c) /* verifica se c non e' un carattere speciale */
{
char *wrk;
for (wrk = special; *wrk != ''; wrk )
if (c == *wrk) return(0);
return(1);
}
/* smallsh.h */
#define FOREGROUND 0
#define BACKGROUND 1
#define MAXARG 512 /* numero massimo di argomenti */
#define MAXBUF 512 /* lunghezza massima riga di input */
int inarg(char c); /* verifica se c non e' un carattere speciale */
int userin(char *p); /* stampa il prompt e legge una riga */
int gettok(char **outptr); /* legge un simbolo */
void procline(); /* tratta una riga di input */
void runcommand(char **cline, int type); /* esegue un comando */
Я должен реализовать фоновое выполнение (amp;), но я понятия не имею, как это сделать…
Я пытался использовать wait при выполнении на переднем плане и без него при выполнении в фоновом режиме, но приглашение и вывод команды находились в одной строке, а «курсор» находился на новой строке.
Можно получить этот результат:
Command> ls amp;
// вывод
Команда> // курсор здесь
вместо:
Command> ls amp;
Command> // вывод
// курсор здесь
?
Комментарии:
1. Весь смысл запуска процесса в фоновом режиме заключается в том, что он выполняется, в то время как оболочка продолжает выполнять больше работы. Таким образом, по определению, если фоновая команда производит вывод, она будет смешана с выводами оболочки (и других команд). Вот почему фоновые процессы обычно всегда перенаправляют свои stdin / stdout / stderr.
Ответ №1:
Возможно ли получить этот результат
К сожалению, это не так. Даже когда вы запускаете программу на переднем плане, ваш курсор находится в конце вывода в терминале. Оболочка выводит эту полную строку запроса, когда программа завершается, чтобы вы знали, что у вас снова есть контроль над оболочкой. Этого не происходит с фоновым выводом, потому что вы по своей сути всегда контролируете оболочку, поэтому не имеет смысла произвольно отображать строку запроса.
Кроме того, представьте, что вы запускаете несколько фоновых процессов: вы бы хотели, чтобы все они вызывали появление строки запроса во время ввода чего-либо?