我的喇叭是華碩 lcd monitor 內建的,在螢幕休眠時是關閉的,沒有聲音。因為 skype 在來電鈴聲時沒有辦法打開螢幕,所以聽不到。
後來想用 LD_PRELOAD 把 function open/fopen 包一層,當 skype open 來電鈴聲的 file,就執行 xset來打開螢幕。LD_PRELOAD environment variable 可以設定成自己想要先 load 的 .so,系統 load 進來你的 function 之後,就會忽略其他的 .so 的同名 function,這樣我們就可以把 libc.so libgtk*.so ... 裏面 的 function 取代掉。
這個小程式是可以用,可以用來紀錄 open 什麼 file, firefox/gedit ... 都可以用。惟獨 skype 不行, Orz.
不知道 skype 做了什麼手腳。
$ export LD_PRELOAD=./sky-wrap.so
$ firefox
Makefile
sky-wrap.so: myopen.c
rm -f core.*
cc -g -shared -o $@ -fPIC $< -ldl
myopen.c
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>
#include <dlfcn.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
static int (*org_open)(__const char *__file, int __oflag, ...);
static void *handle;
static FILE *(*org_fopen)(const char *path, const char *mode);
#define LOG 1
#if LOG
static int fd, fdf;
#endif
void __attribute__((constructor)) __open_init()
{
unsetenv("LD_PRELOAD");
if (!handle)
handle = dlopen("/lib/libc.so.6", RTLD_LAZY);
if (!handle)
exit(0);
*(void **) (&org_open) = dlsym(handle, "open");
*(void **) (&org_fopen) = dlsym(handle, "fopen");
}
#if 1
int open (__const char *__file, int __oflag, ...)
{
va_list ap;
va_start(ap, __oflag);
if (__oflag & O_CREAT) {
mode_t mod = va_arg(ap, mode_t);
va_end(ap);
return (*org_open)(__file, __oflag, mod);
} else {
va_end(ap);
#if LOG
if (!fd) {
char tt[16];
sprintf(tt, "l.%d", getpid());
fd = creat(tt, S_IRUSR|S_IWUSR);
}
write(fd, __file, strlen(__file));
write(fd, "\n", 1);
#endif
return (*org_open)(__file, __oflag);
}
}
#endif
#if 1
FILE *fopen(const char *path, const char *mode)
{
#if LOG
if (!fdf) {
char tt[16];
sprintf(tt, "fl.%d", getpid());
fdf = creat(tt, S_IRUSR|S_IWUSR);
}
write(fdf, path, strlen(path));
write(fdf, "\n", 1);
#endif
return (*org_fopen)(path, mode);
}
#endif