Hey all,

I've been trying to build a simple c shell for assignment, and im a bit stuck.
It doing something different on my laptop to that it does on my pc :S laptop is on mint 7 pc is virtual machine on mint 8.

Im using the getcwd to get the current directory, and on my pc it worked fine, but on laptop i just get returned null.

Also on laptop when i come out of the program, it goes back to normal shell, then when i press button it goes back into program on a constant loop, and wont go out, even using ctrl c , which has baffled me a fair bit if im honest.

Heres my code

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

int main(int argc, char **argv)
{
	system("clear");
	int z =1;

    do
	{
		char *dir;
		char *user;
	
		char *progname; 
   		char *parameters;

		char *cmd, *command;
		char buffer[50], *input;

		int childstatus = 1, status;
		int cmdlen;
		pid_t child;


		user = (char *)getenv("USER");
   		getcwd(dir,50);
	
	
  		if( user == NULL )
   		{
			user == "Unknown";
   	 	}

		printf("%s@dmush ~%s $: ", user, dir);

		input = fgets(buffer, 50, stdin);
       	
		cmd = strtok(input, " ");
		command = cmd;

	
    	while(1)
    	{

			if( command == "exit") 
			{
	 			break;
			}
			else if(command == "set")
			{
	    	/*
	    	 * set an environment variable
	    	 */
	    	//setenv(parm1, parm2, true);
	   			 printf("environ var not set\n");
			}


			//Extract next part of command
			cmd = strtok(NULL, " ");

  			//Check that there is nothing else to extract
	  		if (cmd == NULL)
	  		{
				break;
	 		}

			
			childstatus = fork();
			progname = command;
    			parameters = cmd;

			if (childstatus == 0) 
			{ //if parent process is running
				wait(&status);
			}
			else
			{
				

    				int i;
     			for (i=0; i<3; i++)
     			{
         				execlp(progname,progname,parameters,(char *)0);
     			}

			}
			break;
	
   		}
 
	}while (z == 1);

    return 0;
	exit(0);
}

Thanks for any help

Recommended Answers

All 15 Replies

char *dir;
...
   		getcwd(dir,50);

Thanks for any help

Allocating some memory for dir would help a lot. The fact that it worked fine in some environment is just a pure (bad) luck.

Thanks thats sorted out my null problem!

Now just need to get the command working, when i type ls nothin happens, but when i type ls -l i get invalid command type ls --help , which leads me to think something is happening, and the problem lies within the 2nd tokenizing maybe.

when i type ls nothin happens,

Of course:

cmd = strtok(NULL, " ");

  			//Check that there is nothing else to extract
	  		if (cmd == NULL)
	  		{
				break;
	 		}

and the execlp doesn't get a chance.

but when i type ls -l i get invalid command type ls --help , which leads me to think something is happening, and the problem lies within the 2nd tokenizing maybe.

Not exactly. I mean, there are problems with tokenization, but an immediate one is due to a '\n' at the end of input.

Sorry i got rid of the null, been playing around with code for past hour, so that not in anymore.

as far as the \n at the end,
ive been trying with this

ridline = strlen(input);		//Take out \n
		if (input[ridline-1] == '\n')
             {	
			input[ridline-1] = '\0';	
		}

Ok now i have it half working, it reads in ls -l fine, but not just ls on it own, so basically a single command wont work, but a command with a parameter will ,
any ideas ? also changed it so exit and set will work using strcmp!
heres my code

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

int main(int argc, char **argv)
{
	system("clear");
	int z =1;

    do
	{
		char dir[50];
		char *user;
	
		char *progname; 
   		char *parameters;

		char *cmd, *command;
		char buffer[50], *input;

		int childstatus = 1, status;
		int cmdlen;
		pid_t child;

		int ridline;

		user = (char *)getenv("USER");
   		getcwd(dir,50);
	
	
  		if( user == NULL )
   		{
			user == "Unknown";
   	 	}

		printf("%s@dmush ~%s $: ", user, dir);

		input = fgets(buffer, 50, stdin);

			ridline = strlen(input);		//Take out new line char
		if (input[ridline-1] == '\n') {	//
			input[ridline-1] = '\0';	//
		}				//

       	
		command = strtok(input, " ");
		printf("argv0 = %s\n", command);
		
		if (strcmp(command, "exit") == 0)
		{
			z = 0;
		}

		else if(strcmp(command,"set") == 0)
			{
	    	
	    	     //set environment variable
	    	 
	    	     //setenv(parm1, parm2, true);
	   			 
			}

    	while(1)
    	{

			//Extract next part of command
			cmd = strtok(NULL, " ");
			printf("argv1 = %s\n",cmd);
			
			

			

  			//Check that there is nothing else to extract
	  		if (cmd == NULL)
	  		{
				break;
	 		}

			
			childstatus = fork();
			progname = command;
    			parameters = cmd;

			if (childstatus != 0) 
			{ //if parent process is running
				wait(&status);
			}
			else
			{
				

    				int i;
     			for (i=0; i<3; i++)
     			{
         				execlp(progname,progname,parameters,(char *)0);
     			}

			}
			
	
   		}
 
	}while (z == 1);

    return 0;
	
}

