My program accepts many options.
And I have to write a shell script to test my program.
The shell script must run my program multiple times and every time it must pass different options and different arguments for an option.
For example:
#!/bin/bash
echo "CS111 " > testing.txt
echo "is " >> testing.txt
echo "intersting " >> testing.txt
echo "even " >> testing.txt
echo "though " >> testing.txt
echo "it " >> testing.txt
echo "is " >> testing.txt
echo "time " >> testing.txt
echo "consuming " >> testting.txt
echo "and " >> testing.txt
echo "hard " >> testing.txt
./simpsh \
--verbose \
--rdonly in.txt \
--append --wronly out.txt \
--wronly err.txt \
--command 0 1 2 sort testing
./simpsh \
--verbose\
--rdonly in.txt \
--append --wronly out.txt \
--wronly err.txt \
--command 0 1 2 sort
The first test will be executed, but then there is an error 127.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
int main(int argc, char **argv)
{
int c;
int oflag = 0;
int *fd;
int fdCount = 0;
int pipefd[2];
int p;
int verbose = 0;
while (1) {
static struct option long_options[] = {
{"append",no_argument,0,'a'},
{"cloexec",no_argument,0,'b'},
{"creat", no_argument,0,'c'},
{"directory",no_argument,0,'d'},
{"dsync",no_argument,0,'e'},
{"excl",no_argument,0,'f'},
{"nofollow",no_argument,0,'g'},
{"nonblock",no_argument, 0,'h'},
{"rsync",no_argument,0,'i'},
{"sync",no_argument,0,'j'},
{"trunc",no_argument,0,'k'},
{"rdonly",required_argument,0,'l'},
{"rdwr",required_argument,0,'m'},
{"wronly",required_argument,0,'n'},
{"pipe",no_argument,0,'o'},
{"command",required_argument,0,'p'},
{"wait",no_argument,0,'q'},
{"close",required_argument,0,'r'},
{"verbose",no_argument,0,'s'},
{"profile",no_argument,0,'t'},
{"abort",no_argument,0,'u'},
{"catch",required_argument,0,'v'},
{"ignore",required_argument,0,'w'},
{"default",required_argument,0,'x'},
{"pause",no_argument,0,'y'},
};
c = getopt_long(argc, argv, "abcdefghijkl:m:n:op:qr:stuv:w:x:y", long_options, NULL);
if (c == -1)
break;
switch (c) {
case 'a':
if(verbose)
printf("O_APPEND\n");
oflag = oflag | O_APPEND;
break;
case 'b':
if(verbose)
printf("O_CLOEXEC\n");
oflag = oflag | O_CLOEXEC;
break;
case 'c':
if(verbose)
printf("O_CREAT\n");
oflag = oflag | O_CREAT;
break;
case 'd':
if(verbose)
printf("O_DIRECTORY\n");
oflag = oflag | O_DIRECTORY;
break;
case 'e':
if(verbose)
printf("O_DSYNC\n");
oflag = oflag | O_DSYNC;
break;
case 'f':
if(verbose)
printf("O_EXCL\n");
oflag = oflag | O_EXCL;
break;
case 'g':
if(verbose)
printf("O_NOFOLLOW\n");
oflag = oflag | O_NOFOLLOW;
break;
case 'h':
if(verbose)
printf("O_NONBLOCK\n");
oflag = oflag | O_NONBLOCK;
break;
case 'i':
if(verbose)
printf("O_RSYNC\n");
oflag = oflag | O_RSYNC;
break;
case 'j':
if(verbose)
printf("O_SYNC\n");
oflag = oflag | O_SYNC;
break;
case 'k':
if(verbose)
printf("O_TRUNC\n");
oflag = oflag | O_TRUNC;
break;
case 'l':
if(optarg){
if(fdCount == 0)
fd = (int *)malloc(sizeof(int));
else
fd = (int *)realloc(fd, (fdCount + 1)* sizeof(int));
if(verbose)
printf("O_RDONLY %s\n", optarg);
fd[fdCount] = open(optarg, oflag | O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
oflag = 0;
if(fd[fdCount] == -1){
fprintf(stderr, "%s cannot be opened/created", optarg);
exit(1);
}
else
fdCount++;
}
break;
case 'm':
if(optarg){
if(fdCount == 0)
fd = (int *)malloc(sizeof(int));
else
fd = (int *)realloc(fd, (fdCount + 1)* sizeof(int));
if(verbose)
printf("O_RDWR %s\n", optarg);
fd[fdCount] = open(optarg, oflag | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
oflag = 0;
if(fd[fdCount] == -1){
fprintf(stderr, "%s cannot be opened/created", optarg);
exit(2);
}
else
fdCount++;
}
break;
case 'n':
if(optarg){
if(fdCount == 0)
fd = (int *)malloc(sizeof(int));
else
fd = (int *)realloc(fd, (fdCount + 1)* sizeof(int));
if(verbose)
printf("O_WRONLY %s\n", optarg);
fd[fdCount] = open(optarg, oflag | O_WRONLY, S_IRWXU | S_IRWXG | S_IRWXO);
oflag = 0;
if(fd[fdCount] == -1){
fprintf(stderr, "%s cannot be opened/created", optarg);
exit(3);
}
else
fdCount++;
}
break;
case 'o':
if(verbose)
printf("pipe\n");
p = pipe(pipefd);
if(p == -1){
fprintf(stderr, "The pipe wasn't made.\n");
exit(5);
}
else{
if(fdCount == 0)
fd = (int *)malloc(2 * sizeof(int));
else
fd = (int *)realloc(fd, (fdCount + 2) * sizeof(int));
fdCount = fdCount + 2;
fd[fdCount - 2] = pipefd[0];
fd[fdCount - 1] = pipefd[1];
}
break;
case 'p':
if(optarg){
if(verbose){
printf("command ");
int vi = optind -1;
for( vi = optind - 1; vi < argc && *argv[vi] != '-'; vi++)
printf("%s ", argv[vi]);
printf("\n");
}
pid_t pid = fork();
if(pid == 0){
int fdin;
int fdout;
int fderr;
int i = 0;
char **arg;
int index;
for(index = optind-1; index < argc && *argv[index] != '-'; index++, i++){
switch(i){
case 0:
fdin = atoi(argv[index]);
break;
case 1:
fdout = atoi(argv[index]);
break;
case 2:
fderr = atoi(argv[index]);
break;
default:
if(i - 3 == 0)
arg = (char**)malloc(sizeof(char));
else
arg = (char**)realloc(arg, ((i - 3) + 1)* sizeof(char));
arg[i - 3] = strdup(argv[index]);
}
}
dup2(fd[fdin],0);
close(fd[fdin]);
dup2(fd[fdout],1);
close(fd[fdout]);
dup2(fd[fderr],2);
close(fd[fderr]);
execvp(arg[0], arg);
}
else if(pid == -1){
fprintf(stderr, "The new proccess isn't created by fork()\n");
exit(6);
}
}
break;
case 'q':
break;
case 'r':
break;
case 's':
verbose = 1;
break;
case 't':
break;
case 'u':
break;
case 'v':
break;
case 'w':
break;
case 'x':
break;
case 'y':
break;
default:
fprintf(stderr, "An option is misstyped or has no argument\n");
exit(4);
}
}
exit(0);
}