每次孩子处理时,我的情况是输出打印“p2:”。
当我输入命令行“echo NULL; echo void”时。我的parse()将拆分每个单词并使用getword()函数分配给* newargv []。 getword(char * w)基本上是在命令行中分割每个单词。在我的情况下,“;”被视为换行符。 Getword(char * w)在遇到分号时会返回'\ 0'。
运行程序时的输出。 p2:echo NULL; echo void 空值 空虚 p2:p2:
我认为需要刷新输出缓冲区并尝试fflush(stdout)。但它不起作用。
这是我的p2.c和p2.h
#include <stdio.h>
#include "p2.h"
#define MAXITEM 100 /* max number of words per line */
int BGFLAG = 0, INFLAG = 0, OUTFLAG = 0, AMFLAG = 0, SEMIFLAG = 0, PIPEFLAG = 0;
char argv[255]; //this array get a string from getword function
char *newargv[MAXITEM]; //this pointer array will keep the first character of argv array
char *in, *out; //pointers point to file in argv
int sizeC = 0; //check if it is EOF or not
int parse();
int main()
{
int argc;
signal(SIGTERM,myhandler);
for (;;)
{
printf("p2: ");
pid_t pid, child_pid;
int status;
//call parse function
argc = parse();
if (sizeC == -1)
break;
if (argc == 0) //reissue prompt if line is empty
continue;
if (newargv[0] == NULL){
fprintf(stderr, "Invalid command");
continue;
}
child_pid = fork();
if (child_pid < 0){
printf("ERROR! can't fork\n");
exit(1);
}
else if(child_pid == 0){ //return a new child process
execvp(*newargv,newargv);
printf("ERROR exec failed\n");
exit(1);
}
else {
pid = wait(NULL);
if (pid == child_pid)
continue;
}
}//end for
killpg(getpgrp(),SIGTERM);
printf("p2 terminated. \n");
exit(0);
}// main
int parse()
{
int p = 0;
//this pointer will keep track the argv array for each of loops
//the getword function will not overwrite the argv array
int ptr = 0;
int count = 0;
SEMIFLAG = 0;
int wCount = 0; //return the number of argc
int semiColon = 0;
/* Read from stdin to argv array. The ptr will keep track the argv array
If it is meta character, set a flag appropriately. Otherwise,
set the address of first char of argv to the newargv*/
while ((sizeC = getword(argv + ptr)) > 0)
{
if(sizeC == 0){
semiColon++;
continue;
}else{
//Put the address of first char of each argv to the pointer array
newargv[p] = argv + ptr;
p++;
}
argv[ptr + sizeC] = '\0';
//point to the next address of next word in argv, the getword will not overwrite the argv array
ptr = ptr + sizeC + 1;
wCount++;
}//end while
newargv[p] = NULL;
return wCount;
}//end parse
void myhandler(){
}//end myhandler
这里是p2.h
#include <stdio.h>
#include "getword.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <signal.h>
#define MAXITEM 100
int parse();
void myhandler();
这里是getword.c和getword.h
#include <stdio.h>
#include "getword.h"
int getword(char *w)
{
int count = 0; //represent how many characters are read
char iochar;
int flag = 0; // identify a pair of single quote
//set an infinite loop
while (1)
{
iochar = getchar(); //This variable stores a character from stdin
/* If the array is full, the character will put back for next call.
Return (STORAGE -1) characters*/
if (count >= (STORAGE -1))
{
ungetc(iochar,stdin);
w[count] = '\0';
return count;
}
/* This block code will eleminate the leading tab */
if (iochar == '\t') //ignore the tabs if it counters
continue;
/* Identify if the function hit EOF */
if (iochar == EOF)
{
/* Return an empty string and -1 for size of string array
Because the EOF put back when count > 0 and the getword() encounters right away at next call
Therefore, the count is 0.*/
if (count == 0)
{
w[count] = '\0';
return -1;
}
/* The getword() read some characters before hitting EOF
Set a null terminator to finish a string array.
Return the size of string array.
Put the EOF back to stdin for next call
to print the EOF*/
if (count > 0)
{
w[count] = '\0';
ungetc(iochar,stdin);
return count;
}
}
/* For backslash case, treat all metacharacter
and space character as a normal character
The ";" and newline char will not effect meaning of that newline
*/
if (iochar == '\\')
{
//identify next character is meta-char,
//or normal char or a single quote
char nextC = getchar();
/* Only put a meta-character or space into the array
the blackslash is ignored
flag = 0 means the SINGLE QUOTE MOD is OFF*/
if ((nextC == '\'' || nextC == '!' || nextC == '>' ||
nextC == '&' || nextC == ' ' || nextC == '\\' || nextC == '\t')
&& flag == 0)
{
w[count++] = nextC;
continue;
}
/* As in a pair of single quote
slash and meta char both put in the array
flag = 1 means the SINGLE QUOTE MOD is ON.
The metacharacter and backslash are treat as normal char*/
else if ( (nextC == '!' || nextC == '>' ||
nextC == '&' || nextC == ' ' || nextC == '\\' || nextC ==';')
&& flag == 1)
{
w[count++] = iochar;
w[count++] = nextC;
continue;
}
//the single quote character in a pair of single quote
//treat as a normal character
else if (nextC == '\'' && flag == 1)
{
w[count++] = nextC;
continue;
}
//return the string if it encounters new line
//put nextC back to stdin for next call
//because we need to print out to determine the new line exist
else if (nextC == '\n' || nextC == ';')
{
w[count] = '\0';
ungetc(nextC,stdin);
return count;
}
else
//the normal character is put into the string array
{
w[count++] = nextC;
continue;
}
}// end if blacknextC
/* Identify Space case
Treat a space char as a normal char if it's in a pair of single quotes.
Treat a space char as a delimeter if it's not in a pair of single quotes*/
if (iochar == ' ')
{
if (flag == 1) //SINGLE QUOTE MOD is ON
{
w[count++] = iochar; //space is treat as normal character instead of a delimeter
continue;
}
else if (count == 0)//ignore if it is leading char or space char
continue;
else
{
/*Set a null delimeter and return the size of the array
This case space is a delimeter*/
w[count] = '\0';
return count;
}
}// end if space
/* This block of codes will identify the single quote case*/
if (iochar == '\'')
{
//read the character after single quote to determine
//it is a newline or normal character or metacharacter
char c = getchar();
/* Detect the open quote
If it is not newline or delimeter char, put it back to stdin for next call
and move on*/
if (flag == 0 && (c != '>' || c != '<' || c != '!' || c != '&'
|| c != '|' || c != ' ' || c != ';' || c !='\n'))
{
flag = 1;
ungetc(c,stdin);
continue;
}
/* Detect the closed quote. Set flag on.
Put the character back to stdin and move on*/
else if (flag == 1 && (c != '>' || c != '<' || c != '!' || c != '&' || c != '|' || c != ' ' || c != ';' || c !='\n'))
{
//Set single quote mod back to normal(OFF) (flag = 0)
//get the character back to stdin for next call to read as normal character
flag = 0;
ungetc(c,stdin);
continue;
}
/* if it hit a new line, set a null delimeter to terminate the array
return size of the string array.
the newline char is put back to stdin to print out nextcall*/
else
{
w[count] = '\0';
ungetc(c,stdin);
return count;
}
}//end if single quote
/* This code handle when the character is meta-character
It is considered as a delimeter character */
if (iochar == '>' || iochar == '<' || iochar == '!'
|| iochar == ';' || iochar == '\n' || iochar == '&' || iochar == '|')
{
/* Special character ">!"
Need to read next character to identify "!" */
if (iochar == '>')
{
char c = getchar();
/* return the string if is "!". It becomes a delimeter
put two characters back to stdin for next getword() call.
Return the size of string array before the special char*/
if ( c == '!' && count > 0)
{
w[count] = '\0';
ungetc(c,stdin);
ungetc(iochar,stdin);
return count;
}
//Return size and the special character ">!"
if (c == '!' && count == 0)
{
w[count++] = iochar; //iochar = ">"
w[count++] = c; //c = "!"
w[count] = '\0';
return count;
}
/* Put c and iochar back to stdin for next call
make sure in order, ">" need to be read first to print out the ">" char
The delimeter is only ">". Return the size of string array before ">"*/
if ( c != '!' && count > 0)
{
ungetc(c,stdin);
ungetc(iochar,stdin);
w[count] = '\0';
return count;
}
//put the ">" in to the array
//make sure put the non-"!" back to stdin for next call
//Return the meta-character ">" and size = 1
if ( c != '!' && count == 0)
{
ungetc(c,stdin);
w[count++] = iochar;
w[count] = '\0';
return count;
}
}
/* This code identify when the character is a new line "\n" or ";" */
if (iochar == '\n' || iochar == ';')
{
if (count == 0) // return an empty string
{
w[count] = '\0';
return 0;
}
/* Return a string array after newline
Put newline back to stdin for next call
to print out*/
if (count > 0)
{
w[count] = '\0';
ungetc(iochar,stdin);
return count;
}
}
/* This code block handle the rest of the metacharacter.
Return the size of 1 and that metacharacter if count = 0.
Set null delimeter and return string array before the metacharacter.
Put the metacharacter back to stdin for next call to print out.*/
if (iochar == '<' || iochar == '!' || iochar == '&' || iochar == '|')
{
//return the delimeter and size of 1.
if (count == 0)
{
w[count++] = iochar;
w[count] = '\0';
return count;
}
/* Set null delimiter to and return size of 1 and string array.
put the meta-character back to stdin for next call to get the meta-character */
if (count > 0)
{
w[count] = '\0';
ungetc(iochar,stdin);
return count;
}
}
}//end if meta case
/* After handling all situation, this character is normal.
Put the normal character to the string array */
w[count++] = iochar;
}//end while
}// getword
getword.h
#include <stdio.h>
#include <string.h>
#include <strings.h>
#define STORAGE 255
/* This is one more than the max wordsize that getword() can handle */
int getword(char *w);
答案 0 :(得分:0)
以下代码:
现在代码:
#include <stdio.h> // perror(), printf()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <unistd.h> // execvp(), fork(), pid_t
#include <sys/types.h>
#include <sys/wait.h> // waitpid()
char **parse( void );
int main( void )
{
for (;;)
{
printf("p2: ");
//pid_t pid;
pid_t child_pid;
//int status;
//call parse function
char **argv = parse();
child_pid = fork(); //fork a child process
if(child_pid < 0)
{ // then error occurred
perror( "fork failed" );
//printf("ERROR: can't fork! exec failed\n");
//exit(1);
exit( EXIT_FAILURE );
}
else if (child_pid == 0)
{ // then child process
execvp( argv[0], argv );
perror( "execvp failed" );
exit(1);
}
else
{ // parent process
int status;
waitpid( child_pid, &status, 0);
}
}//end for
}// main