LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-08-2005, 08:41 PM   #1
ar1
Member
 
Registered: Nov 2003
Location: Bloomington, IL, USA
Distribution: Fedora Core 3
Posts: 126

Rep: Reputation: 15
Weird error in C program


Hi, I wrote the following code which creates a simple shell (like bash). It works fine, can take a command along with arguments and run it or give error if it doesn't exist. However, the strange problem is that it doesn;t execute anything the first time "enter" is hit!! But after that it works perfectly.

I couldn't find the bug, any help would be great. Thanks
---------------------------------------------------------------------------------------------

#include <string.h>
#include <errno.h>

#define TRUE 1

void type_prompt();
void *read_command(char *argv[]);
int n = 0;

int main(int argc, char *argv[], char *envp[])
{
char *command;
int status;
argv[0] = NULL;

while (TRUE) /* repeat forever */
{
type_prompt(); /* display prompt on screen */
read_command(argv); /* read input from terminal */

if (fork() != 0) /* fork off child process */
{
waitpid(-1, &status, 0); /* wait for child to exit */
}
else
{
if (execve(argv[0], argv, envp) == -1) /* execute command */
printf("Ouch, can't execute: %s\n", strerror(errno));
}
}
return 0;
}

void type_prompt()
{
printf("[arajgarh]$ ");
}

void *read_command(char *argv[])
{
n = 0;
char temp[256];

gets(temp);
argv[n++] = strtok (temp," ");

while (argv[n-1] != NULL)
argv[n++] = strtok (NULL, " ");
}
 
Old 02-09-2005, 10:08 AM   #2
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 59
Have you tried any debugging? Maybe print what temp is after the gets() in read_command().

By the way, don't ever ever use gets(). Use fgets() instead.
 
Old 02-09-2005, 11:00 AM   #3
ar1
Member
 
Registered: Nov 2003
Location: Bloomington, IL, USA
Distribution: Fedora Core 3
Posts: 126

Original Poster
Rep: Reputation: 15
Yes, I tried debugging and temp gives the correct value even the first time. Yet the first time, as I said, the value of temp gets messed up when fork() is called. I do not know why this happens
 
Old 02-09-2005, 11:36 AM   #4
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 59
Well, I don't think the way you're using argv is very reliable. Ideally, you'd create your own array of strings that you can store the user's input in.
 
Old 02-09-2005, 11:43 AM   #5
ar1
Member
 
Registered: Nov 2003
Location: Bloomington, IL, USA
Distribution: Fedora Core 3
Posts: 126

Original Poster
Rep: Reputation: 15
I tried using my own array, but it didn't help. Here's a sample output with ot without my own array. You can see what I mean:

----------------------------------------------------------------------------------------------------------------

[arajgarh@localhost ass1]$ ./q3
[arajgarh]$ /bin/ls
Ouch, can't execute: No such file or directory
[arajgarh]$ /bin/ls
debug_me debug_me.c listing9 listing9.c q3 q3b q3b.c q3.c q3.o simple-shell simple-shell.c simple-shell.o temp temp.c
[arajgarh]$ /bin/ls -a
. .. debug_me debug_me.c listing9 listing9.c q3 q3b q3b.c q3.c q3.o simple-shell simple-shell.c simple-shell.o temp temp.c
[arajgarh]$

----------------------------------------------------------------------------------------------------------------

Thanks
 
Old 02-09-2005, 12:30 PM   #6
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 59
You should try getting your code to compile correctly (warning free):
Code:
itsme@dreams:~/C$ gcc -Wall shell.c -o shell
shell.c: In function `main':
shell.c:22: warning: implicit declaration of function `fork'
shell.c:24: warning: implicit declaration of function `waitpid'
shell.c:28: warning: implicit declaration of function `execve'
shell.c:29: warning: implicit declaration of function `printf'
shell.c:12: warning: unused variable `command'
shell.c: In function `read_command':
shell.c:43: parse error before `char'
shell.c:45: warning: implicit declaration of function `gets'
shell.c:45: `temp' undeclared (first use in this function)
shell.c:45: (Each undeclared identifier is reported only once
shell.c:45: for each function it appears in.)
shell.c:50: warning: control reaches end of non-void function
 
