I'm trying to write a C program to soft-link 2 files on Unix. In Unix, this command would be:
ln -s oldfile newlink
So I wrote a code to create a char * array of the arguments like so:
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);
But the -s flag is not read by the Linux processor. How can I rewrite this in a way that it will handle the -s flag? I tried to do it with execlp as well:
execlp(args[0], args[0], args[1], args[2], args[3], NULL);
But that also does not work. What am I doing wrong in these lines?
EDIT: I have also attempted the symlink() command, but I don't think my version of linux supports it, unless I am wrong and there is a flaw in my code:
char *args[4];
args[0] = "symlink";
args[1] = argv[2];
args[2] = argv[3];
args[3] = NULL;
execvp(args[0], args);
For that specific purpose, you don't need to start a
/bin/lnprocess in your C code. You should instead use the symlink(2) system call (which would be used by thelnprocess); this is simpler and much faster. Don't forget to check its success. Notice thatsymlinkis a system call (that even old Linux kernels should have) available as a C function, not a command (so indeed you cannot run anycommand or executable in your shell). As documented, you need tosymlink#include <unistd.h>in your C source file. Read also symlink(7).using the
symlinksystem callFor example, to do the equivalent of
ln -s ~/somefile /tmpyou would first compute the path (e.g. using snprintf(3)...) corresponding to~/somefile(by usinggetenv...):(and I leave you to handle all the error cases, including lack of space for
snprintf, and they are important!)Then you need to compute the path of the new link (you cannot use
symlinksystem call on directories):(again, handle the errors, and think what would happen if
somefilepathstarts with../)At last, do the system call but check against failure:
executing the
/bin/lnprogramIf you insist (wrongly IMHO) on using the execve(2) syscall on
/bin/lnor some exec(3) function (which would callexecve), be sure to explicitly add aNULLpointer. BTW on success theseexecfunctions don't return, so you probably need to call fork(2) before and to use waitpid(2) after.Be aware that
execvpuses thePATHvariable. So passing justlnto it might run (if your user has a weird$PATHsetting) something else than/bin/ln(that file path is specified in the Linux FHS and in POSIX) with some unexpected side-effect. But see environ(7).There is no "Linux processor" involved. The
-sflag is handled by the/bin/lnexecutable program (whosemainfunction gets the expanded program arguments, and which then calls thesymlinksystem call). You need to understand more the role of unix shells and what globbing is and how a command is expanded by the shell.useful references to read
I recommend reading Advanced Linux Programming and the intro(2) and syscalls(2) man page.
You probably should read more about Operating Systems and understand the difference between commands and system calls and the role of any Unix shell. I recommend reading the freely available Operating Systems : Three Easy Pieces