有关命令终止的事实的信息,C 中的命令行管理程序



runcommand(( 用于通过fork()在 shell 中执行命令。

对于在后台启动的命令,如何打印有关命令终止的信息(使用 waitpid 的 WNOHANG 选项(?

打印信息:进程终止 [PID]

所有子进程完全结束非常重要

#include <sys/types.h>
#include <signal.h> 
#include <fcntl.h>  // tipi di apertura file
#include <assert.h> // assert
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define EOL 1       /* end of line */
#define ARG 2       /* normal topic */
#define AMPERSAND 3     /* & */
#define SEMICOLON 4 /* ; */
#define REDIRECT 5  /* > */
#define APPEND 6     /* >> */
#define MAXARG 512  /* maximum number of arguments */
#define MAXBUF 512
#define FOREGROUND 0
#define BACKGROUND 1
int gettok(char **outptr);  /* reads a symbol */
void runcommand(char **cline,int where);    /* execute a command */
int inarg(char c);      /* check if c is not a special character */
pid_t pid;
char prompt[MAXBUF];
static char inpbuf[MAXBUF], tokbuf[2*MAXBUF], *ptr, *tok;
static char special[]=
{' ', 't', '&', ';', 'n', '', '>'};
int proc(void)  /* treats a line of input */
{
char *arg[MAXARG+1];    /* array of pointers for runcommand */
int toktype;
int n_arg;      /* number of topics considered so far */
int type;       /* FOREGROUND o BACKGROUND */
n_arg=0;
while (1)
{
switch (toktype = gettok(&arg[n_arg])) 
{
/* if argument: go to the next symbol */
case ARG:
if (n_arg < MAXARG)
{n_arg++;}
break;
/* if end of line or ';' or '&' executes the command now contained in arg, putting NULL to signal the end of the arguments: it serves as execvp */
case EOL:
case SEMICOLON:
case AMPERSAND:
type = (toktype == AMPERSAND) ? BACKGROUND : FOREGROUND;
if (n_arg != 0) 
{
arg[n_arg] = NULL;
runcommand(arg,type);
}

if (toktype == EOL) return 1;
n_arg = 0;
break;
}
}
}
void runcommand(char **command,int wr)  
{
int exitstat,ret;
pid = fork();
if (pid == (pid_t) -1) 
{
perror("smallsh: fork fallita");
return;
}
if (pid == (pid_t) 0)           /* child */
{
execvp(*command,command);/* executes a command */
perror(*command);
exit(1);
}
else if(wr != BACKGROUND)    /* father */
{
ret = waitpid(pid, &exitstat, 0);
if (ret == -1) perror("wait");
}
}
int scan(char *p); /* print the prompt and read a line */
int main()
{
while(scan(prompt) != EOF)
proc();
}
int scan(char *p)
{
int c, count;
ptr = inpbuf;
tok = tokbuf;
printf("%s ",p);
count=0;
while(1) 
{
if ((c = getchar()) == EOF)
return(EOF);
if (count < MAXBUF)
inpbuf[count++] = c;
if (c == 'n' && count < MAXBUF) 
{
inpbuf[count] = '';
return(count);
}
if (c == 'n') 
{
printf("riga in input troppo lungan");
count = 0;
printf("%s ",p);
}
}
}
int gettok(char **outptr)  
{
int type;
*outptr = tok;
while (*ptr == ' ' || *ptr == 't') ptr++;
*tok++ = *ptr;
switch(*ptr++)
{
case 'n':
type = EOL; break;
case '&':
type = AMPERSAND; break;
case ';':
type = SEMICOLON; break;
default:
type = ARG;
while(inarg(*ptr))
*tok++ = *ptr++;
}
*tok++ = '';
return(type);
}
int inarg(char c)  
{
char *wrk;
for (wrk = special; *wrk != ''; wrk++)
if (c == *wrk) return(0);
return(1);
}

因此,如果您调用ret = waitpid(pid, &exitstat, WNOHANG),那么即使孩子没有退出,该命令也会返回。因此,您需要查看返回值ret以查看函数是否成功,然后查看exitstat的值以查看子值是否已退出(通过从main()函数返回或由于信号(:

if(ret >= 0)
{
if(WIFEXITED(exitstat) || WIFSIGNALED(exitstat))
{
printf("Child endedn");
}
}
else
{
printf("Error!n");
}

注意:

  1. 在某些情况下,您可能还需要检查WIFSTOPPED(exitstat)。详见 waitpid(2(。

  2. 如果出现错误,您可以检查 errno 以获取有关出错的更多信息。

最新更新