2006-11-26 11:13:41 -07:00
|
|
|
|
|
|
|
#ifdef HAVE_XORG_CONFIG_H
|
|
|
|
#include <xorg-config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include "xf86_OSlib.h"
|
|
|
|
#include "xf86.h"
|
|
|
|
|
|
|
|
#define MODPROBE_PATH_FILE "/proc/sys/kernel/modprobe"
|
|
|
|
#define MAX_PATH 1024
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* XFree86 #defines execl to be the xf86execl() function which does
|
|
|
|
* a fork AND exec. We don't want that. We want the regular,
|
|
|
|
* standard execl().
|
|
|
|
*/
|
|
|
|
#ifdef execl
|
|
|
|
#undef execl
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load a Linux kernel module.
|
|
|
|
* This is used by the DRI/DRM to load a DRM kernel module when
|
|
|
|
* the X server starts. It could be used for other purposes in the future.
|
|
|
|
* Input:
|
|
|
|
* modName - name of the kernel module (Ex: "tdfx")
|
|
|
|
* Return:
|
|
|
|
* 0 for failure, 1 for success
|
|
|
|
*/
|
2010-07-27 13:02:24 -06:00
|
|
|
int
|
2006-11-26 11:13:41 -07:00
|
|
|
xf86LoadKernelModule(const char *modName)
|
|
|
|
{
|
2012-06-10 07:21:05 -06:00
|
|
|
char mpPath[MAX_PATH] = "";
|
|
|
|
int fd = -1, status, n;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
/* get the path to the modprobe program */
|
|
|
|
fd = open(MODPROBE_PATH_FILE, O_RDONLY);
|
|
|
|
if (fd >= 0) {
|
|
|
|
int count = read(fd, mpPath, MAX_PATH - 1);
|
|
|
|
|
|
|
|
if (count <= 0) {
|
|
|
|
mpPath[0] = 0;
|
|
|
|
}
|
|
|
|
else if (mpPath[count - 1] == '\n') {
|
|
|
|
mpPath[count - 1] = 0; /* replaces \n with \0 */
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
/* if this worked, mpPath will be "/sbin/modprobe" or similar. */
|
|
|
|
}
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2012-06-10 07:21:05 -06:00
|
|
|
if (mpPath[0] == 0) {
|
|
|
|
/* we failed to get the path from the system, use a default */
|
|
|
|
strcpy(mpPath, "/sbin/modprobe");
|
|
|
|
}
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2012-06-10 07:21:05 -06:00
|
|
|
/* now fork/exec the modprobe command */
|
|
|
|
/*
|
|
|
|
* It would be good to capture stdout/stderr so that it can be directed
|
|
|
|
* to the log file. modprobe errors currently are missing from the log
|
|
|
|
* file.
|
|
|
|
*/
|
|
|
|
switch (pid = fork()) {
|
|
|
|
case 0: /* child */
|
|
|
|
/* change real/effective user ID to 0/0 as we need to
|
|
|
|
* preinstall agpgart module for some DRM modules
|
|
|
|
*/
|
|
|
|
if (setreuid(0, 0)) {
|
|
|
|
xf86Msg(X_WARNING, "LoadKernelModule: "
|
|
|
|
"Setting of real/effective user Id to 0/0 failed");
|
|
|
|
}
|
|
|
|
setenv("PATH", "/sbin", 1);
|
|
|
|
n = execl(mpPath, "modprobe", modName, NULL);
|
|
|
|
xf86Msg(X_WARNING, "LoadKernelModule %s\n", strerror(errno));
|
|
|
|
exit(EXIT_FAILURE); /* if we get here the child's exec failed */
|
|
|
|
break;
|
|
|
|
case -1: /* fork failed */
|
|
|
|
return 0;
|
|
|
|
default: /* fork worked */
|
|
|
|
{
|
|
|
|
/* XXX we loop over waitpid() because it sometimes fails on
|
|
|
|
* the first attempt. Don't know why!
|
|
|
|
*/
|
|
|
|
int count = 0, p;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2012-06-10 07:21:05 -06:00
|
|
|
do {
|
2006-11-26 11:13:41 -07:00
|
|
|
p = waitpid(pid, &status, 0);
|
2012-06-10 07:21:05 -06:00
|
|
|
} while (p == -1 && count++ < 4);
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2012-06-10 07:21:05 -06:00
|
|
|
if (p == -1) {
|
2006-11-26 11:13:41 -07:00
|
|
|
return 0;
|
2012-06-10 07:21:05 -06:00
|
|
|
}
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2012-06-10 07:21:05 -06:00
|
|
|
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
|
|
|
return 1; /* success! */
|
|
|
|
}
|
|
|
|
else {
|
2006-11-26 11:13:41 -07:00
|
|
|
return 0;
|
2012-06-10 07:21:05 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2012-06-10 07:21:05 -06:00
|
|
|
/* never get here */
|
|
|
|
return 0;
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|