Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / linux / lnx_kmod.c
CommitLineData
a09e091a
JB
1
2#ifdef HAVE_XORG_CONFIG_H
3#include <xorg-config.h>
4#endif
5
6#include <errno.h>
7#include <fcntl.h>
8#include <unistd.h>
9#include <sys/wait.h>
10#include <signal.h>
11#include "xf86_OSlib.h"
12#include "xf86.h"
13
14#define MODPROBE_PATH_FILE "/proc/sys/kernel/modprobe"
15#define MAX_PATH 1024
16
17#if 0
18/* XFree86 #defines execl to be the xf86execl() function which does
19 * a fork AND exec. We don't want that. We want the regular,
20 * standard execl().
21 */
22#ifdef execl
23#undef execl
24#endif
25#endif
26
27/*
28 * Load a Linux kernel module.
29 * This is used by the DRI/DRM to load a DRM kernel module when
30 * the X server starts. It could be used for other purposes in the future.
31 * Input:
32 * modName - name of the kernel module (Ex: "tdfx")
33 * Return:
34 * 0 for failure, 1 for success
35 */
36int
37xf86LoadKernelModule(const char *modName)
38{
39 char mpPath[MAX_PATH] = "";
40 int fd = -1, status, n;
41 pid_t pid;
42
43 /* get the path to the modprobe program */
44 fd = open(MODPROBE_PATH_FILE, O_RDONLY);
45 if (fd >= 0) {
46 int count = read(fd, mpPath, MAX_PATH - 1);
47
48 if (count <= 0) {
49 mpPath[0] = 0;
50 }
51 else if (mpPath[count - 1] == '\n') {
52 mpPath[count - 1] = 0; /* replaces \n with \0 */
53 }
54 close(fd);
55 /* if this worked, mpPath will be "/sbin/modprobe" or similar. */
56 }
57
58 if (mpPath[0] == 0) {
59 /* we failed to get the path from the system, use a default */
60 strcpy(mpPath, "/sbin/modprobe");
61 }
62
63 /* now fork/exec the modprobe command */
64 /*
65 * It would be good to capture stdout/stderr so that it can be directed
66 * to the log file. modprobe errors currently are missing from the log
67 * file.
68 */
69 switch (pid = fork()) {
70 case 0: /* child */
71 /* change real/effective user ID to 0/0 as we need to
72 * preinstall agpgart module for some DRM modules
73 */
74 if (setreuid(0, 0)) {
75 xf86Msg(X_WARNING, "LoadKernelModule: "
76 "Setting of real/effective user Id to 0/0 failed");
77 }
78 setenv("PATH", "/sbin", 1);
79 n = execl(mpPath, "modprobe", modName, NULL);
80 xf86Msg(X_WARNING, "LoadKernelModule %s\n", strerror(errno));
81 exit(EXIT_FAILURE); /* if we get here the child's exec failed */
82 break;
83 case -1: /* fork failed */
84 return 0;
85 default: /* fork worked */
86 {
87 /* XXX we loop over waitpid() because it sometimes fails on
88 * the first attempt. Don't know why!
89 */
90 int count = 0, p;
91
92 do {
93 p = waitpid(pid, &status, 0);
94 } while (p == -1 && count++ < 4);
95
96 if (p == -1) {
97 return 0;
98 }
99
100 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
101 return 1; /* success! */
102 }
103 else {
104 return 0;
105 }
106 }
107 }
108
109 /* never get here */
110 return 0;
111}