Wrapper procedure for write () with unistd.h included results in error

I am writing a shell procedure for write()to override the original system function, and inside it I need to execute another program through execve(); for which I include the header file unistd.h. I get an error message . I would really appreciate it if someone could help me, since I need to call another program from within the wrapper and also send arguments to it from inside the shell procedure. conflicting types for 'write' /usr/include/unistd.h:363:16: note: previous declaration of 'write'was here

+3
source share
5 answers

An alternative to using the GNU liner option --wrap symbolas suggested by Matthew Slatter is to use dlsym()it to get the address of the character execve()at runtime to avoid compilation issues with inclusion unistd.h.

I suggest reading the Jay Conrod Blog Blog Tutorial: Function Interpolation on Linux for more information on replacing calls with functions in dynamic libraries with calls to your own wrapper functions.

​​ write(), write() execve() unistd.h. , write() , .

:

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>

size_t write(int fd, const void *buf, size_t count)
{
    static size_t (*write_func)(int, const void *, size_t) = NULL;    
    static int (*execve_func)(const char *, char *const[], char *const[]) = NULL;

    /* arguments for execve()  */
    char *path = "/bin/echo";
    char *argv[] = { path, "hello world", NULL };
    char *envp[] = { NULL };

    if (!write_func)
    {
        /* get reference to original (libc provided) write */
        write_func = (size_t(*)(int, const void *, size_t)) dlsym(RTLD_NEXT, "write");
    }

    if (!execve_func)
    {
        /* get reference to execve */
        execve_func = (int(*)(const char *, char *const[], char *const[])) dlsym(RTLD_NEXT, "execve");
    }

    /* call original write() */
    write_func(fd, buf, count);

    /* call execve() */
    return execve_func(path, argv, envp);
}

int main(int argc, char *argv[])
{
    int filedes = 1;
    char buf[] = "write() called\n";
    size_t nbyte = sizeof buf / sizeof buf[0];

    write(filedes, buf, nbyte);

    return 0;
}

:

$gcc -Wall -Werror -ldl test.c -o test
$./test
write()

$

. , . .

+2

GNU --wrap <symbol>, .

--wrap write, write __wrap_write ( ), __real_write write ( ).

write() - , hello.o :

$ cat hello.c
#include <unistd.h>

int main(void)
{
    write(0, "Hello, world!\n", 14);
    return 0;
}
$ gcc -Wall -c hello.c
$ gcc -o test1 hello.o
$ ./test1
Hello, world!
$

__wrap_write(), __real_write(). ( , , __real_write . , - #define write __real_write #include <unistd.h>.)

$ cat wrapper.c
#include <unistd.h>

extern ssize_t __real_write(int fd, const void *buf, size_t n);

ssize_t __wrap_write(int fd, const void *buf, size_t n)
{
    __real_write(fd, "[wrapped] ", 10);
    return __real_write(fd, buf, n);
}
$ gcc -Wall -c wrapper.c
$

hello.o, wrapper.o, . ( gcc , -Wl,option.)

$ gcc -o test2 -Wl,--wrap -Wl,write hello.o wrapper.o
$ ./test2
[wrapped] Hello, world!
$
+4

write() POSIX. C, write(), , . , POSIX - execve() - POSIX, ; POSIX write().

, , . write() , <unistd.h> , C . , execve() , <unistd.h>. .

, . , . , , o/s ( ) . write().

+2

Muggen ( wiki):

write write . -

void write(int a) {
    /* code code code */
    write(42);                  /* ??? what `write`?
                                   ??? recursive `write`?
                                   ??? the other `write`? */
    /* code code code */
}

:)

+1

, , , unistd.h. .

, , . , - libc write(), .

:
exec.c

#include <unistd.h>

inline int execve_func(const char *path, char *const argv[], char *const envp[])
{
    return execve(path, argv, envp);
}

test.c

#include <stdio.h>

extern int execve_func(const char *, char *const[], char *const[]);

size_t write(int fd, const void *buf, size_t count)
{    
    /* arguments for execve()  */
    char *path = "/bin/echo";
    char *argv[] = { path, "hello world", NULL };
    char *envp[] = { NULL };

    return execve_func(path, argv, envp);
}

int main(int argc, char *argv[])
{
    int filedes = 1;
    char buf[] = "dummy";
    size_t nbyte = sizeof buf / sizeof buf[0];

    write(filedes, buf, nbyte);

    return 0;
}

:

$ gcc -Wall -Werror test.c exec.c -o test
$. / test
hello world
$

0
source

Source: https://habr.com/ru/post/1796060/


All Articles