Использование execvp или execlp с флагом?

Я пытаюсь написать C-программу для софт-линка 2 файлов в Unix. В Unix эта команда будет:

ln -s oldfile newlink  

Поэтому я написал код для создания char * массив аргументов выглядит так:

char *args[4];
args[0] = "ln";
args[1] = "-s";
args[2] = argv[2]; //argv[2] is the name of the old file
args[3] = argv[3]; //argv[3] is the name of the new soft link file


execvp(args[0], args); 

Но флаг -s не читается процессором Linux. Как я могу переписать это так, чтобы он обрабатывал флаг -s? Я пытался сделать это с execlp также:

execlp(args[0], args[0], args[1], args[2], args[3], NULL);  

Но это также не работает. Что я делаю не так в этих строках?

РЕДАКТИРОВАТЬ: Я также пытался команду symlink(), но я не думаю, что моя версия Linux поддерживает ее, если я не ошибаюсь, и в моем коде есть недостаток:

char *args[4];
args[0] = "symlink";
args[1] = argv[2];
args[2] = argv[3];
args[3] = NULL;



execvp(args[0], args);

1 ответ

написать код C для soft-link 2 файлов на Linux

Для этой конкретной цели вам не нужно начинать /bin/ln процесс в вашем C-коде. Вместо этого вы должны использовать системный вызов symlink(2) (который будет использоваться ln процесс); это проще и намного быстрее. Не забудьте проверить его успех. Заметить, что symlink системный вызов (который должны иметь даже старые ядра Linux), доступный как функция C, а не команда (так что вы действительно не можете запустить symlink команда или исполняемый файл в вашей оболочке). Как задокументировано, вам нужно #include <unistd.h> в вашем C исходном файле. Читайте также символическую ссылку (7).

с использованием symlink системный вызов

Например, чтобы сделать эквивалент ln -s ~/somefile /tmp сначала вы должны вычислить путь (например, используя snprintf (3)...), соответствующий ~/somefile ( используя getenv...):

char* somefilepath = "somefile";
char oldpathbuf[256];
snprintf(oldpathbuf, sizeof(pathbuf), "%s/%s", getenv("HOME"), somefilepath);
/// missing detecting and handling of errors in above

(и я оставляю вас для обработки всех случаев ошибок, в том числе нехватка места для snprintf и они важны!)

Затем вам нужно вычислить путь новой ссылки (вы не можете использовать symlink системный вызов по каталогам):

 char newpathbuf[256];
 snprintf(newpathbuf, sizeof(newpathbuf), "/tmp/%s", somefilepath);

(снова обработайте ошибки и подумайте, что произойдет, если somefilepath начинается с ../ )

Наконец, выполните системный вызов, но проверьте на наличие ошибок:

 if (symlink(newpathbuf, oldpathbuf)) {
   perror("symlink");
   exit(EXIT_FAILURE);
 }

выполнение /bin/ln программа

Если вы настаиваете (ошибочно ИМХО) на использовании системного вызова execve (2) /bin/ln или какая-нибудь функция exec (3) (которая вызовет execve), обязательно добавьте NULL указатель. Кстати на успех эти exec функции не возвращаются, поэтому вам, вероятно, нужно вызвать fork (2) до и использовать waitpid (2) после.

Быть в курсе, что execvp использует PATH переменная. Так мимоходом просто ln к нему может работать (если у вашего пользователя странные $PATH установка) что-то еще, чем /bin/ln (этот путь к файлу указан в Linux FHS и в POSIX) с неожиданным побочным эффектом. Но см. Окружающую среду (7).

флаг -s не читается процессором Linux

Там не задействован "процессор Linux". -s флаг обрабатывается /bin/ln исполняемая программа (чья main Функция получает расширенные аргументы программы, а затем вызывает symlink системный вызов). Вам нужно больше понимать роль оболочек Unix, что такое глобализация и как команда расширяется оболочкой.

полезные ссылки для чтения

Я рекомендую прочитать Расширенное программирование Linux и справочную страницу intro (2) и syscalls (2).

Вы, вероятно, должны прочитать больше об операционных системах и понять разницу между командами и системными вызовами и ролью любой оболочки Unix. Я рекомендую прочитать свободно доступные Операционные системы: Три Легких Части

Другие вопросы по тегам