blob: 142a712325e66adfb7bab6715b841c5d30c2b06e [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Aatir7b291ec2019-11-19 10:37:37 -060016#include "config.h"
17
18#include "../bcd_time.hpp"
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +080019#include "../json_utils.hpp"
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080020#include "../paths.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050021#include "../pel.hpp"
Aatir7b291ec2019-11-19 10:37:37 -060022#include "../pel_types.hpp"
23#include "../pel_values.hpp"
Aatir186ce8c2019-10-20 15:13:39 -050024
25#include <CLI/CLI.hpp>
Aatir7b291ec2019-11-19 10:37:37 -060026#include <bitset>
Aatir186ce8c2019-10-20 15:13:39 -050027#include <iostream>
Aatir7b291ec2019-11-19 10:37:37 -060028#include <phosphor-logging/log.hpp>
29#include <regex>
Aatir186ce8c2019-10-20 15:13:39 -050030#include <string>
Aatir7b291ec2019-11-19 10:37:37 -060031#include <xyz/openbmc_project/Common/File/error.hpp>
Aatir186ce8c2019-10-20 15:13:39 -050032
Aatir7b291ec2019-11-19 10:37:37 -060033namespace fs = std::filesystem;
Aatir186ce8c2019-10-20 15:13:39 -050034using namespace phosphor::logging;
35using namespace openpower::pels;
Matt Spinler27de6f32020-02-21 08:35:57 -060036using sdbusplus::exception::SdBusError;
Aatir7b291ec2019-11-19 10:37:37 -060037namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
38namespace message = openpower::pels::message;
39namespace pv = openpower::pels::pel_values;
Aatir186ce8c2019-10-20 15:13:39 -050040
Matt Spinler27de6f32020-02-21 08:35:57 -060041using PELFunc = std::function<void(const PEL&)>;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +080042message::Registry registry(getMessageRegistryPath() /
43 message::registryFileName);
Matt Spinler27de6f32020-02-21 08:35:57 -060044namespace service
45{
46constexpr auto logging = "xyz.openbmc_project.Logging";
47} // namespace service
48
49namespace interface
50{
51constexpr auto deleteObj = "xyz.openbmc_project.Object.Delete";
52constexpr auto deleteAll = "xyz.openbmc_project.Collection.DeleteAll";
53} // namespace interface
54
55namespace object_path
56{
57constexpr auto logEntry = "/xyz/openbmc_project/logging/entry/";
58constexpr auto logging = "/xyz/openbmc_project/logging";
59} // namespace object_path
60
Aatire340c132019-12-09 14:19:29 -060061/**
Aatir37822f62019-12-10 14:40:27 -060062 * @brief helper function to get PEL commit timestamp from file name
63 * @retrun BCDTime - PEL commit timestamp
64 * @param[in] std::string - file name
65 */
66BCDTime fileNameToTimestamp(const std::string& fileName)
67{
68 std::string token = fileName.substr(0, fileName.find("_"));
69 int i = 0;
70 BCDTime tmp;
71 if (token.length() >= 14)
72 {
73 try
74 {
75 tmp.yearMSB = std::stoi(token.substr(i, 2), 0, 16);
76 }
77 catch (std::exception& err)
78 {
79 std::cout << "Conversion failure: " << err.what() << std::endl;
80 }
81 i += 2;
82 try
83 {
84 tmp.yearLSB = std::stoi(token.substr(i, 2), 0, 16);
85 }
86 catch (std::exception& err)
87 {
88 std::cout << "Conversion failure: " << err.what() << std::endl;
89 }
90 i += 2;
91 try
92 {
93 tmp.month = std::stoi(token.substr(i, 2), 0, 16);
94 }
95 catch (std::exception& err)
96 {
97 std::cout << "Conversion failure: " << err.what() << std::endl;
98 }
99 i += 2;
100 try
101 {
102 tmp.day = std::stoi(token.substr(i, 2), 0, 16);
103 }
104 catch (std::exception& err)
105 {
106 std::cout << "Conversion failure: " << err.what() << std::endl;
107 }
108 i += 2;
109 try
110 {
111 tmp.hour = std::stoi(token.substr(i, 2), 0, 16);
112 }
113 catch (std::exception& err)
114 {
115 std::cout << "Conversion failure: " << err.what() << std::endl;
116 }
117 i += 2;
118 try
119 {
120 tmp.minutes = std::stoi(token.substr(i, 2), 0, 16);
121 }
122 catch (std::exception& err)
123 {
124 std::cout << "Conversion failure: " << err.what() << std::endl;
125 }
126 i += 2;
127 try
128 {
129 tmp.seconds = std::stoi(token.substr(i, 2), 0, 16);
130 }
131 catch (std::exception& err)
132 {
133 std::cout << "Conversion failure: " << err.what() << std::endl;
134 }
135 i += 2;
136 try
137 {
138 tmp.hundredths = std::stoi(token.substr(i, 2), 0, 16);
139 }
140 catch (std::exception& err)
141 {
142 std::cout << "Conversion failure: " << err.what() << std::endl;
143 }
144 }
145 return tmp;
146}
147
148/**
149 * @brief helper function to get PEL id from file name
150 * @retrun uint32_t - PEL id
151 * @param[in] std::string - file name
152 */
153uint32_t fileNameToPELId(const std::string& fileName)
154{
155 uint32_t num = 0;
156 try
157 {
158 num = std::stoi(fileName.substr(fileName.find("_") + 1), 0, 16);
159 }
160 catch (std::exception& err)
161 {
162 std::cout << "Conversion failure: " << err.what() << std::endl;
163 }
164 return num;
165}
166
167/**
Aatire340c132019-12-09 14:19:29 -0600168 * @brief helper function to check string suffix
169 * @retrun bool - true with suffix matches
170 * @param[in] std::string - string to check for suffix
171 * @param[in] std::string - suffix string
172 */
173bool ends_with(const std::string& str, const std::string& end)
174{
175 size_t slen = str.size(), elen = end.size();
176 if (slen < elen)
177 return false;
178 while (elen)
179 {
180 if (str[--slen] != end[--elen])
181 return false;
182 }
183 return true;
184}
185
Aatir37822f62019-12-10 14:40:27 -0600186/**
187 * @brief get data form raw PEL file.
188 * @param[in] std::string Name of file with raw PEL
189 * @return std::vector<uint8_t> char vector read from raw PEL file.
190 */
Aatirbad5f8a2019-12-10 15:27:16 -0600191std::vector<uint8_t> getFileData(const std::string& name)
Aatir37822f62019-12-10 14:40:27 -0600192{
193 std::ifstream file(name, std::ifstream::in);
194 if (file.good())
195 {
196 std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
197 std::istreambuf_iterator<char>()};
198 return data;
199 }
200 else
201 {
Aatir37822f62019-12-10 14:40:27 -0600202 return {};
203 }
204}
205
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800206/**
207 * @brief Creates JSON string of a PEL entry if fullPEL is false or prints to
208 * stdout the full PEL in JSON if fullPEL is true
209 * @param[in] itr - std::map iterator of <uint32_t, BCDTime>
210 * @param[in] hidden - Boolean to include hidden PELs
211 * @param[in] fullPEL - Boolean to print full JSON representation of PEL
212 * @param[in] foundPEL - Boolean to check if any PEL is present
213 * @return std::string - JSON string of PEL entry (empty if fullPEL is true)
214 */
Aatir7b291ec2019-11-19 10:37:37 -0600215template <typename T>
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800216std::string genPELJSON(T itr, bool hidden, bool fullPEL, bool& foundPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600217{
218 std::size_t found;
219 std::string val;
220 char tmpValStr[50];
221 std::string listStr;
222 char name[50];
223 sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", itr.second.yearMSB,
224 itr.second.yearLSB, itr.second.month, itr.second.day,
225 itr.second.hour, itr.second.minutes, itr.second.seconds,
226 itr.second.hundredths, itr.first);
227 std::string fileName(name);
228 fileName = EXTENSION_PERSIST_DIR "/pels/logs/" + fileName;
229 try
230 {
Aatir37822f62019-12-10 14:40:27 -0600231 std::vector<uint8_t> data = getFileData(fileName);
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800232 if (data.empty())
Aatir37822f62019-12-10 14:40:27 -0600233 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800234 log<level::ERR>("Empty PEL file",
235 entry("FILENAME=%s", fileName.c_str()));
236 return listStr;
237 }
238 PEL pel{data};
239 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
240 if (pel.valid() && (hidden || !actionFlags.test(hiddenFlagBit)))
241 {
242 if (fullPEL)
243 {
244 if (!foundPEL)
245 {
246 std::cout << "[" << std::endl;
247 foundPEL = true;
248 }
249 else
250 {
251 std::cout << ",\n" << std::endl;
252 }
253 pel.toJSON(registry);
254 }
255 else
Aatir7b291ec2019-11-19 10:37:37 -0600256 {
Aatir37822f62019-12-10 14:40:27 -0600257 // id
258 sprintf(tmpValStr, "0x%X", pel.privateHeader().id());
259 val = std::string(tmpValStr);
260 listStr += "\t\"" + val + "\": {\n";
261 // ASCII
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800262 if (pel.primarySRC())
263 {
264 val = pel.primarySRC().value()->asciiString();
265 listStr += "\t\t\"SRC\": \"" +
266 val.substr(0, val.find(0x20)) + "\",\n";
267 // Registry message
268 auto regVal = pel.primarySRC().value()->getErrorDetails(
269 registry, DetailLevel::message, true);
270 if (regVal)
271 {
272 val = regVal.value();
273 listStr += "\t\t\"Message\": \"" + val + "\",\n";
274 }
275 }
276 else
277 {
278 listStr += "\t\t\"SRC\": \"No SRC\",\n";
279 }
Aatir37822f62019-12-10 14:40:27 -0600280 // platformid
281 sprintf(tmpValStr, "0x%X", pel.privateHeader().plid());
282 val = std::string(tmpValStr);
283 listStr += "\t\t\"PLID\": \"" + val + "\",\n";
284 // creatorid
285 sprintf(tmpValStr, "%c", pel.privateHeader().creatorID());
286 std::string creatorID(tmpValStr);
287 val = pv::creatorIDs.count(creatorID)
288 ? pv::creatorIDs.at(creatorID)
289 : "Unknown Creator ID";
290 listStr += "\t\t\"CreatorID\": \"" + val + "\",\n";
291 // subsytem
292 std::string subsystem = pv::getValue(
293 pel.userHeader().subsystem(), pel_values::subsystemValues);
294 listStr += "\t\t\"Subsystem\": \"" + subsystem + "\",\n";
295 // commit time
Harisuddin Mohamed Isa160c51c2020-02-13 23:42:20 +0800296 sprintf(tmpValStr, "%02X/%02X/%02X%02X %02X:%02X:%02X",
Aatir37822f62019-12-10 14:40:27 -0600297 pel.privateHeader().commitTimestamp().month,
298 pel.privateHeader().commitTimestamp().day,
299 pel.privateHeader().commitTimestamp().yearMSB,
300 pel.privateHeader().commitTimestamp().yearLSB,
301 pel.privateHeader().commitTimestamp().hour,
302 pel.privateHeader().commitTimestamp().minutes,
303 pel.privateHeader().commitTimestamp().seconds);
304 val = std::string(tmpValStr);
305 listStr += "\t\t\"Commit Time\": \"" + val + "\",\n";
306 // severity
307 std::string severity = pv::getValue(pel.userHeader().severity(),
308 pel_values::severityValues);
309 listStr += "\t\t\"Sev\": \"" + severity + "\",\n ";
310 // compID
311 sprintf(tmpValStr, "0x%X",
312 pel.privateHeader().header().componentID);
313 val = std::string(tmpValStr);
314 listStr += "\t\t\"CompID\": \"" + val + "\",\n ";
315
316 found = listStr.rfind(",");
317 if (found != std::string::npos)
318 {
319 listStr.replace(found, 1, "");
320 listStr += "\t}, \n";
321 }
Aatir7b291ec2019-11-19 10:37:37 -0600322 }
323 }
324 }
325 catch (std::exception& e)
326 {
327 log<level::ERR>("Hit exception while reading PEL File",
328 entry("FILENAME=%s", fileName.c_str()),
329 entry("ERROR=%s", e.what()));
330 }
331 return listStr;
332}
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800333
Aatir7b291ec2019-11-19 10:37:37 -0600334/**
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800335 * @brief Print a list of PELs or a JSON array of PELs
336 * @param[in] order - Boolean to print in reverse orser
337 * @param[in] hidden - Boolean to include hidden PELs
338 * @param[in] fullPEL - Boolean to print full PEL into a JSON array
Aatir7b291ec2019-11-19 10:37:37 -0600339 */
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800340void printPELs(bool order, bool hidden, bool fullPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600341{
342 std::string listStr;
343 std::map<uint32_t, BCDTime> PELs;
Aatir7b291ec2019-11-19 10:37:37 -0600344 listStr = "{\n";
345 for (auto it = fs::directory_iterator(EXTENSION_PERSIST_DIR "/pels/logs");
346 it != fs::directory_iterator(); ++it)
347 {
348 if (!fs::is_regular_file((*it).path()))
349 {
350 continue;
351 }
Aatir37822f62019-12-10 14:40:27 -0600352 else
Aatir7b291ec2019-11-19 10:37:37 -0600353 {
Aatir37822f62019-12-10 14:40:27 -0600354 PELs.emplace(fileNameToPELId((*it).path().filename()),
355 fileNameToTimestamp((*it).path().filename()));
Aatir7b291ec2019-11-19 10:37:37 -0600356 }
357 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800358 bool foundPEL = false;
359 auto buildJSON = [&listStr, &hidden, &fullPEL, &foundPEL](const auto& i) {
360 listStr += genPELJSON(i, hidden, fullPEL, foundPEL);
Aatir37822f62019-12-10 14:40:27 -0600361 };
Aatir7b291ec2019-11-19 10:37:37 -0600362 if (order)
363 {
364 std::for_each(PELs.rbegin(), PELs.rend(), buildJSON);
365 }
366 else
367 {
368 std::for_each(PELs.begin(), PELs.end(), buildJSON);
369 }
370
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800371 if (!fullPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600372 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800373 std::size_t found;
374 found = listStr.rfind(",");
375 if (found != std::string::npos)
376 {
377 listStr.replace(found, 1, "");
378 listStr += "\n}\n";
379 printf("%s", listStr.c_str());
380 }
381 }
382 else if (foundPEL)
383 {
384 std::cout << "]" << std::endl;
Aatir7b291ec2019-11-19 10:37:37 -0600385 }
386}
Aatir186ce8c2019-10-20 15:13:39 -0500387
Matt Spinler27de6f32020-02-21 08:35:57 -0600388/**
389 * @brief Calls the function passed in on the PEL with the ID
390 * passed in.
391 *
392 * @param[in] id - The string version of the PEL ID, either with or
393 * without the 0x prefix.
394 * @param[in] func - The std::function<void(const PEL&)> function to run.
395 */
396void callFunctionOnPEL(const std::string& id, const PELFunc& func)
397{
398 std::string pelID{id};
399 std::transform(pelID.begin(), pelID.end(), pelID.begin(), toupper);
400
401 if (pelID.find("0X") == 0)
402 {
403 pelID.erase(0, 2);
404 }
405
406 bool found = false;
407
408 for (auto it = fs::directory_iterator(EXTENSION_PERSIST_DIR "/pels/logs");
409 it != fs::directory_iterator(); ++it)
410 {
411 // The PEL ID is part of the filename, so use that to find the PEL.
412
413 if (!fs::is_regular_file((*it).path()))
414 {
415 continue;
416 }
417
418 if (ends_with((*it).path(), pelID))
419 {
420 found = true;
421
422 auto data = getFileData((*it).path());
423 if (!data.empty())
424 {
425 PEL pel{data};
426
427 try
428 {
429 func(pel);
430 }
431 catch (std::exception& e)
432 {
433 std::cerr
434 << " Internal function threw an exception: " << e.what()
435 << "\n";
436 exit(1);
437 }
438 }
439 else
440 {
441 std::cerr << "Could not read PEL file\n";
442 exit(1);
443 }
444 break;
445 }
446 }
447
448 if (!found)
449 {
450 std::cerr << "PEL not found\n";
451 exit(1);
452 }
453}
454
455/**
456 * @brief Delete a PEL by deleting its corresponding event log.
457 *
458 * @param[in] pel - The PEL to delete
459 */
460void deletePEL(const PEL& pel)
461{
462 std::string path{object_path::logEntry};
463 path += std::to_string(pel.obmcLogID());
464
465 try
466 {
467 auto bus = sdbusplus::bus::new_default();
468 auto method = bus.new_method_call(service::logging, path.c_str(),
469 interface::deleteObj, "Delete");
470 auto reply = bus.call(method);
471 }
472 catch (const SdBusError& e)
473 {
474 std::cerr << "D-Bus call to delete event log " << pel.obmcLogID()
475 << " failed: " << e.what() << "\n";
476 exit(1);
477 }
478}
479
480/**
481 * @brief Delete all PELs by deleting all event logs.
482 */
483void deleteAllPELs()
484{
485 try
486 {
487 // This may move to an audit log some day
488 log<level::INFO>("peltool deleting all event logs");
489
490 auto bus = sdbusplus::bus::new_default();
491 auto method =
492 bus.new_method_call(service::logging, object_path::logging,
493 interface::deleteAll, "DeleteAll");
494 auto reply = bus.call(method);
495 }
496 catch (const SdBusError& e)
497 {
498 std::cerr << "D-Bus call to delete all event logs failed: " << e.what()
499 << "\n";
500 exit(1);
501 }
502}
503
Matt Spinler1b420bc2020-02-21 08:54:25 -0600504/**
505 * @brief Display a single PEL
506 *
507 * @param[in] pel - the PEL to display
508 */
509void displayPEL(const PEL& pel)
510{
511 if (pel.valid())
512 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800513 pel.toJSON(registry);
Matt Spinler1b420bc2020-02-21 08:54:25 -0600514 }
515 else
516 {
517 std::cerr << "PEL was malformed\n";
518 exit(1);
519 }
520}
521
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800522/**
523 * @brief Print number of PELs
524 * @param[in] hidden - Bool to include hidden logs
525 */
526void printPELCount(bool hidden)
527{
528 std::size_t count = 0;
529 for (auto it = fs::directory_iterator(EXTENSION_PERSIST_DIR "/pels/logs");
530 it != fs::directory_iterator(); ++it)
531 {
532 if (!fs::is_regular_file((*it).path()))
533 {
534 continue;
535 }
536 else
537 {
538 std::vector<uint8_t> data = getFileData((*it).path());
539 if (!data.empty())
540 {
541 PEL pel{data};
542 std::bitset<16> actionFlags{pel.userHeader().actionFlags()};
543 if (pel.valid() && (hidden || !actionFlags.test(hiddenFlagBit)))
544 {
545 count++;
546 }
547 }
548 }
549 }
550 std::cout << "{\n"
551 << " \"Number of PELs found\": "
552 << getNumberString("%d", count) << "\n}" << std::endl;
553}
554
Aatir186ce8c2019-10-20 15:13:39 -0500555static void exitWithError(const std::string& help, const char* err)
556{
557 std::cerr << "ERROR: " << err << std::endl << help << std::endl;
558 exit(-1);
559}
560
561int main(int argc, char** argv)
562{
563 CLI::App app{"OpenBMC PEL Tool"};
564 std::string fileName;
Aatire340c132019-12-09 14:19:29 -0600565 std::string idPEL;
Matt Spinler27de6f32020-02-21 08:35:57 -0600566 std::string idToDelete;
Aatire340c132019-12-09 14:19:29 -0600567 bool listPEL = false;
568 bool listPELDescOrd = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800569 bool hidden = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600570 bool deleteAll = false;
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800571 bool showPELCount = false;
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800572 bool fullPEL = false;
Matt Spinler27de6f32020-02-21 08:35:57 -0600573
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800574 app.set_help_flag("--help", "Print this help message and exit");
Aatire340c132019-12-09 14:19:29 -0600575 app.add_option("-f,--file", fileName,
576 "Display a PEL using its Raw PEL file");
577 app.add_option("-i, --id", idPEL, "Display a PEL based on its ID");
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800578 app.add_flag("-a", fullPEL, "Display all PELs");
Aatirbad5f8a2019-12-10 15:27:16 -0600579 app.add_flag("-l", listPEL, "List PELs");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800580 app.add_flag("-n", showPELCount, "Show number of PELs");
Aatir7b291ec2019-11-19 10:37:37 -0600581 app.add_flag("-r", listPELDescOrd, "Reverse order of output");
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800582 app.add_flag("-h", hidden, "Include hidden PELs");
Matt Spinler27de6f32020-02-21 08:35:57 -0600583 app.add_option("-d, --delete", idToDelete, "Delete a PEL based on its ID");
584 app.add_flag("-D, --delete-all", deleteAll, "Delete all PELs");
585
Aatir186ce8c2019-10-20 15:13:39 -0500586 CLI11_PARSE(app, argc, argv);
587
588 if (!fileName.empty())
589 {
590 std::vector<uint8_t> data = getFileData(fileName);
591 if (!data.empty())
592 {
593 PEL pel{data};
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800594 pel.toJSON(registry);
Aatir186ce8c2019-10-20 15:13:39 -0500595 }
596 else
597 {
598 exitWithError(app.help("", CLI::AppFormatMode::All),
599 "Raw PEL file can't be read.");
600 }
601 }
Aatire340c132019-12-09 14:19:29 -0600602 else if (!idPEL.empty())
603 {
Matt Spinler1b420bc2020-02-21 08:54:25 -0600604 callFunctionOnPEL(idPEL, displayPEL);
Aatire340c132019-12-09 14:19:29 -0600605 }
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800606 else if (fullPEL || listPEL)
Aatir7b291ec2019-11-19 10:37:37 -0600607 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800608 printPELs(listPELDescOrd, hidden, fullPEL);
Harisuddin Mohamed Isad4002f32020-02-26 16:19:58 +0800609 }
610 else if (showPELCount)
611 {
612 printPELCount(hidden);
Aatir7b291ec2019-11-19 10:37:37 -0600613 }
Matt Spinler27de6f32020-02-21 08:35:57 -0600614 else if (!idToDelete.empty())
615 {
616 callFunctionOnPEL(idToDelete, deletePEL);
617 }
618 else if (deleteAll)
619 {
620 deleteAllPELs();
621 }
Aatir186ce8c2019-10-20 15:13:39 -0500622 else
623 {
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800624 std::cout << app.help("", CLI::AppFormatMode::All) << std::endl;
Aatir186ce8c2019-10-20 15:13:39 -0500625 }
626 return 0;
627}