I'm trying to emulate bash/cmd type program. I have written programs like cat, ls, grep (simple one) and kept it under \bin\ directory. This program will take user input and run programs present in \bin\ accordingly. I'm using _spawnv () as the argument list is going to be variable.

When I googled I found in one site its telling me last argument of _spawnv () is pointers to arguments value, like *argv[], but when I compiled its asking for const char* const*. I know that they are not equivalent but I'm not able to figure out a way. Here is my code.

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <errno.h>
# include <direct.h>
# include <process.h>
# define GetCurrentDir _getcwd
# define MAX 1024

char ** tokenize (const char *) ;

int main (int argc, char *argv[])
{
    char arg[MAX][MAX], input[MAX] ;
    char** tokens ;
    char prog[MAX], cwd[FILENAME_MAX] ;
    int i, count, res = 0 ;
    char** it;

    while (1)
    {
        if (!GetCurrentDir(cwd, sizeof(cwd)))
            return errno;
        cwd[sizeof(cwd) - 1] = '\0';

        printf ("%s\n#  ", cwd) ;
        fgets (input, 100, stdin) ;

        tokens = tokenize(input) ;
        count = 0 ;
        for (it = tokens, i = 0; it && *it; ++it, i++)
        {
            count++ ;
            strcpy (arg[i], *it) ;
            free (*it) ;
        }

        arg[++count] = NULL ;

        free(tokens) ;

        prog[0] = '\0' ;

        strcpy (prog,cwd) ;
        strcat (prog,"\\bin\\") ;
        strcat (prog, arg[0]) ;

        if (strcmp(arg[0], "exit") == 0)
            break ;

        if ((res = _spawnv (_P_WAIT, prog, arg)) == -1 )
            perror ("\nspawn error\n") ;
    }
    return 0 ;
}

char** tokenize(const char* input)
{
    char* str = strdup(input);
    int count = 0;
    int capacity = 10;
    char** result = malloc(capacity*sizeof(*result));

    char* tok=strtok(str," ");

    while(1)
    {
        if (count >= capacity)
            result = realloc(result, (capacity*=2)*sizeof(*result));

        result[count++] = tok? strdup(tok) : tok;

        if (!tok) break;

        tok=strtok(NULL," ");
    }

    free(str);
    return result;
}

Also is there anyother way to do this work ? Thank you.

Recommended Answers

All 3 Replies

Line 24 is unnecessary because the string is already null terminated. Also, you are null terminating the string in the wrong place.

line 38: illegal statement. Must be arg[++count][0] = '\0';

line 40: That is a memory leak. tokens is not a simple block of memory. You have to free() each of the pointers individually (see line 71).

line 42 is unnecessary because line 44 strcpy() will start at the beginning of the character array anyway.

line 51: you might try typcasting the last parameter
_spawnv(_P_WAIT, prog, (char**)arg))

line 62 and 69: sizeof(*result) will ALWAYS be 1, so using sizeof() there has no value.

Thanks Ancient Dragon, but I couldn't make my C program work. Everytime it crashes on _spawnv() call. I think I'm not being able to pass the arguments properly. Can you just check it where I'm going wrong ?

I tried this on python and it works like charm. Here is my code

import os

while 1:
    cwd = os.getcwd()
    command = input (cwd + "\n# ")
    if command == "exit":
        break
    prog = command.split()
    pwd = cwd + "\\bin\\" + prog[0] + ".exe"
    os.spawnve (os.P_WAIT, pwd, prog, os.environ)

I think I should use subprocess module rather than spawn, because in the documentation its said that these functions are not thread safe (wonder what that means). Anyway I think I will do this calling thing on python and bundle the exe using cz_freeze.

Also I would like to know what would you guys implement, for making a bash/cmd like program. Thanks !!!

What are you entering for Input (line 27)? And what are the command-line arguments you are using (argv[])?

I tried to run your program and it crashed upon startup, the reason is that it takes up too much stack space. All those huge arrays are just too much. Move lines 14 and 16 up above main() into global space and the program will run.

line 40: That is a memory leak.

Ignore that comment -- your program is freeing memory correctly.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.