Thread: Basic Linus Shell

  1. #1
    Registered User
    Join Date
    Sep 2010
    Posts
    8

    Question Basic Linus Shell

    SO this is my first post in this forums. Hoping to get better feedback than the others I have tried.

    I'm currently working on a project. We were assigned to do a simple linux shell in C. I have since improved the code a little, keep in mind I'm not C expert or linux expert, now using "lex" to tokenize the input from the user instead of strtok. I'm also looking to add some more functionality to the shell. I've done some google searches and such around on other forums and would like my own specific help not links to other boards.

    Now to the issue at hand. Most of my basic commands are working, the problem is the command "cd" isn't. I thought it would just work with simple execvp() command, but I guess there is more that will have to go into it. I assume it has something to do with creating the path for the desired directory and such using chdir(). I can post my code around noonish to help better understand my logic. I guess what I'm getting at is i need some direction in getting "cd <directory>" to work.

  2. #2
    Noob AnishaKaul's Avatar
    Join Date
    Jan 2010
    Location
    Gurgaon, India
    Posts
    115

  3. #3
    Registered User
    Join Date
    Sep 2010
    Posts
    8
    Check out this thread :
    [SOLVED] How to write a replacement for shell command line interpreter
    excellent. Figured out my problem. I was trying to fork and do the processesing of the cd in the child process instead of doing it as part of the shell. W00t thx. Ill try to reimplement mine. If i have any questions I'll post. Won't know till tonight.

  4. #4
    Noob AnishaKaul's Avatar
    Join Date
    Jan 2010
    Location
    Gurgaon, India
    Posts
    115
    Glad I could help you

  5. #5
    Registered User
    Join Date
    Sep 2010
    Posts
    8
    So i ran into a fundamental issue that i'm not realizing. So i had my shell running with most of my commands and low and behold my process id's weren't returning correctly. The shell work go back to the parent process before the child process was finished. Here is the code. Can anyone explain why i dont get the right process id returned at "child process finished" pid . I keep getting a -1 instead of the matching pid for "waiting for child" pid.



    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/types.h>
    
    //used for lex
    extern char **getline();
    
    int main(int argc, char *argv[], char *envp[]){
    
        int *ret_status;
        char **args;
        pid_t pid;
    
        while(1){
            printf("$ ");
    
            args = getline();
    
            if (args[0]==NULL) continue;
            if (!strcmp(args[0], "exit" )) exit(0);
            pid = fork();
            if (pid){
                printf("Waiting for child (%d)\n", pid);
                pid = wait(ret_status);
                printf("Child (%d) finished\n", pid);
            } else {
                if( execvp(args[0], args)) {
                    puts(strerror(errno));
                    exit(127);
                }
            }
        }
        return 0;
    }

  6. #6
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    You are passing an uninitialized pointer to wait(). I think you want to declare ret_status as a regular integer, then pass its pointer to the wait function.
    bit∙hub [bit-huhb] n. A source and destination for information.

  7. #7
    Noob AnishaKaul's Avatar
    Join Date
    Jan 2010
    Location
    Gurgaon, India
    Posts
    115
    Are you able to compile that code even ? It is giving me:
    conflicting types for ‘getline’
    /usr/include/stdio.h:653: note: previous declaration of ‘getline’ was here
    and then a segmentation fault !!

    and there is no nedd to decalre int *ret_status; as a pointer . you can do : int ret_status and then use as &ret_status !

  8. #8
    Registered User
    Join Date
    Sep 2010
    Posts
    8
    sorry...to compile it you need a lex.c which i didn't included with the post. You need to run the command "flex lex.c" then you will get another file called lex.yy.c then run this command to compile "gcc –o shell shell.c lex.yy.c -lfl"
    Or if not using gcc umm idk lol!

    Code:
    %{
    int _numargs = 10;
    char *_args[10];
    int _argcount = 0;
    %}
    
    WORD	[a-zA-Z0-9\/\.-]+
    SPECIAL	[()><|&;*]
    
    %%
    	_argcount = 0; 
    	_args[0] = NULL; 
    
    {WORD}|{SPECIAL} {  
    	  if(_argcount < _numargs-1) {
    	    _args[_argcount++] = (char *)strdup(yytext);
    	    _args[_argcount] = NULL;
    	  }
    	}
    
    \n	return (int)_args;
    
    [ \t]+
    
    .
    
    %%
    
    char **getline() {
      return (char **)yylex();
    }
    Last edited by Josh_Dude83; 09-19-2010 at 03:01 PM.

  9. #9
    Registered User
    Join Date
    Sep 2010
    Posts
    8
    ran into an issue with redirecting output to a file in my shell

    else if(strncmp(">", args[2], 1) == 0)

    if args[2] is null, it crashes. How else can I test for this?

  10. #10
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    check argc from int main(int argc,char *argv[]).The C Book — Arguments to main

  11. #11
    Registered User
    Join Date
    Sep 2010
    Posts
    8
    btw:
    char **args;

    using lex it's treated as an array

  12. #12
    Registered User
    Join Date
    Sep 2010
    Posts
    8
    Good I fixed that problem. A new one has risen. The following code outputs to the file, however any subsequent commands dont output to the stdout. For instance if after running in my shell, ls -l > foobar.txt, I run ls, the output for ls never appears on the stdout. Any ideas?

    Code:
                                             int orig_stdout;
    					//char *filename;
    					// Duplicate the stdout file handle and store it in orig_stdout.
    					orig_stdout = dup(fileno(stdout));
    					// This text appears on-screen.
    					// Reopen stdout and redirect it to the file.
    
    					freopen(args[3], "w", stdout);
    
    					// This text appears in the file.
    
    					pid = fork();
    
    					if (pid)
    					{
    						pid = wait(&ret_status);
    					}else
    					{
    						//format execlp input
    						strncat(args[1], "\0", 1);
    
    						if(execlp(args[0], args[1], NULL))
    						{
    							puts(strerror(errno));
    							exit(127);
    						}
    
    					}
    
    					// Close the redirected stdout.
    					fclose(stdout);
    					// Restore the original stdout and print to the screen again.
    					fdopen(orig_stdout, "w");
    					printf("I'm back writing to the original stdout.\n");

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. basic shell command execution
    By Opel_Corsa in forum Linux Programming
    Replies: 4
    Last Post: 10-20-2006, 08:37 AM
  2. shell script basic question
    By PedroTuga in forum Linux Programming
    Replies: 1
    Last Post: 09-09-2006, 03:24 AM
  3. A basic shell question
    By AngKar in forum C# Programming
    Replies: 1
    Last Post: 06-20-2006, 05:18 PM
  4. Basic Shell Script-Very Frustrating
    By kwigibo in forum Linux Programming
    Replies: 8
    Last Post: 05-19-2002, 02:43 AM