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