Writing a small shell program

in C. This is the start of the semester and my course is called Operating Systems. I have a HUGE project due at the end of the semester, but first I need to get my basics right. How exactly am I supposed to write a shell program (in C) and then create a process. Detailed answers or useful web links (possibly with some examples) would definitely help.
PS: This is NOT the project itself. I am just trying to get started on the right foot. I am new to this stuff and need some specific guidance (the course happens to be online)
Get a C compiler.

Write some C code. This will do to start you off:

1
2
3
4
int main()
{
return 0;
}


The code should be a plain text file. Now compile your code using the C compiler. You now have an executable program you can run from the shell.
I sure hope you're using a POSIX compliant Unix for this kind of work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    pid_t pid; // integer that can store a process ID (use pid_t for portability)

    if ((pid = fork()) == -1) // system functions also set a variable called "errno"
    {
        perror("fork"); // this function automatically checks "errno"
        // and prints the error plus what you give it
        return EXIT_FAILURE;
    }
// ---- by when you get here there will be two processes
    if (pid == 0) // child process
    {
        // look up exec functions
    }
    else // parent process
    {
    }

    return EXIT_SUCCESS;
}


You can't use exec() directly without a fork because the new program will "take over" the original one from that point. You can however use popen() or system().

Sites:
http://www.cs.cf.ac.uk/Dave/C/
http://linux.die.net/
http://www.advancedlinuxprogramming.com/


Have fun error-checking in C!
Catfish, thank you for your reply. I have the same example on forking in my book. What compiler would you use for that. Since it is a C program, I could use any C compiler like Turbo C, right? An option that our instructor gave us was doing it on a Linux server located in our school. We had to use putty and everything to gain access to it. But I get a ton of errors there. It's like it doesn't recognize C language at all. Your input would be greatly appreciated.
No, you can't use "any C compiler". You need to be sure the compiler you use has the needed capabilities.

If you need to use POSIX functions then look inside your compiler's include folder. If it doesn't have some header files like unistd.h, errno.h and signal.h and a directory sys, then it's probably not capable of compiling my example, and if so, many examples in your book.

The compiler which I'd use would be GCC (GNU C Compiler).

How do you get to use GCC? Options are:
1) Get a Linux LiveCD (almost all of them have it preinstalled)
2) Get Cygwin (simulates Linux, on Windows)
3) Get MinGW (it's the Windows port of GCC and other tools)
4) Get old DJGPP (it's the MS-DOS port of GCC and other tools)

I'd recommend Linux because it's the natural environment for C, in my opinion. Historically C and Unix have been bundled together... and Linux is just a modern version of Unix.
Definitely! I will definitely give it a shot. I don't want to archive this forum yet, I think there is lot of I could learn from here. Looking forward to hearing more from you. My project progress report will be up shortly, on the same forum.

Thanks again.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>

//This method looks up the input command against the lookup for 
//validity purposes
bool FunctionLookUp(char *argv, char *Lookup[])
{
	bool match = false;
	for(int i = 0; i < 10; i++){
		if(*Lookup[i] == *argv){
			match = true;
			break;}
	}
	return match;
}
void  parse(char *line, char **argv)
{
     while (*line != '\0') {       /* if not the end of line ....... */ 
          while (*line == ' ' || *line == '\t' || *line == '\n')
               *line++ = '\0';     /* replace white spaces with 0    */
          *argv++ = line;          /* save the argument position     */
          while (*line != '\0' && *line != ' ' && 
                 *line != '\t' && *line != '\n') 
               line++;             /* skip the argument until ...    */
     }
     *argv = '\0';                 /* mark the end of argument list  */
}

bool CheckForwardSlash(char temp[], int size)
{
      bool present = false
      for(int i = 0; i < size; i++){
          if(temp[i] == '/'){  
           present = true;
           break;
           }
      }
      return present;
}
void  execute(char **argv)
{
     pid_t  pid;
     int    status;
     
     if ((pid = fork()) < 0) {     /* fork a child process           */
          printf("*** ERROR: forking child process failed\n");
          exit(1);
     }
     else if (pid == 0) {          /* for the child process:         */
          if (execvp(*argv, argv) < 0) {     /* execute the command  */
               printf("*** ERROR: exec failed\n");
               exit(1);
          }
     }
     else {                                  /* for the parent:      */
          while (wait(&status) != pid)       /* wait for completion  */
               ;
     }
}

  
void  main(void)
{
     char  line[1024];                         // The input line                 
     char  *argv[3];                           // An array of pointers to the tokens (the tokens were parsed 
											   // from the input line)
     bool check1, check2 = false;

	 //A look-up table that contains some of the valid commands
	 char *LookUp[11] = {"emacs", "kill", "bye", "jobs", "fg", "chmod", "cd", "help", "cat", "cp"};
     
     while (1) {                              // repeating....         
          printf("tish >> ");                 // the prompt             
          gets(line);                         // read in the command line     
          printf("\n");
          parse(line, argv);                  // parse the line  
       
          if (strcmp(argv[0], "bye") == 0)    // exit if the user enters bye
               {exit(0);}  

					  //Input Validation//
					  ///////////////////

          //If the input is just a white space character, continue with the next iteration of the loop
          if (isspace(argv[0]))
           continue;    //If it is some sort of a white-space character, 
						//skip the current iteration of the while loop
	  
			
          //Call a function that checks for the validity of the input command
		  check2 = FunctionLookUp(argv, LookUp);
		  if(check2 == false){
			  fprintf("Invalid Command\n");
			  continue;
		  }

          //Test argv[0] for invalid internal commands. Check for Letters and Negative numbers.
          if(strcmp(argv[0], "kill") == 0){
           if(isaplha(argv[1]) || atoi(argv[1]) < 0){
           fprintf("Invald PID entered");
           fprintf("Enter a positive numeric number");
           continue;
           }
           }
           
                                                     
        
         int size = sizeof(argv[1]) + 1;
         char temp[size];
		 strcpy(temp,agrv[1]);
         check1 = CheckForwardSlash(temp, size);
		 //If true is returned by the CheckForwardSlash method, skip the rest of the while loop
         if(check1 == true){                
         printf("Invalid file format\n");
         printf("Avoid Forward Slashes in your file name\n");
         continue;
         }  

					  //Input Validation Ends//
        ///////////////*********************//////////////////

		//Signals to catch the Ctrl-C and Ctrl/ combination
        signal(SIGINT, SIG_IGN);       	        //The instructions said to ignore the SIGINT signal
        signal(SIGTERM, SIG_DFL);               //SIGTERM signal must be caught. 
        execute(argv);                          //Finally, execute the command
     }
}
Last edited on
Topic archived. No new replies allowed.