包含unistd.h的write()的包装程序例程导致错误 [英] Wrapper routine for write() with unistd.h included results in error

查看:130
本文介绍了包含unistd.h的write()的包装程序例程导致错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为write()编写包装程序以覆盖原始系统功能,并且在其中我需要通过execve()执行另一个程序;为此,我包括头文件unistd.h.我收到错误 conflicting types for 'write' /usr/include/unistd.h:363:16: note: previous declaration of 'write'was here .如果有人可以帮助我,我将不胜感激,因为我需要从包装器内部调用另一个程序,并从包装器例程内部向其发送参数.

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

推荐答案

将GNU内衬--wrap symbol选项用作

An alternative to using the GNU liner --wrap symbol option as suggested by Matthew Slattery would be to use dlsym() to obtain the address of the execve() symbol at runtime in order to avoid the compile-time issues with including unistd.h.

我建议阅读杰伊·康罗德(Jay Conrod)的博客文章,标题为

I suggest reading Jay Conrod's blog post entitled Tutorial: Function Interposition in Linux for additional information on replacing calls to functions in dynamic libraries with calls to your own wrapper functions.

下面的示例提供了一个write()包装函数,该函数在调用execve()之前调用原始的write(),并且不包含unistd.h.重要的是要注意,您不能直接从包装器调用原始write(),因为它将被解释为对包装器本身的递归调用.

The following example provides a write() wrapper function that calls the original write() before calling execve() and does not include unistd.h. It is important to note that you cannot directly call the original write() from the wrapper because it will be interpreted as a recursive call to the wrapper itself.

代码:

Code:

#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;
}

输出:

Output:

$ gcc -Wall -Werror -ldl test.c -o test
$ ./test
write()被称为
你好,世界
$

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

注意:提供此代码是作为可能的示例.我建议遵循 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