Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/forums/c/)
-   -   trying to use strtok for CL shell (http://www.go4expert.com/forums/trying-strtok-cl-shell-t5013/)

ohaqqi 30Jun2007 21:53

trying to use strtok for CL shell
 
Hi everybody. I haven't programmed anything in about 8 years, I've read up a little bit on C and need to write a shell in C. I want to use strtok() to take an input from a user and parse it into the command and its arguments.

for example: copy <file1> <file2> will copy file 2 to file 1, del <file1> will delete a file, etc. The exit command is all I've implemented right now, but even that produces an error when executed...I'm sure I've got a problem with how I've implemented strtok().

I've tried to implement it below, but when I compile it using gcc (no errors/warnings) and try to execute it I get the following output:

o-shell>exit
com = exit
Segmentation fault (core dumped)


Here is the code snippet:
****************************
Code:

char command[50]; //Command line input

char com[10]; //Primary command
char file1[20]; //File affected by command (if necessary)
char file2[20]; //2nd file affected by command (if necessary)

char *token; //Used for strtok() function

for(;;)
{

printf("o-shell>"); //user prompts for o-shell

scanf("%s", command); //command line input from user

//tokenize the command line input using strtok() function
//this produces the command as well as any command line arguments

while(token != NULL)
{
token = strtok(command, " ");
strcpy(com, token);

printf("com = %s\n", com);

token = strtok(NULL, " ");
strcpy(file1, token);

printf("file1 = %s\n", file1);

token = strtok(NULL, " ");
strcpy(file2, token);

printf("file2 = %s\n", file2);
}

****************************
When I run the program, I get a segmentation fault. Will this code run OK if there are no arguments, just a command? I'm sure the problem is with strtok() either way. thanks!

DaWei 30Jun2007 22:04

Re: trying to use strtok for CL shell
 
Your while test isn't doing you any good down in the sequence. Let's say the second strtok doesn't find a token. It returns NULL. You aren't testing for that, you're dereferencing a NULL pointer when you attemp the strcpy. The problem isn't with strtok. As usual, it's with the coder.

ohaqqi 1Jul2007 04:22

Re: trying to use strtok for CL shell
 
I admit that I'm a total newbie, this is the first C program I've written in a long while, and that was just freshman intro to programming :D

So I'm trying to break the command[50] input from the user into 3 (or less) character strings. If I remove the while(token != NULL) and change it to if(&token == NULL) after each strtok() function indicating the end of the input by the user, is that correct? I'm totally confused :confused:

DaWei 1Jul2007 06:07

Re: trying to use strtok for CL shell
 
Did you try it? It's just logic. Strtok says it will deliver you the address of the next token, for each call, or a NULL when there's no new token. That's pretty clear. It doesn't promise to deliver the address of a token when there's no token. It's YOUR job to check that out. It doesn't promise to work if you dereference a NULL. It leaves the results of that up to the language (which forbids it) and the implementation, which seems, in this case, to give you a seg fault. It could burn your machine to a slag heap and cause your homework to eat the dog, and still comply with the standard.

You are flirting with danger in other respects. Just because you define the command to have a maximum of 9 characters, and the arguments to have a maximum of 19 characters, do you think that forces your user to obey? I don't know about you, but MY users are uninformed or lazy or malicious or fall asleep with their forehead on the keyboard. It is MY job, and YOUR job, to handle those eventualities.

We can ignore our jobs and issue updates to our programs for years, like MS, so long as we can convince people that they should pay us for the privilege of giving them crap code. Personally, I haven't been able to do that.

ohaqqi 1Jul2007 09:49

Re: trying to use strtok for CL shell
 
I redid my code and it partially works right now. I can use strtok to find the first input in the command line, but cannot get the arguments.

The format is <command> <arg1> <arg2>

So far, I've only implemented 'exit' and 'help'. When I run this code, it compiles fine but I get a segmentation fault. I've placed a couple printf to help debug. One of the problems is that the arguments are not detected/counted.

Here is the output:

************************************************** *
Welcome to O-Shell! A UNIX shell by O Haqqi

Type 'help' for list of commands, 'exit' to exit
************************************************** *

o-shell>exit
exit was entered
There are 0 arguments
Command is exit
Segmentation fault (core dumped)


Code:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char *argv[])
{
char command[50]; //Command line input

//tokens for strtok() funtion
char * com; //Primary command
char * arg1; //First argument of command (usually a file name)
char * arg2; //2nd argument of command (usually a file name)

int args; //Number of arguments entered

printf("************************************************** *\n");
printf("Welcome to O-Shell! A UNIX shell by O Haqqi\n\n");
printf("Type 'help' for list of commands, 'exit' to exit\n");
printf("************************************************** *\n\n");

for(;;)
{

printf("o-shell>"); //user prompts for o-shell

scanf("%s", command); //command line input from user

printf("%s was entered\n", command);

com = strtok(command, " \r\n\t");

args = 0;
arg1 = strtok(NULL, " \r\n\t");
if(arg1) args++; //to see if arguments being tracked
arg2 = strtok(NULL, " \r\n\t");
if(arg2) args++; //to see if arguments being tracked

printf("There are %d arguments\n", args);
printf("Command is %s\n", com);
printf("File1 is %s\n", arg1);
printf("File2 is %s\n", arg2);

if ((strcmp(com,"help")) ==0 || (strcmp(com,"Help")) ==0)
{
printf("\nO-Shell Help Menu:\n");
printf("\nhelp - Print help menu\n");
printf("\nexit - Exit O-Shell\n");
printf("\ntype <file> - Print contents of <file>\n");
printf("\ncopy <file1> <file2> - Copy contents of <file1> to <file2>.");
printf("\n <file2> must be a non-existent file and must be created\n");
printf("\ndelete <file> - Delete <file>\n\n");
}

else if ((strcmp(com,"exit")) ==0 || (strcmp(com,"Exit")) ==0)
{
printf("Exiting O-Shell...Goodbye!\n");
break;
}

else
printf("Invalid command!!! No operation performed...\n");

}


return 0;
}


DaWei 1Jul2007 17:46

Re: trying to use strtok for CL shell
 
You ask for help, you get a response, you don't pay attention. Is that nice? Suppose there is no arg1. That pointer is NULL. Do not dereference it with a statement like printf("File1 is %s\n", arg1);. That's invalid. Won't work. Seg fault. Core dump. Slag heap.

ohaqqi 2Jul2007 00:36

Re: trying to use strtok for CL shell
 
Quote:

Originally Posted by DaWei
You ask for help, you get a response, you don't pay attention. Is that nice? Suppose there is no arg1. That pointer is NULL. Do not dereference it with a statement like printf("File1 is %s\n", arg1);. That's invalid. Won't work. Seg fault. Core dump. Slag heap.

But if I type the following this is what I see:

o-shell>exit exit exit
exit was entered
There are 0 arguments
Command is exit
Segmentation fault (core dumped)


There should be two arguments (two exits after the command exit) counted. So the args pointer shouldn't be NULL, unless the strtok code that I entered is wrong...which is what I'm looking for --- the error.

ohaqqi 2Jul2007 00:44

Re: trying to use strtok for CL shell
 
Changing scanf to fgets fixed it (not sure why). As long as I don't try to printf NULL pointers, like you said dawei.
thanks

DaWei 2Jul2007 01:55

Re: trying to use strtok for CL shell
 
That's because scanf %s only returns the first token. Therefore there's nothing for strtok to find as the second and third arguments. Fgets returns the whole line. You still need to protect against using the args pointers for cases with fewer than three tokens. For example, just modifying your existing code:
Code:

printf("There are %d arguments\n", args);
printf("Command is %s\n", com);
if (arg1) printf("File1 is %s\n", arg1);
if (arg2) printf("File2 is %s\n", arg2);



All times are GMT +5.5. The time now is 04:45.