Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

i can't find the bug...need help!

Status
Not open for further replies.

aboujouj83

IS-IT--Management
May 9, 2003
52
US
I am writing a unix shell in C. One of the required function of the shell is to be able to make variable substitution i.e if we write cd $var1, the shell should convert it to cd folder1, if $var1=folder1.

My shell is working fine if I don't include the code of variable substitution. I will write the relevant part of the code here (the whole program is very long, and won't help much to solve the problem):

char* findVar(myshenvTP *env, char* gname){
int j;
for (j = 0; j < MAXNOENV; j++){
/* returns null when it finds a variable name = &quot; &quot; meaning there are no more variables */
if (strcmp(env -> envarray[j].NAME,&quot; &quot;)== 0)
return &quot;notfound&quot;;

else if (strcmp(env -> envarray[j].NAME,gname) == 0){
/* here the variable is found, so we return it */
return (env -> envarray [j].VALUE);
}
}
/* the function hasn't returned yet i.e variable not found */
/* returns also NULL in this case */
return &quot;notfound&quot;;
}


**********************************************************
int parseline(myshenvTP *env, char *line, char **token, char *dlimiter) {

int i = 0;
token = strtok(line, dlimiter);

while(token != NULL) {
/* check each token for environmental variables
replace the variable by its value if it exists
return variable not defined if variable not found */
if (strcmp ((replaceVariables(env, token)),&quot;varNotDefined&quot;) == 0)
return -1;
*/
i++;
token = strtok(NULL, dlimiter);

}

if(i > MAX_ARG) {

fprintf(stderr, &quot;Exceeds defined max # of args! Omit those out of index!\n&quot;);

i = MAX_ARG;

}
return i;
}
***********************************************************

/* replace environmental variable by its value
assumes that only one environmental variable used in the beginning of the token */

char* replaceVariables (myshenvTP *env, char *aToken){
char *subtoken1 = malloc((1)*sizeof(char));
char *valueOfVar = malloc((1)*sizeof(char));
char *subtoken2 = malloc((1)*sizeof(char));
if (aToken[0] != '$')
return &quot;noVariablefound&quot;;

else{
subtoken1= strtok(aToken, &quot;/&quot;);
if (subtoken1 == NULL){ /* no token found */

/* here we search for the variable in the enviromental variable array */
valueOfVar = findVar(env, aToken + 1);
if(strcmp(valueOfVar, &quot;notfound&quot;) == 0)
{
printf(&quot;%s: Undefined variable.\n&quot;, aToken + 1);
return &quot;varNotDefined&quot;;
}
else strcpy (aToken, valueOfVar);
return &quot;success&quot;;

/* here we found a token delimiter
So we replace subtoken1 by its value and then concatenate it with subtoken2*/
}else{
subtoken2 = strtok(NULL, &quot;/&quot;);
strcpy(aToken, valueOfVar);
strcat(aToken, &quot;/&quot;);
strcat(aToken, subtoken2);
/*free(subtoken1);
free(subtoken2);
free(valueOfVar); */
return &quot;success&quot;;
}
}
}


***********************************************************

Note that these types are declared in the header of my file:
#define MAX_STR_LEN 64
#define MAX_LEN 1023 /* maximum length of a line */

#define MAX_ARG 100 /* maximum # of command arguments */

#define MAXNOCMD 32 /* max No of previous commands shown for history */

#define MAXNOENV 100 /* max No of environment variables allowed */

#define MALLOC(p,n,type) ((p) = malloc((n)*sizeof(type))) == NULL)



extern int errno; /* To use errno in the program */


/* internal variable structure */

typedef struct {

char NAME[MAX_STR_LEN];

char VALUE[MAX_STR_LEN];

}envarT;


/* Shell environmental var structure */

typedef struct {

envarT envarray[MAXNOENV];

} myshenvTP;



/* Command structure */

typedef struct {

char *Argv[MAX_ARG]; /* Argv[0] is command name */

int argc;

}cmdT, *cmdTP;
***********************************************************

WHEN I COMMENT THE replaceVariables method in the parseLine method, the program works...BUT I CAN'T SEE THE ERROR...IT'S PROBABLY MEMORY RELATED since the messages that I get are:
&quot;Segmentation fault&quot; and &quot;Bus error&quot; depending on the command that I request.
ANY HELP IS VERY APPRECIATED
ABOUJOUJ
 
> char *subtoken2 = malloc((1)*sizeof(char));
This allocates memory - you don't need to allocate memory for what this function is doing.

> subtoken2 = strtok(NULL, &quot;/&quot;);
This trashes the pointer to the memory you previously allocated. You now have a memory leak.

> free(subtoken2);
Now you're in trouble, you're freeing a pointer which was not returned by malloc. All sorts of chaos is about to happen.

Simply remove the malloc and free calls inside this routine.


I rather suspect that you don't know how strtok() works either.
If you have
Code:
char p[] = &quot;hello world&quot;;
And you do
Code:
char *q = strtok(p,&quot; &quot;);
Then q will point to &quot;hello&quot;, as you know.

What few people realise is that p now looks like this
Code:
char p[] = &quot;hello\0world&quot;;
That is, it has been MODIFIED by strtok.
This will trash your symbol database unless you are very careful about it.

> #define MALLOC(p,n,type) ((p) = malloc((n)*sizeof(type))) == NULL)
This adds so little to the understanding of the problem that is it not worth adding IMO


--
 
Thanks Salem,
I am trying to understand more the strtok function:
Does it return Null if there it delimiter in the string?
Taking your example and modifying p[]:
char p[] = &quot;hello&quot;;
And you do
char *q = strtok(p,&quot; &quot;);
Where do q point to now?
Has p been modified in this case?

Thanks
aboujouj
 
I meant &quot;Does it return Null if there is NO delimiter in the string?

Aboujouj
 
An example
Code:
char msg[] = &quot;this is a test&quot;;
char *p;
for ( p = strtok(msg,&quot; &quot;) ; p != NULL ; p = strtok(NULL,&quot; &quot;) ) {
  printf( &quot;Token=%s\n&quot;, p );
}
This extracts all tokens from a string.


If there is initially no delimiter, you get the whole string
Code:
char msg[] = &quot;this&quot;;
char *p = strtok(msg,&quot; &quot;);
// p is also &quot;this&quot;
// Follow this with p = strtok(p,NULL) would result in p == NULL

--
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top