1 /*
2 *
3 * program: sanityCheck
4 * file: main.c
5 * author: Todd Naugle
6 * date: 11/17/2010
7 *
8 * Desc: Command line version of the sanity check functions found in jack
9 */
10
11 #include <algorithm>
12 #include <stdio.h>
13 #include <string>
14 #include <vector>
15
16 #include "systemtest.h"
17
18
19 using namespace std;
20
21 typedef int (*testfuncPtr) ();
22 typedef int (*testfuncOpPtr) (string);
23
24 typedef struct
25 {
26 string switchText; // ie -option
27 string swOptionText; // option arguments for just this swtich.
28 string descriptionText; // Help Text on what this does
29 string failureText; // What to say when this test fails
30 bool hasOption; // Set true if this switch has option paramters
31 testfuncPtr functionPtr; // Function to call
32 testfuncOpPtr opFunctionPtr; // Function with option string to call
33 string optionArg; // Storage used to hold any options passed in by the user
34 } testRecord;
35
36 static vector<testRecord> gTestSet;
37
38 static vector<string> gValidSwitchList;
39 static vector<string> gSwitchDescriptionList;
40
41 static vector<string> gSwitchesReceived;
42
43 int
ExecuteAll()44 ExecuteAll()
45 {
46 bool OK = true;
47
48 OK &= system_user_can_rtprio();
49
50 if (system_has_frequencyscaling()) {
51 OK &= !system_uses_frequencyscaling();
52 }
53
54 OK &= !(system_memlock_amount() == 0);
55
56 return OK;
57 }
58
59 int
HasGroup(string name)60 HasGroup(string name)
61 {
62 return system_has_group(name.c_str());
63 }
64
65 int
IsMemberOfGroup(string name)66 IsMemberOfGroup(string name)
67 {
68 return system_user_in_group(name.c_str());
69 }
70
71 int
CheckFreqScaling()72 CheckFreqScaling()
73 {
74 bool OK = true;
75
76 if (system_has_frequencyscaling()) {
77 OK &= !system_uses_frequencyscaling();
78 }
79
80 return OK;
81 }
82
83 int
CheckMemoryLocking()84 CheckMemoryLocking()
85 {
86 return !(system_memlock_amount() == 0);
87 }
88
89 int
PrintUsage()90 PrintUsage()
91 {
92 printf("\n");
93 printf(" sanityCheck - A program to verify proper system settings for use with audio applications (Ardour/Jack/Mixbus).\n");
94 printf("\n");
95 printf(" Usage: sanityCheck [OPTIONS]\n");
96 printf("\n");
97 printf(" Options are as follows:\n");
98 printf("\n");
99 printf("\n");
100
101 vector<testRecord>::iterator itr;
102
103 for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
104 printf("%20s %s :\t%s\n", (*itr).switchText.c_str(), (*itr).swOptionText.c_str(), (*itr).descriptionText.c_str());
105 }
106
107 printf("\n");
108
109 return true;
110 }
111
112 void
DefineSwitches()113 DefineSwitches()
114 {
115 testRecord rec;
116
117 // Global switches
118 rec.switchText = "-a";
119 rec.swOptionText = "";
120 rec.descriptionText = "Checks for a working RT system. Same as -rt -freqscaling -memlock";
121 rec.failureText = "";
122 rec.hasOption = false;
123 rec.functionPtr = &ExecuteAll;
124 rec.optionArg = "";
125 gTestSet.push_back(rec);
126
127 rec.switchText = "-h";
128 rec.swOptionText = "";
129 rec.descriptionText = "Print usage";
130 rec.failureText = "";
131 rec.hasOption = false;
132 rec.functionPtr = &PrintUsage;
133 rec.optionArg = "";
134 gTestSet.push_back(rec);
135
136 // Switches for various tests that can be performed.
137 rec.switchText = "-rt";
138 rec.swOptionText = "";
139 rec.descriptionText = "Verify that the user can run tasks with realtime priority";
140 rec.failureText = "";
141 rec.hasOption = false;
142 rec.functionPtr = &system_user_can_rtprio;
143 rec.optionArg = "";
144 gTestSet.push_back(rec);
145
146 rec.switchText = "-hasrtlimits";
147 rec.swOptionText = "";
148 rec.descriptionText = "Verify the system has a limits.conf and the audio group can use realtime";
149 rec.failureText = "";
150 rec.hasOption = false;
151 rec.functionPtr = &system_has_rtprio_limits_conf;
152 rec.optionArg = "";
153 gTestSet.push_back(rec);
154
155 rec.switchText = "-hasgroup";
156 rec.swOptionText = "<groupname>";
157 rec.descriptionText = "Verify that the system has a group named <groupname>";
158 rec.failureText = "";
159 rec.hasOption = true;
160 rec.opFunctionPtr = &HasGroup;
161 rec.optionArg = "";
162 gTestSet.push_back(rec);
163
164 rec.switchText = "-hasaudiogroup";
165 rec.swOptionText = "";
166 rec.descriptionText = "Verify that the system has an audio group (audio or jackuser) defined";
167 rec.failureText = "";
168 rec.hasOption = false;
169 rec.functionPtr = &system_has_audiogroup;
170 rec.optionArg = "";
171 gTestSet.push_back(rec);
172
173 rec.switchText = "-memberofgroup";
174 rec.swOptionText = "<groupname>";
175 rec.descriptionText = "Verify that the user is a member of the group named <groupname>";
176 rec.failureText = "";
177 rec.hasOption = true;
178 rec.opFunctionPtr = &IsMemberOfGroup;
179 rec.optionArg = "";
180 gTestSet.push_back(rec);
181
182 rec.switchText = "-memberaudiogroup";
183 rec.swOptionText = "";
184 rec.descriptionText = "Verify that the user is a member of the audio group (audio or jackuser)";
185 rec.failureText = "";
186 rec.hasOption = false;
187 rec.functionPtr = &system_user_in_audiogroup;
188 rec.optionArg = "";
189 gTestSet.push_back(rec);
190
191 rec.switchText = "-freqscaling";
192 rec.swOptionText = "";
193 rec.descriptionText = "Check to see if frequency scaling is being used by the CPU";
194 rec.failureText = "";
195 rec.hasOption = false;
196 rec.functionPtr = &CheckFreqScaling;
197 rec.optionArg = "";
198 gTestSet.push_back(rec);
199
200 rec.switchText = "-memlock";
201 rec.swOptionText = "";
202 rec.descriptionText = "Check to see if the user is able to lock memory";
203 rec.failureText = "";
204 rec.hasOption = false;
205 rec.functionPtr = &CheckMemoryLocking;
206 rec.optionArg = "";
207 gTestSet.push_back(rec);
208
209 }
210
211 bool
ParseSwitches(int argc,char ** argv)212 ParseSwitches(
213 int argc,
214 char **argv)
215 {
216 string tmp;
217 vector<testRecord>::iterator itr;
218 bool OK = true;
219 int i;
220
221 if (argc == 1) {
222 gSwitchesReceived.push_back("-a");
223 }
224 else {
225 for (i = 1; i < argc && OK == true; i++) {
226 tmp = argv[i];
227
228 for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
229 if (tmp == (*itr).switchText) {
230 if ((*itr).hasOption == true) {
231 if (++i < argc) {
232 string op = argv[i];
233 if (op[0] == '-') {
234 // reqiured option for this switch is missing
235 --i;
236 OK = false;
237 break;
238 }
239 (*itr).optionArg = op;
240 break;
241 }
242 else {
243 // reqiured option for this switch is missing
244 --i;
245 OK = false;
246 break;
247 }
248 }
249 break;
250 }
251 }
252
253 if (OK && itr != gTestSet.end()) {
254 // Known option switch found
255 gSwitchesReceived.push_back(tmp);
256 }
257 else {
258 // Unknown option
259 OK = false;
260 }
261 }
262 }
263
264 if (OK) {
265 // All switches are at least valid, now check to make sure they are all valid to
266 // be used together.
267
268 if (gSwitchesReceived.size() > 1) {
269 // make sure help is not mixed with other options
270 vector<string>::iterator swItr;
271 tmp = "-h";
272
273 swItr = find(gSwitchesReceived.begin(), gSwitchesReceived.end(), tmp);
274
275 if (swItr != gSwitchesReceived.end()) {
276 gSwitchesReceived.clear();
277 gSwitchesReceived.push_back("-h");
278 }
279
280 // make sure -a is only used by itself
281 tmp = "-a";
282 swItr = find(gSwitchesReceived.begin(), gSwitchesReceived.end(), tmp);
283
284 if (swItr != gSwitchesReceived.end()) {
285 gSwitchesReceived.clear();
286 gSwitchesReceived.push_back("-a");
287 }
288 }
289
290 return true;
291 }
292 else {
293 fprintf(stderr, "\n");
294 fprintf(stderr, "ERROR - Invalid Option: %s\n", (const char *) argv[--i]);
295 fprintf(stderr, "Check syntax\n");
296 PrintUsage();
297 return false;
298 }
299 }
300
301 bool
Execute()302 Execute()
303 {
304 bool OK = true;
305 vector<string>::iterator itr;
306 vector<testRecord>::iterator testItr;
307
308 for (itr = gSwitchesReceived.begin(); itr != gSwitchesReceived.end(); ++itr) {
309 for (testItr = gTestSet.begin(); testItr != gTestSet.end(); ++testItr) {
310 if ((*itr) == (*testItr).switchText) {
311 break;
312 }
313 }
314
315 bool result;
316 if ((*testItr).hasOption) {
317 result = ((*testItr).opFunctionPtr((*testItr).optionArg) != 0);
318 }
319 else {
320 result = ((*testItr).functionPtr() != 0);
321 }
322
323 if (result == 0) {
324 // Check for a Failure message and print it if found.
325 if (!(*testItr).failureText.empty()) {
326 printf("\n%s\n", (*testItr).failureText.c_str());
327 }
328 }
329
330 OK &= result;
331 }
332
333 return OK;
334 }
335
336 int
main(int argc,char ** argv)337 main(
338 int argc,
339 char **argv)
340 {
341 int status = 0;
342
343 DefineSwitches();
344
345 if (ParseSwitches(argc, argv)) {
346 if (Execute() == false) {
347 printf("\nSanity Check Failed!\n\n");
348 status = -1;
349 }
350 else {
351 printf("\nSanity Check OK!\n\n");
352 }
353 }
354 else {
355 status = -1;
356 }
357
358 return status;
359 }
360