Solved

Created my own shell need help processing a sequence of commands/programs separated by ";"

Posted on 2006-06-17
6
299 Views
Last Modified: 2010-04-15
Ok i have created my own shell but i am having trouble creating it to process a sequence of commands/programs separated by ";"

This is sofar what i have could you please just tell me what to add to my code to make this work?

#include <stdio.h>
#include <string.h>
#include <unistd.h>

pid_t myFork();
int readArgs(const char*,char*[]);


int main (int argc, char *argv[]){
      pid_t pid;
      char line [255];
      char *argList[20];
      int ampersand, status, i;

      printf ("This program executes commands and \n");
      printf ("progams for you \n");

      while(1){
        printf ("To exit, enter CTR-C, or enter\n");
        printf ("a program name with its arguments> ");
        fgets(line,255,stdin);
        ampersand=readArgs(line,argList);
      if ((pid = myFork ()) == -1){
         perror("impossible to fork");
        exit(1);
      }
      
      if (pid>0)       //This is the parent
        if (ampersand) //Background execution
            printf("Process [%d]\n", pid);
        else{
            waitpid(pid, &status,0);
            printf("My child has terminated\n");
      }
        else            //this is the child
            if (execvp(argList[0], argList)==-1){
            perror("child Process");
            exit(22);
        }
      }
      exit(0);
}


pid_t myFork(){
      static int count=0;

      count++;
      if (count<=20)
        return(fork());
      else
        return(-1);
      }

int readArgs(const char *line, char *argList[]){
      static int yes=0;
      int i=0, offset=0;
      char name[50];
      int found=0;

      while (yes & argList[i] !=NULL)
        free(argList[i++]);
      i=0;            //reset i to ZERO
      while(sscanf(line+offset, "%s", name)==1){
            argList[i] = (char *)malloc(strlen(name)+1);
            strcpy(argList[i++],name);
            
            while(line[offset]==' ') offset++;  //skip blanks
            offset += strlen(name);
      }
      if (!strcmp(argList[i-1], "&")){
            argList[i-1] = NULL;
            found = 1;
      }
      else{
            if (argList[i-1][strlen(argList[i-1])-1]=='&'){
              argList[i-1][strlen(argList[i-1])-1]='\0';
              found = 1;
            }
            argList[i] = NULL;
      }
      yes=1;
      return(found);      
      }

Thanx
0
Comment
Question by:dush_1986
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
6 Comments
 
LVL 14

Expert Comment

by:cwwkie
ID: 16927558
first something else;

>     static int yes=0;

>     while (yes & argList[i] !=NULL)
>       free(argList[i++]);

I asume you do this because you got errors the first time you free argList? It is better to initialize argList before you use it.

     char *argList[20];
     ...
     argList[0]=NULL;
0
 
LVL 14

Accepted Solution

by:
cwwkie earned 100 total points
ID: 16927565
> to process a sequence of commands/programs separated by ";"

there are diffent ways to do that, but I think it is the easiest if you use strtok to split the string (http://cplusplus.com/ref/cstring/strtok.html), and than process each substring the usual way.
0
 

Expert Comment

by:sibtay
ID: 16988354

I started to debug your program and ended up in writing a new one :-) In the following program "input" variable in main() represents the format which you are trying to parse (i am not mistaken).

The general idea is that in the main program tokenize my input on ";". Hence each token will represent a program name and its respective arguments which will be taken care by construct_cmd function.
Each command is represented by a Command struct. Which is the output of construct_cmd function. A Command Struct contains all what your program needs i.e. program name, its arguments and a boolean
idicating whether it should run in background or not.

Have a look at it. If you dont understand feel free to ask.

typedef enum bool
{
      false,
      true
}bool;

typedef struct
{
      char      *cmd_name;
      char      **args;
      int      nargs;
      bool      run_in_bg;      
}Command;

void free_cmd(Command *cmd2free);
void print_cmd(Command *cmd2print);
Command *construct_cmd(const char *cmd);

int main(int argc, char *argv[])
{
      char            *input = strdup("prog p1_o1 p1_o2 p1_o3 &;     prog2 p2_o1 ; prog3; prog4 &");
      char            *buf;
      char            *str;
      Command      *cmds[10];
      int            i = 0;
      char            *tok;
      int            ncmds = 0;

      // create a modifiable copy of input
      str = strdup(input);

      tok = strtok_r(str, ";", &buf);

      for (i = 0; tok != NULL; i++)
      {
            cmds[i] = construct_cmd(tok);
            tok = strtok_r(NULL, ";", &buf);
      }

      ncmds = i;

      // print all cmds

      for (i = 0; i < ncmds; i++)
            print_cmd(cmds[i]);

      // free all cmds
      for (i = 0; i < ncmds; i++)
            free_cmd(cmds[i]);

      free(str);
      free(input);

      return 0;
}

Command *construct_cmd(const char *cmd_str)
{
      char      *tok;
      char      *buf;
      int      nalloc = 2;
      char      **cmd_args;
      int      i = 0;

      Command *cmd = (Command *)malloc(sizeof(Command));
      memset(cmd, 0, sizeof(Command));

      cmd_args = (char **)malloc(nalloc * sizeof(char *));
      
      // create a modifiable copy of cmd
      char      *str = strdup(cmd_str);

      // a command is given as <prog_name> <option_list>
      // so now tokenize str on the basis of spaces

      tok = strtok_r(str, " ", &buf);
      
      // first token is always the program name
      cmd->cmd_name = strdup(tok);
      
      // the rest are its arguments
      tok = strtok_r(NULL, " ", &buf);
      while (tok != NULL)
      {
            // special case
            if (strcmp(tok, "&") == 0)
                  cmd->run_in_bg = true;
            else
            {
                  if (i == nalloc)
                  {
                        nalloc *= 2;
                        cmd_args = (char **)realloc(cmd_args, nalloc * sizeof(char *));
                  }

                  cmd_args[i++] = strdup(tok);
            }

            tok = strtok_r(NULL, " ", &buf);
      }

      cmd->nargs = i;

      if (cmd->nargs > 0)
      {
            // deallocate extra cmd_args elements
            for (i = i; i < nalloc; i++)
                  free(cmd_args[i]);

            cmd->args = cmd_args;
      }

      free(str);

      return cmd;
}

void print_cmd(Command *cmd2print)
{
      int      i;
      
      printf("===Command===\n");
      printf("Name = %s\n", cmd2print->cmd_name);
      printf("Nargs = %d\n", cmd2print->nargs);
      printf("RunInBg = %s\n", cmd2print->run_in_bg==true?"true":"false");

      for (i = 0; i < cmd2print->nargs; i++)
            printf("arg[%d] = %s\n", i, cmd2print->args[i]);
      
      printf("=============\n");
}

void free_cmd(Command *cmd2free)
{
      int      i;
      
      free(cmd2free->cmd_name);

      for (i = 0; i < cmd2free->nargs; i++)
            free(cmd2free->args[i]);

      free(cmd2free->args);
      free(cmd2free);
}
0
 
LVL 14

Expert Comment

by:cwwkie
ID: 16995079
sibtay,

you should not give full answers to homework questions (see http://www.experts-exchange.com/help.jsp#hi130)
But there is no problem helping and guiding to an answer.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Test against App 49 139
Read file descriptor 3 in C 14 128
Linux context switch  - loop takes long time to process 6 154
Why is compiler in oracle server ? 9 110
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.
Suggested Courses

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question