/*
* prompting shell version 1
* Prompts for the command and its arguments.
* Builds the argument vector for the call to execvp.
* Uses execvp(), and never returns.
*/#include <stdio.h>#include <signal.h>#include <string.h>#define MAXARGS 20 /* cmdline args */#define ARGLEN 100 /* token length */int main()
{
char *arglist[MAXARGS + 1]; /* an array of ptrs */int numargs; /* index into array */char argbuf[ARGLEN]; /* read stuff here */char *makestring(); /* malloc etc */
numargs = 0;
while (numargs < MAXARGS)
{
printf("arg[%d]? ", numargs);
if (fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n')
arglist[numargs++] = makestring(argbuf);
else
{
if (numargs > 0) { /* any args? */
arglist[numargs] = NULL; /* close list */
execute(arglist); /* do it */
numargs = 0; /* and reset */
}
}
}
return0;
}
int execute(char *arglist[])
/*
* use execvp to do it
*/
{
execvp(arglist[0], arglist); /* do it */
perror("execvp failed");
exit(1);
}
char *makestring(char *buf)
/*
* tim off newline and create storage for the string
*/
{
char *cp, *malloc();
buf[strlen(buf) - 1] = '\0'; /* trim newline */
cp = malloc(strlen(buf) + 1); /* get memory */if (cp == NULL) { /* or die */fprintf(stderr, "no memory\n");
exit(1);
}
strcpy(cp, buf); /* copy chars */return cp; /* return ptr */
}
/*
* forkdemo1.c
* shows how fork creates two processes, distinguishable
* by the different returnvalues from fork()
*/#include <stdio.h>
main()
{
int ret_from_fork = 1, mypid;
mypid = getpid(); /* who am i? */printf("Before: my pid is %d\n", mypid); /* tell the world */
ret_from_fork = fork();
sleep(1);
printf("After: my pid is %d, fork() said %d\n",
getpid(), ret_from_fork);
}
/*
* forkdemo2.c
* shows how child processes pick up at the return
* from fork() and can execute any code they like,
* even fork(). Predict number of lines of output.
*/
main()
{
printf("my pid is %d\n", getpid());
fork();
fork();
fork();
printf("my pid is %d\n", getpid());
}
/*
* forkdemo3.c
* shows how the return value from fork()
* allows a process to determine whether
* it is a child process
*/
main()
{
int fork_rv;
printf("Before: my pid is %d\n", getpid());
fork_rv = fork(); /* create new process */if (fork_rv == -1) /* check for error */
perror("fork");
elseif (fork_rv == 0)
printf("I am the child. my pid = %d\n", getpid());
elseprintf("I am the parent. my child is %d\n", fork_rv);
}
/*
* waitdemo1.c
* shows how parent pauses until child finishes
*/#include <stdio.h>#define DELAY 2
main()
{
int newpid;
void child_code(), parent_code();
printf("before: mypid is %d\n", getpid());
if ((newpid = fork()) == -1)
perror("fork");
elseif (newpid == 0)
child_code(DELAY);
else
parent_code(newpid);
}
/*
* new process takes a nap and then exits
*/
void child_code(int delay)
{
printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
sleep(delay);
printf("child donee. about to exit\n");
exit(17);
}
/*
* parent waits for child then prints a message
*/
void parent_code(int childpid)
{
int wait_rv; /* return value from wait() */
wait_rv = wait(NULL);
printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);
}
/*
* waitdemo2.c
* shows how parent gets child status
*/#include <stdio.h>#define DELAY 10
main()
{
int newpid;
void child_code(), parent_code();
printf("before: mypid is %d\n", getpid());
if ((newpid = fork()) == -1)
perror("fork");
elseif (newpid == 0)
child_code(DELAY);
else
parent_code(newpid);
}
/*
* new process takes a nap and then exits
*/
void child_code(int delay)
{
printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
sleep(delay);
printf("child done. about to exit\n");
exit(17);
}
/*
* parent waits for child then prints a message
*/
void parent_code(int childpid)
{
int wait_rv; /* return value from wait() */int child_status;
int high_8, low_7, bit_7;
wait_rv = wait(&child_status);
printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);
high_8 = child_status >> 8; /* 1111 1111 0000 0000 */
low_7 = child_status & 0x7F; /* 0000 0000 0111 1111 */
bit_7 = child_status & 0x80; /* 0000 0000 1000 0000 */printf("status: exit = %d, sig = %d, core = %d\n", high_8, low_7, bit_7);
}
/*
* prompting shell version 2
*
* Solves the 'one-shot' problem of version 1
* Uses execvp(), but fork()s first so that the
* shell waits around to perform another command
* New problem: shell catches signals. Run vi, press ^c;
*/#include <stdio.h>#include <signal.h>#define MAXARGS 20 /* cmdline args */#define ARGLEN 100 /* token length */int main()
{
char *arglist[MAXARGS + 1]; /* an array of ptrs */int numargs; /* index into array */char argbuf[ARGLEN]; /* read stuff here */char *makestring(); /* malloc etc */
numargs = 0;
while (numargs < MAXARGS)
{
printf("arg[%d]? ", numargs);
if (fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n')
arglist[numargs++] = makestring(argbuf);
else
{
if (numargs > 0) { /* any args? */
arglist[numargs] = NULL; /* close list */
execute(arglist); /* do it */
numargs = 0; /* and reset */
}
}
}
return0;
}
int execute(char *arglist[])
/*
* use fork and execvp and wait to do it
*/
{
int pid, exitstatus; /* of child */
pid = fork(); /* make new process */switch(pid) {
case -1:
perror("fork failed");
exit(1);
case0:
execvp(arglist[0], arglist); /* do it */
perror("execvp failed");
exit(1);
default:
while (wait(&exitstatus) != pid)
;
printf("child exited with status %d, %d\n",
exitstatus >> 8, exitstatus & 0377);
}
}
char *makestring(char *buf)
/*
* tim off newline and create storage for the string
*/
{
char *cp, *malloc();
buf[strlen(buf) - 1] = '\0'; /* trim newline */
cp = malloc(strlen(buf) + 1); /* get memory */if (cp == NULL) { /* or die */fprintf(stderr, "no memory\n");
exit(1);
}
strcpy(cp, buf); /* copy chars */return cp; /* return ptr */
}