Improved to "half-way usable" (version 0.5)
[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 PIRModprobe::PIRModprobe()
12   : successfullyLoadedModule(false)
13 {
14 }
15
16
17 PIRModprobe::~PIRModprobe()
18 {
19   if (successfullyLoadedModule)
20   {
21     unloadRX51Module();
22   }
23 }
24
25
26 int PIRModprobe::loadRX51Module()
27 {
28   // First, has the module already been loaded?  If /dev/lirc0 exists, it
29   // should already be there:
30   struct stat statBuffer;
31   if (stat("/dev/lirc0", &statBuffer) == 0)
32   {
33     // "/dev/lirc0" exists, so no need to do anything:
34     successfullyLoadedModule = false;
35     return 0;
36   }
37
38   // Do the hard work: start by forking off a child process:
39   pid_t pid = fork();
40
41   if (pid == -1)
42   {
43     // The fork failed!  Tell our user about the error:
44     std::stringstream ss;
45     ss << "Failed to fork a child process.\n";
46     ss << "Error returned was: " << strerror(errno) << "\n";
47     PIRException e(ss.str());
48     e.display();
49     return -1;
50   }
51   else if (pid == 0)
52   {
53     // We're inside the child process, so exec the load module script:
54     execl(
55       "/usr/bin/sudo",
56       "/usr/bin/sudo",
57       "/opt/pierogi/bin/loadRX51Module",
58       NULL);
59
60     // The execl call should overwrite the child process.  So, if we still
61     // exist at this point, an error has occurred:
62     std::stringstream ss;
63     ss << "Failed to successfully call execl().\n";
64     ss << "Error returned was: " << strerror(errno) << "\n";
65     PIRException e(ss.str());
66     e.display();
67     return -1;
68   }
69
70   // If we reach this point, we are inside the parent process.  So, we'll wait
71   // for the child process to complete:
72   int *stat_loc = NULL;
73   if (waitpid(pid, stat_loc, 0) == -1)
74   {
75     // The call to modprobe failed.
76     std::stringstream ss;
77     ss << "Call to modprobe failed.\n";
78     ss << "Error returned was: " << strerror(errno) << "\n";
79     PIRException e(ss.str());
80     e.display();
81     return -1;
82   }
83
84   if (stat_loc)
85   {
86     if (WIFEXITED(*stat_loc) == 0)
87     {
88       // modprobe encountered an error of some sort.
89       std::stringstream ss;
90       ss << "Unable to load the lirc_rx51 module.\n";
91       // Need better details about the error here!
92       PIRException e(ss.str());
93       e.display();
94       return -1;
95     }
96   }
97
98   // By this point, we should have successfully loaded module.
99   successfullyLoadedModule = true;
100
101   return 0;
102 }
103
104
105 int PIRModprobe::unloadRX51Module()
106 {
107   // start by forking off a child process:
108   pid_t pid = fork();
109
110   if (pid == -1)
111   {
112     // The fork failed!  Tell our user about the error:
113     std::stringstream ss;
114     ss << "Failed to fork a child process.\n";
115     ss << "Error returned was: " << strerror(errno) << "\n";
116     PIRException e(ss.str());
117     e.display();
118     return -1;
119   }
120   else if (pid == 0)
121   {
122     // We're inside the child process, so exec the unload script:
123     execl(
124       "/usr/bin/sudo",
125       "/usr/bin/sudo",
126       "/opt/pierogi/bin/unloadRX51Module",
127       NULL);
128
129     // The execl call should overwrite the child process.  So, if we still
130     // exist at this point, an error has occurred:
131     std::stringstream ss;
132     ss << "Failed to successfully call execl().\n";
133     ss << "Error returned was: " << strerror(errno) << "\n";
134     PIRException e(ss.str());
135     e.display();
136     return -1;
137   }
138
139   // If we reach this point, we are inside the parent process.  So, we'll wait
140   // for the child process to complete:
141   int *stat_loc = NULL;
142   if (waitpid(pid, stat_loc, 0) == -1)
143   {
144     // The call to modprobe failed.
145     std::stringstream ss;
146     ss << "Call to modprobe failed.\n";
147     ss << "Error returned was: " << strerror(errno) << "\n";
148     PIRException e(ss.str());
149     e.display();
150     return -1;
151   }
152
153   if (stat_loc)
154   {
155     if (WIFEXITED(*stat_loc) == 0)
156     {
157       // modprobe encountered an error of some sort.
158       std::stringstream ss;
159       ss << "Unable to unload the lirc_rx51 module.\n";
160       // Need better details about the error here!
161       PIRException e(ss.str());
162       e.display();
163       return -1;
164     }
165   }
166
167   // If we reach this point, module has been unloaded successfully:
168   successfullyLoadedModule = false;
169
170   return 0;
171 }