alltime |
04-15-2005 04:03 PM |
Okay, below is some code that I am trying to write:
Code:
#include <linux/limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#define DEBUGON 0
#define DEBUGOFF 1
const char my_prompt[] = "(***SHELL***)";
void parse(char *line, char **argv)
{
/* While we are not at the end of the line */
while (*line != '\0') { /* if not the end of line ....... */
/* If line is space tab or newline */
while (*line == ' ' || *line == '\t' || *line == '\n')
/* Replace with whitespace */
*line++ = '\0';
*argv++ = line;
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
line++;
}
*argv = '\0';
}
void execute(char **argv)
{
pid_t pid;
int i, ai;
int fout;
int fin;
char **mycmd;
int status;
int fd[2];
strcpy(*mycmd, *argv);
if ((pid = fork()) < 0) {
/* Execute process */
printf("errno is %d\n", errno);
exit(1);
}
else if (pid == 0) {
/* Go through the string */
for(i=0; argv[i] != NULL; i++){
/* -----------------------------------------------If we reach > */
if(!strcmp(argv[i], ">")){
/* Replace > with a 0*/
argv[i] = '\0';
printf("I found a > \n");
/* If the next character is Null */
i++;
if(argv[i] == NULL){
/* Print error for wrong syntax */
printf("ERROR > usage: program > file ");
break;
}
if ((fout = open(argv[i], O_CREAT | O_WRONLY, 0666)) < 0){
printf("Unable to create target file, check permissions\n");
}
/* Make STDOUT the file */
if(dup2(fout, 1) == -1){
printf("ERROR errno is: %d\n", errno);
}
}
/* -----------------------------------------------If we reach < */
if(!strcmp(argv[i], "<")){
/* Replace > with a 0*/
argv[i] = '\0';
/* If the next character is Null */
i++;
if(argv[ai] == NULL){
/* Print error for wrong syntax */
printf("ERROR < usage: program < file ");
break;
}
/* make file name to outfile */
if ((fin = open(argv[i], O_RDONLY, 0666)) < 0){
printf("Unable to open file for reading, check permissions\n");
}
/* Make STDOUT the file */
if(dup2(fin, 0) == -1){
printf("ERROR errno is: %d\n", errno);
}
}
/* -----------------------------------------------If we reach | */
if(!strcmp(argv[i], "|")){
argv[i] = '\0';
if(-1 == pipe(fd)){
perror("pipe error");
exit(1);
}
if((pid = fork()) < 0){
perror("fork error");
exit(1);
}else if (pid){
/* Make STDOUT the same as fd[1] */
if (-1 == dup2(fd[1], STDOUT_FILENO)){
perror("dup2 error on first process");
exit(1);
}
/* Unecessary to have open */
close(fd[0]);
/* Begin the first process */
if (execvp(*argv, argv)){
perror("execvp failure on first process");
exit(1);
}
}else{
if(-1 == dup2(fd[0], STDOUT_FILENO)){
perror("dup2 error on second process");
exit(1);
}
/* Unecessary to have open */
close(fd[1]);
/* Begin the second process */
if (execvp(argv[i+1], &argv[i+1])){
perror("execvp failure on second process");
exit(1);
}
}
}
}
/* -----------------------------------------------Now exec */
if (execvp(*argv, argv) < 0) {
/* Execvp should return value < 0 if command execution fails */
printf("%s: %s\n", *argv, "command not found\n");
exit(1);
}
/*------------------------------------ Wait for processes to finish */
}
else {
/* Parent waiting for program to finish */
while (wait(&status) != pid);
}
}
int main(int argc, char* argv[])
{
char line[256];
char linecopied[256];
char linecopied2[256];
char cmd[sizeof(line)], *args;
int i;
int linelen;
system("clear");
while (1)
{
/* Prints out my prompts */
printf(my_prompt);
/* Get the users line STDIN */
if(fgets(line, sizeof(line), stdin) == NULL) continue;
printf("lines is %s\n", line);
/* Copy the line to linecopied */
strcpy(linecopied, line);
strcpy(linecopied2, line);
printf("linecopied is %s\n", linecopied);
/* Return the lenght of the line */
linelen = strlen(line);
/* Remove end of line character from string */
if(line[linelen-1]=='\n') line[linelen-1]='\0';
cmd[0] = '\0';
args = line + strlen(line);
/* Scan users input */
sscanf(line, "%s ", cmd);
for(i=strlen(cmd); i<linelen; i++){
args = line+i;
/* If does not return */
if(!isspace(args[0]))break;
}
/* Print the command */
printf("cmd = \"%s\"; args = \"%s\"\n", cmd, args);
/* If the command is change directories */
if(strcmp(cmd, "cd") == 0){
/* If we cannot change directories return error changing */
if(chdir(args)<0)
perror("Error changing directory");
continue;
}
/* If the command is pwd */
if(strcmp(cmd, "pwd")==0){
char curdir[PATH_MAX];
/* Use getcwd to print the current directories */
if(getcwd(curdir, sizeof(curdir))!=NULL)
{
printf("%s\n", curdir);
}
/* If pwd fails, print error */
else
perror("Error calling getcwd");
continue;
}
/* If the command is umask */
if(strcmp(cmd, "umask")==0){
mode_t mode;
int r;
if((r=sscanf(args, "%o", &mode) == 1))
{
umask(mode);
}
else
{
fprintf(stderr, "umask: argument missing!\n");
}
continue;
}
/* If the command is exit */
if(strcmp(cmd, "exit") == 0){
/* Break */
exit(1);
}
/* If the command is clear */
if(strcmp(cmd, "clear")==0){
system("clear");
continue;
}
printf("command cmd:%s\n", cmd);
/* Parse the copied users input */
parse(linecopied, argv);
/* Execute the users command */
execute(argv);
}
printf("Exited normally\n");
return 0;
}
In case anyone asks, the reason why I replaced | \0 at argv[i] = '\0'; is because execvp reads until null and executes everything untill null.
The problem is that I need to get everything on the other side of the | (now NULL) so that it can be executed in the area under the comments saying "second process".
The program will eventually be run like this (example): gcc myfile.c | uname
|