使用带有限字符的execvp *

时间:2014-03-02 22:15:54

标签: c pointers exec

我有:

char * tokens[50][2];  

在此设置中,标记[i] [0]指向参数的开头,标记[i] [1]指向结尾。这些令牌不是空终止。要打印它们我正在使用:

printf("%.*s ",(int)(com->tokens[i][1] - com->tokens[i][0] + 1), com->tokens[i][0]); 

现在我需要使用它们来执行一个函数。我试图用execvp来完成这项工作。我试图避免为这些字符串分配内存,如果可能的话。有没有办法发送有界字符串作为参数?有什么想法吗?

1 个答案:

答案 0 :(得分:0)

由于execvp()仅适用于空终止字符串,因此您必须将null终止字符串或者......实际上,由于所有系统调用都没有选项使用以null结尾的字符串。

好的:另一种方法是制作字符串的空终止副本,并用副本调用execvp()。既然你知道它们有多长,你就能够相当有效地完成它 - 但你需要分配足够的内存。

size_t req_size = 0;
for (int i = 0; i < n; i++)
    req_size += (com->tokens[i][1] - com->tokens[i][0] + 2);
char **argv = malloc((n + 1) * sizeof(argv[0]));
char *args = malloc(req_size);
if (argv == 0 || args == 0)
    …report memory allocation failure; do not continue…
char *argp = args;
int i;
for (i = 0; i < n; i++)
{
    size_t len_i = com->tokens[i][1] - com->tokens[i][0] + 1;
    argv[i] = argp;
    memmove(argv[i], com->tokens[i][0], len_i);
    argv[i][len_i] = '\0';
    argp += len_i + 1;
}
assert(argp == args + req_size);
argv[i] = 0;                      // Null terminate list of pointers

execvp(argv[0], argv);

嵌入在SSCCE中的代码(Short, Self-Contained, Correct Example):

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct command
{
    int n;
    char *tokens[50][2];
};

static void print_fixed(struct command *com)
{
    printf("fixed:\n");
    printf("%d:", com->n);
    for (int i = 0; i < com->n; i++)
        printf(" [%.*s]", (int)(com->tokens[i][1] - com->tokens[i][0] + 1), com->tokens[i][0]);
    putchar('\n');
}

static void print_argv(int argc, char **argv)
{
    printf("argv:\n");
    for (int i = 0; i <= argc; i++)
    {
        char *arg = argv[i];
        if (arg == 0)
            arg = "<<NULL pointer>>";
        printf("%d: [%s]\n", i, arg);
    }
}

int main(void)
{
    char data[] = "command arg1 arg2 arg3 arg4";
    struct command cmd =
    {
        5,
        { { &data[ 0], &data[ 6] }, { &data[ 8], &data[11] },
          { &data[13], &data[16] }, { &data[18], &data[21] },
          { &data[23], &data[26] },
        }
    };
    struct command *com = &cmd;
    int n = com->n;
    print_fixed(com);

    size_t req_size = 0;
    for (int i = 0; i < n; i++)
        req_size += (com->tokens[i][1] - com->tokens[i][0] + 2);
    char **argv = malloc((n + 1) * sizeof(argv[0]));
    char *args = malloc(req_size);
    if (argv == 0 || args == 0)
    {
        fprintf(stderr, "Memory allocation failure\n");
        exit(1);
    }
    char *argp = args;
    int i;
    for (i = 0; i < n; i++)
    {
        size_t len_i = com->tokens[i][1] - com->tokens[i][0] + 1;
        argv[i] = argp;
        memmove(argv[i], com->tokens[i][0], len_i);
        argv[i][len_i] = '\0';
        argp += len_i + 1;
    }
    assert(argp == args + req_size);
    argv[i] = 0;                      // Null terminate list of pointers

    print_argv(i, argv);

    return 0;
}

输出:

fixed:
5: [command] [arg1] [arg2] [arg3] [arg4]
argv:
0: [command]
1: [arg1]
2: [arg2]
3: [arg3]
4: [arg4]
5: [<<NULL pointer>>]