Examples: pipesize.c
#include
#include
main(){
printf("PIPE BUF SIZE is =%d\n", PIPE_BUF);
}
popen
- FILE *popen(char *cmd, char *type);
- popen pipes/forks/sets up pipe/ execs cmd
- Examples/popen.c
#include
main(){
FILE *fp, *popen();
char str[1024];
fp = popen("date","r");
fgets(str, 1024, fp);
fprintf(stdout, "%s", str);
}
- Implementation
FILE *popen(cmd, mode)
char *cmd, *mode;
{
FILE *fp, *fdopen();
int pfd[2];
int pid;
if(pipe(pfd) < 0) fatal("Pipe failed");
if(*mode == 'r'){
if((pid = fork()) < 0){ fatal("Fork failed");
}else if (pid == 0){
close(pfd[0]);
close(1);
if(dup(pfd[1]) != 1) fatal("Dup returned non STDOUT");
execlp(cmd, cmd, NULL);
fatal("Exec failed");
}else{
if((fp = fdopen(pfd[0],"r")) == NULL) fatal("Fdopen failed");
return(fp);
}
}else if(*mode == 'w'){
}else{
fatal("popen mode must be 'r' or 'w'");
}
}
I/O redirection in Shells
- <
- >
- >>
- |
- > & (in bash 2>)
Multiple Pipes
- Handling "ls -l | grep "^d" | sort
- How many processes? How many forks?
- Who should quit first?
- Who is the child of the shell?
Example sh.pipe.pseudo
typedef struct wordnode{
char *word;
struct wordnode *link;
} WORDLIST;
exec_cmd_with_pipes(cmd)
WORDLIST *cmd;
{
WORDLIST *cmd1;
char *myargv[ARGSIZE];
int status, pid, pfd[2];
- search cmd for pipe symbol
- if no pipe symbol
- set up myargv
- execute myargv with myenv
- if found; find last pipe and break cmd into cmd and cmd1
- pipe
- fork
- remap stdout of child; recursive call
- remap stdin of parent; execve (myarg, myenv)
/* Somewhere in main command loop */
... if((pid = fork()) < 0) fatal("P0 Can't fork");
... if(pid == 0) execute_with_pipes(command);
else if(!backgroundflag) wait(&status);
* set pipeflag */
...
if (pipeflag == 0){ /* Simple case */
...
} else { /* Pipe joining cmd and cmd1 */
if(pipe(pfd) < 0) fatal("Mysh can't create");
if((pid = fork()) < 0) fatal("Mysh Can't fork");
if (pid == 0){ /* P2 code */
- close stdout
- map stdout to the pipe
- close extra fd
- recursive call
} else { /* P1 Code */
- close stdin
- map stdin to the pipe (dup pfd[0])
- close extra fd
- execute cmd1 after putting in argv form
}
}
}
.setup file handling:
FILE *infp;
infp = fopen(...)
read and process cmds until end of file
if infp == stdin exit
else set infp = stdin and repeat
Review of transformations
- read-line from fp
- parse line into wordlist
- substitutions
- history
- variable
- filename expansion
- command substitution
- alias
- remapping I/O
- >
- <
- >>
- >& or 2>
- pipes
- set flags saving filenames for redirection
- exec_cmd_with_pipes
- find rightmost pipe, break into cmd and cmd1
- pipe, fork
- In Child recursively call exec_cmd_with_pipes(cmd1)
- In Parent execute(cmd) remapping stdin to pipe
Example lsl $d !37:4 *.c | sort -u | wc -l > out
Old Signals Overview
- signal table
- signals sent
- signals received
- catching, masking, blocking
- SIGINT ^C usually
- stty command
- SIGQUIT ^\ usually
/usr/include/signal.h
Signal Table
Processing with signals
- signal(SIGnum, myfunc) to set up entry in table, return value is ...
- When a SIGnum signal is received, consult table to get myfunc
- call myfunc as an interrupt service routine
- after myfunc return to next instruction
SIG_DFL and SIG_IGN
Signal system call
#include
void (*signal(
int sig,
void (*function) (int))) (int);
When to catch signals?
Example: graceful.c
#include
#include
main(){
int onint(); /* SIGINT handler */
int i;
signal(SIGINT, (void *) onint);
signal(SIGQUIT, (void *) onint);
for(i=0; ;i++)
fprintf(stdout,"%d\n",i);
}
int
onint(int sig){
fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig);
fprintf(stdout,"STDOUT:Recieved SIGNAL NUMBER =%d\n", sig);
/*
* Graceful exit type things removing temporary files etc.
*/
exit(1);
}
The kill system Call - kill(pid_t pid, int sig)
abort, alarm
Setjmp, Longjmp