我正在尝试使用execv()函数。
我试图将参数命令传递到左侧。
execv(file,arguments);
我正在使用char *来解析我的shell的输入用户输入。
execv的第二个参数采用char * const *。
有没有办法将char * const强制转换为char * const *?
我在下面尝试,
char * arg;
char *const a[] = (char *const)arg;
error: invalid initializer
char *const a[] = (char *const)arg;
^
但是它不起作用,并给我错误。
将不胜感激。
答案 0 :(得分:3)
char *const a[] = (char *const)arg;
中的错误不是由于转换不正确引起的。这是因为char *const a[]
声明了一个数组,并且该数组的初始化程序必须位于大括号 1 ,{ … }
中,但是您只指定了一个不带有大括号的初始化程序。
此外,argv
的{{1}}参数应该是一个指针数组,其中第一个指针指向包含正在执行的程序的文件名的字符串(按惯例,这不是必需的)最后一个是空指针。因此,您对execv
的定义应类似于:
a
1 除非使用字符串文字来初始化数组,但是这里不是这种情况。
答案 1 :(得分:0)
您正在尝试初始化数组。
char * arg;
char *const a[] = (char *const)arg;
执行此操作:
char * arg;
char *const a[] = {(char *const)arg};
答案 2 :(得分:0)
在删除命令名称和一些第一个参数之后,执行execv
是很正常的。例如,如果您有类似的代码(最好发布一个完整且可验证的示例),那么假设您正在执行类似的操作(如果您想要一个示例,请查找xargs(1)
联机帮助页,您可以找到一条命令,并在处理了选项及其参数之后,想要消除所有选项,并像执行命令行一样执行其余操作,例如,我有一条命令重复执行一条命令,从而延迟了指定的时间,例如:>
cont -t 0.1 -- df -k .
我使用<getopts.h>
处理cont
程序的选项,然后重复执行命令df -k
。使用选项可以显示程序的版本,指定超时,详细信息或执行命令的次数。我刚刚写了它,以向您展示如何做(该示例包括fork(2)
的使用,execvp(2)
和重定向,以捕获命令的输出,以便能够返回到原点(一旦知道)我们收到的行数,程序使用ANSI转义将光标移回开头。)
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define F(_fmt) "%s:%d: " _fmt, __FILE__, __LINE__
#define FLAG_VERBOSE (1<<0)
#define FLAG_VERSION (1<<1)
#define FLAG_DELAY (1<<2)
#define FLAG_NTIMES (1<<3)
int flags = 0;
useconds_t delay = 1000000;
size_t ntimes;
void doVersion(void)
{
fprintf(stderr,
"cont: v1.0\n"
"(C) Luis Colorado. All rights reserved.\n"
"License: BSD\n");
exit(EXIT_SUCCESS);
}
ssize_t loop(int argc_unused, char **argv)
{
int fd[2];
int res = pipe(fd);
res = fork();
if (res < 0) {
fprintf(stderr,
F("fork: ERROR %d: %s\n"),
errno,
strerror(errno));
return -1;
} else if (res == 0) { /* child */
close(fd[0]); /* not going to use it */
dup2(fd[1], 1); /* redirect output to pipe */
close(fd[1]);
execvp(argv[0], argv);
fprintf(stderr,
F("execv: ERROR %d: %s\n"),
errno, strerror(errno));
return -1;
} else { /* parent */
pid_t cld_pid = res;
close(fd[1]); /* no writing to the pipe */
FILE *f = fdopen(fd[0], "rt"); /* just reading */
int c;
size_t lines = 0;
while((c = fgetc(f)) != EOF) {
if (c == '\n') lines++;
putc(c, stdout);
}
wait(NULL);
return lines;
}
} /* loop */
int main(int argc, char **argv)
{
int opt;
float t;
while ((opt = getopt(argc, argv, "t:Vvn:")) >= 0) {
switch(opt) {
case 't': flags |= FLAG_DELAY;
t = atof(optarg);
break;
case 'V': flags |= FLAG_VERSION;
break;
case 'v': flags |= FLAG_VERBOSE;
break;
case 'n': flags |= FLAG_NTIMES;
ntimes = atoi(optarg);
break;
/* ... */
}
}
if (flags & FLAG_VERSION)
doVersion();
/* the next pair of sentences is like `shift optind' in the shell. */
/* trick, don't move the parameters, just move the pointer */
argc -= optind; /* adjust the number of parameters. */
argv += optind; /* advance the pointer to the proper place */
/* NOW, argc && argv are identical to the original ones, but lacking the
* first `optind' argument strings. As the original string array ended
* in a NULL, there's no need to construct it from allocating memory.
* Anyway, we're not going to use after it's consumed in main(). */
if (flags & FLAG_VERBOSE) {
char *sep = "About to execute: ";
int i;
for (i = 0; i < argc; i++) {
fprintf(stderr, "%s%s", sep, argv[i]);
sep = " ";
}
fprintf(stderr, "\n");
}
if (flags & FLAG_DELAY) {
delay = t * 1.0E6;
}
size_t total_lines = 0;
ssize_t n = 0;
while(!(flags & FLAG_NTIMES) || ntimes--) {
/* move up as many lines as input from subcommand */
if (n) printf("\r\033[%ldA@\b", n);
n = loop(argc, argv);
if (n < 0) {
/* we have already written the error */
exit(EXIT_FAILURE);
}
usleep(delay);
total_lines += n;
}
if (flags & FLAG_VERBOSE) {
fprintf(stderr,
F("Total lines: %lu\n"),
total_lines);
}
exit(EXIT_SUCCESS);
}
您可以从Github下载该程序的完整版本