Maintenance plus Initial Website
[pierogi] / pirmodprobe.cpp
1 #include "pirmodprobe.h"
2
3 #include <unistd.h> // for fork()
4 #include <sys/types.h> // for pid_t
5 #include <sys/wait.h> // for waitpid()
6 #include "pirexception.h"
7 #include <sstream>
8 #include <errno.h>
9 #include <sys/stat.h>
10
11
12 PIRModprobe::PIRModprobe()
13   : successfullyLoadedModule(false)
14 {
15 }
16
17
18 PIRModprobe::~PIRModprobe()
19 {
20   if (successfullyLoadedModule)
21   {
22     unloadRX51Module();
23   }
24 }
25
26
27 int PIRModprobe::modprobeRX51Module(
28   bool unloadModule)
29 {
30   // First, has the module already been loaded?  If /dev/lirc0 exists, it
31   // should already be there:
32   struct stat statBuffer;
33   if (stat("/dev/lirc0", &statBuffer) == 0)
34   {
35     // "/dev/lirc0" exists, so no need to do anything:
36     return 0;
37   }
38
39   // Do the hard work: start by forking off a child process:
40   pid_t pid = fork();
41
42   if (pid == -1)
43   {
44     // The fork failed!  Tell our user about the error:
45     std::stringstream ss;
46     ss << "Failed to fork a child process.\n";
47     ss << "Error returned was: " << strerror(errno) << "\n";
48     PIRException e(ss.str());
49     e.display();
50     return -1;
51   }
52   else if (pid == 0)
53   {
54     // We're inside the child process, so exec a modprobe:
55     if (unloadModule)
56     {
57       execl(
58         "/usr/bin/sudo",
59         "/usr/bin/sudo",
60         "/opt/pierogi/bin/unloadRX51Module",
61         NULL);
62     }
63     else
64     {
65       execl(
66         "/usr/bin/sudo",
67         "/usr/bin/sudo",
68         "/opt/pierogi/bin/loadRX51Module",
69         NULL);
70     }
71     // The execl call should overwrite the child process.  So, if we still
72     // exist at this point, an error has occurred:
73     std::stringstream ss;
74     ss << "Failed to successfully call execl().\n";
75     ss << "Error returned was: " << strerror(errno) << "\n";
76     PIRException e(ss.str());
77     e.display();
78     return -1;
79   }
80
81   // If we reach this point, we are inside the parent process.  So, we'll wait
82   // for the child process to complete:
83   int *stat_loc = NULL;
84   if (waitpid(pid, stat_loc, 0) == -1)
85   {
86     // The call to modprobe failed.
87     std::stringstream ss;
88     ss << "Call to modprobe failed.\n";
89     ss << "Error returned was: " << strerror(errno) << "\n";
90     PIRException e(ss.str());
91     e.display();
92     return -1;
93   }
94
95   if (stat_loc)
96   {
97     if (WIFEXITED(*stat_loc) == 0)
98     {
99       // modprobe encountered an error of some sort.
100       std::stringstream ss;
101       ss << "Unable to load the lirc_rx51 module.\n";
102       // Need better details about the error here!
103       PIRException e(ss.str());
104       e.display();
105       return -1;
106     }
107   }
108
109   // By this point, we should have successfully ensured the module is loaded.
110   successfullyLoadedModule = true;
111
112   return 0;
113 }