When you just type ls, your code is breaks out at line 79. Check the usage of strtok properly

I managed to get it working by removing the if cmd = null break, and just put break at end of while loop!

Now i need to get change directory working (cd) but have no idea how to do so!

any hints or lips or ideas of where i can go from here?

Managed to get just cd working, but im having trouble getting cd .. or cd (directory) working.

iv used this

if (!strcmp(command,"cd")) 
			{
				 chdir(getenv("HOME"));
			}

I've tried replace the home with cmd (the name im used for argv1)

any ideas?

Why are you not executing the cd command via excec ?

Why are you not executing the cd command via excec ?

O i wish i was, it doesn't work?? No idea why or how just doesn't

O i wish i was, it doesn't work?? No idea why or how just doesn't

By design of the OS. Each process has its own working directory; changing it in the child does not affect the parent. That's why cd is a builtin in all *nix shells.

well i got it working, using code before, i just but a break; at end of each if statement, i thouht it was blanking out because it was giving a null, it wasnt, it was doing it was meant to do just not looping back to the top of the program, break sorted it out.

#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
main()
{
    char *argv[200];
    char *argv1[50];
    char *argv2[50];
    int m,c,i=0,k,number,set=0;
    int pid,fd,pid_d;
    char *p;
    int f[2];
    char file[20];
    while(1)
    {
        if((pid=fork())==0)
        {
            for(k=0;k<200;k++)
                argv[k]=NULL;
            printf("\nAP@BESU$");
            m=0;
            do
            {
                argv[m]=(char *)malloc(sizeof(file));
                k=0;
                while((c=getchar())!=' ')
                {
                    if(c=='\n')
                        break;
                    *(argv[m]+k)=c;
                    k++;
                }
                *(argv[m]+k)='\0';
                m++;
            }
            while(c!='\n');
            argv[m]=NULL;
            number=m;
            for(k=0;k<number;k++)
            {
                if(strcmp(argv[k],">")==0)
                {
                    set=1;
                    fd=open(argv[k+1],O_WRONLY|O_CREAT,S_IRWXU);
                    close(1);
                    dup2(fd,1);
                    number=k;
                    for(i=number;i<200;i++)
                        argv[i]=NULL;
                    break;
                }
                else if(strcmp(argv[k],"<")==0)
                {
                    set=2;
                    fd=open(argv[k+1],O_RDONLY);
                    close(0);
                    dup2(fd,0);
                    number=k;
                    for(i=number;i<200;i++)
                        argv[i]=NULL;
                    break;
                }
                else if(strcmp(argv[k],">>")==0)
                {
                    set=3;
                    fd=open(argv[k+1],O_WRONLY|O_APPEND);
                    close(1);
                    dup2(fd,1);
                    number=k;
                    for(i=number;i<200;i++)
                        argv[i]=NULL;
                    break;
                }
                else
                {
                    if(*(argv[k])=='|')
                    {
                        set=4;
                        for(m=0;m<k;m++)
                        {
                            argv1[m]=(char *)malloc(sizeof(file));
                            strcpy(argv1[m],argv[m]);
                            printf("\n %s \n",argv1[m]);
                        }
                        argv1[m]=NULL;
                        for(m=k+1;argv[m]!=NULL;m++)
                        {
                            argv2[m-k-1]=(char *)malloc(sizeof(file));
                            strcpy(argv2[m-k-1],argv[m]);
                            printf("\n %s \n",argv2[m-k-1]);
                        }
                        argv2[m-k-1]=NULL;
                        if((pipe(f)==-1))
                            printf("\n  pipe  failed\n");
                        if((pid_d=fork())==-1)
                            printf("\n  fork  failed\n");
                        if(pid_d>0)
                        {
                            close(f[0]);
                            close(1);
                            dup2(f[1],1);
                            execvp(argv1[0],argv1);
                        }
                        else if(pid_d==0)
                        {
                            close(f[1]);
                            close(0);
                            dup2(f[0],0);
                            execvp(argv2[0],argv2);
                        }
                    }
                }
            }
            if(set<=3)
                execvp(argv[0],argv);
        }
        else if(pid)
            wait();
    }
}

above one is a working shell..

ap_besu your code does not compile with gcc or g++, any suggestions? It says the wait() command has to few arguments

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.