Unrealcow
Unrealcow

Reputation: 41

Parsing one buffer affects another?

I am developing a history function for a custom C shell for a class. I need the history to display the last twenty commands that have been entered in the shell. The command history is being stored in a local text file with the following format:

0001 <command>
0002 <command>
0003 <command>
...

When I attempt to print lines from the history file, only the numbers are being printed and not the command itself. Here is my function to print the history:

169 int print_history()
170 {
171     int first = (current - 20);
172     if (first < 1)
173         first = 1;
174
175     char **arg_p;
176     FILE *fp = fopen("history", "r");
177     int count = 0;
178     char buff[MAX_LENGTH];
179     while(fgets(buff, sizeof buff, fp) != NULL)
180     {
181         char *temp_buf = buff;
182         printf("%s\n", temp_buf);  // this line prints the entire line, just as I need it
183         arg_p = parse(buff);
184         printf("%s\n", temp_buf);  // this line prints only the number
185         int temp = atoi(arg_p[0]);
186         if(temp >= first && temp <= current)
187             printf("%s\n", temp_buf);
188     }
189     fclose(fp);
190 }

The printf lines with the comments (182 and 184) are just for error checking. When I parse buff, it somehow changes temp_buf so that it does not display correctly. The output from those two lines (for a single loop cycle) appears as follows:

0035 exit

0035 

Here is my parse function that buff is being passed to:

76 char **parse(char *line)
77 {
78     int size = 64;
79     int position = 0;
80     char **words = malloc(size * sizeof(char*));
81     char *word;
82     word = strtok(line, DELIM);
83     while (word != NULL)
84     {
85         words[position] = word;
86         position++;
87         word = strtok(NULL, DELIM);
88     }
89     words[position] = NULL;
90     return words;
91 }

Any ideas on why parsing one buffer is affecting another buffer as well? Any help is appreciated.

Thanks!

Upvotes: 0

Views: 49

Answers (2)

Rohan
Rohan

Reputation: 53336

In your parse() function, you are storing the word as

words[position] = word;

However, you should do

words[position] = strdup(word);

e.g duplicate the string. The contents of word aka line aka buff (from main) would change once you read the next line.

Upvotes: 2

Leandros
Leandros

Reputation: 16825

strtok is destructive.

This function is destructive: it writes the '\0' characters in the elements of the string str. In particular, a string literal cannot be used as the first argument of strtok.

Taken from the strtok doc here.

Upvotes: 2

Related Questions