Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm writing a unix minishell in C, and am at the point where I'm adding command expansion. What I mean by this is that I can nest commands in other commands, for example:

$> echo hello $(echo world! ... $(echo and stuff))
hello world! ... and stuff

I think I have it working mostly, however it isn't marking the end of the expanded string correctly, for example if I do:

$> echo a $(echo b $(echo c))
a b c
$> echo d $(echo e)
d e c

See it prints the c, even though I didn't ask it to. Here is my code:

msh.c - http://pastebin.com/sd6DZYwB expand.c - http://pastebin.com/uLqvFGPw

I have a more code, but there's a lot of it, and these are the parts that I'm having trouble with at the moment. I'll try to tell you the basic way I'm doing this.

Main is in msh.c, here it gets a line of input from either the commandline or a shellfile, and then calls processline (char *line, int outFD, int waitFlag), where line is the line we just got, outFD is the file descriptor of the output file, and waitFlag tells us whether or not we should wait if we fork. When we call this from main we do it like this:

processline (buffer, 1, 1);

In processline, we allocate a new line:

char expanded_line[EXPANDEDLEN];

We then call expand, in expand.c:

expand(line, expanded_line, EXPANDEDLEN);

In expand, we copy the characters literally from line to expanded_line until we find a $(, which then calls:

static int expCmdOutput(char *orig, char *new, int *oldl_ind, int *newl_ind)

orig is line, and new is expanded line. oldl_ind and newl_ind are the current positions in the line and expanded line, respectively. Then we pipe, and recursively call processline, passing it the nested command(for example, if we had "echo a $(echo b)", we would pass processline "echo b").

This is where I get confused, each time expand is called, is it allocating a new chunk of memory EXPANDEDLEN long? If so, this is bad because I'll run out of stack room really quickly(in the case of a hugely nested commandline input). In expand I insert a null character at the end of the expanded string, so why is it printing past it?

If you guys need any more code, or explanations, just ask. Secondly, I put the code in pastebin because there's a ton of it, and in my experience people don't like it when I fill up several pages with code.

Thanks.

share|improve this question
    
perhaps better off asked at/transferred to stackoverflow –  vpit3833 Nov 19 '12 at 5:28
    
I already asked at stackoverflow(and unix, and many IRC channels, and the C forums). Nobody wants to touch this one! –  Optimus_Pwn Nov 19 '12 at 5:48
add comment

1 Answer

Most likely, you're not clearing out your structure that holds the expanded commands between processing. And / or, you're not terminating your expanded command structure properly after (re-)inserting new terms.

If the third term from the previous command shows up again on the next command that only has two terms, then that indicates your parser is being thrown off.

A quick way to test this would be to find out the results in this case:

$> echo a $(echo b $(echo c))
a b c
$> echo d 

and I expect you'll see:

d b c
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.