Old 02-09-2005, 01:16 PM   #7
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 59
Here's a version of your code that works:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

#define TRUE 1

void type_prompt();
void read_command(char ***args);

int main(int argc, char *argv[])
{
  char **args;
  int i, status;

  while(TRUE) /* repeat forever */
  {
    type_prompt(); /* display prompt on screen */
    read_command(&args); /* read input from terminal */

    if(fork() != 0) /* fork off child process */
    {
      waitpid(-1, &status, 0); /* wait for child to exit */
    }
    else
    {
      if(execvp(args[0], args) == -1) /* execute command */
        printf("Ouch, can't execute '%s': %s\n",
          args[0], strerror(errno));
      for(i = 0;args[i];++i)
        free(args[i]);
      free(args);
    }
  }
  return 0;
}

void type_prompt(void)
{
  printf("[arajgarh]$ ");
  fflush(stdout);
}

void read_command(char ***args)
{
  char temp[256], *p;
  int n = 0;

  fgets(temp, sizeof(temp), stdin);
  temp[strlen(temp)-1] = '\0';

  *args = malloc(sizeof(char *));
  p = strtok(temp, " ");
  if(p)
  {
    (*args)[n] = malloc(strlen(p)+1);
    strcpy((*args)[n++], p);
  }
  else
    (*args)[n++] = NULL;

  while((*args)[n-1])
  {
    *args = realloc(*args, sizeof(char *) * n);
    p = strtok(NULL, " ");
    if(p)
    {
      (*args)[n] = malloc(strlen(p)+1);
      strcpy((*args)[n++], p);
    }
    else
      (*args)[n++] = NULL;
  }
}

Last edited by itsme86; 02-09-2005 at 01:17 PM.
 
Old 02-09-2005, 01:25 PM   #8
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Code:
void *read_command(char *argv[])
{
    n = 0;
    char temp[256];

    gets(temp);
    argv[n++] = strtok (temp," ");

    while (argv[n-1] != NULL)
    argv[n++] = strtok (NULL, " ");
}
What this function does is bad:
It assigns pointers to the local variable 'temp' to the argv 'owned' by main(). After this function returns, 'temp' doesn't exist anymore, while main() will have its argv[] point to 'temp'... Because local var's like 'temp' are on the stack you didn't get segementation fault crashes. It's more or less coincidence that your argv[] still has values that seem correct after calling read_command().

Even without the error above, I fully agree with itsme86's doubts about the way you are fiddling with argv[]. While it's not necessarily wrong to change argv-strings: e.g. the getopt() library function shuffles them, and some software change argv[0] which reflects in top, ps, etc. But: "argv[0] = NULL" looks very "experimental" to me. I'm not sure if its really wrong to do that, it's "unusual" to say the least. Also, imagine you start your program without any parameters on the command line, so argv[1]....argv[x] will be empty or don't even exist. What would happen if a user of your program enters a command with 1 or more arguments? Then argv[1]...argv[x] will be assinged those arguments, but do argv[1], argv[2] exist, e.g. have memory space allocated for all of them? I don't know, and maybe Linux does allocate space for some argv[]'s for each program even if they were not given on the command line that started the program. But even if Linux does this, how many?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
weird PHP error atom Programming 5 09-26-2004 08:50 AM
weird 'swapon -a' error elluva Slackware 3 08-18-2004 02:39 AM
Weird X error AMMullan Red Hat 3 11-22-2003 08:11 PM
Weird error demonfi Linux - Newbie 1 08-16-2003 01:35 PM
Weird error help! please Devboy Linux - Software 9 08-01-2003 08:56 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:28 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration