blob: b93a0f9697a39fc2785fc5815eb319415c4e5547 [file] [log] [blame]
Nathan Scott36389fb2021-03-23 15:04:54 +11001/*
2htop - CommandLine.c
3(C) 2004-2011 Hisham H. Muhammad
4(C) 2020-2021 htop dev team
Daniel Lange94ad1112021-09-22 11:33:00 +02005Released under the GNU GPLv2+, see the COPYING file
Nathan Scott36389fb2021-03-23 15:04:54 +11006in the source distribution for its full text.
7*/
8
9#include "config.h" // IWYU pragma: keep
10
11#include "CommandLine.h"
12
13#include <assert.h>
набdfa62502021-10-04 15:08:55 +020014#include <ctype.h>
Nathan Scott36389fb2021-03-23 15:04:54 +110015#include <getopt.h>
16#include <locale.h>
17#include <stdbool.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <time.h>
22#include <unistd.h>
23
24#include "Action.h"
25#include "CRT.h"
Sohaib Mohamed6f2021f2021-07-11 03:11:29 +020026#include "DynamicColumn.h"
Nathan Scottf0ed0fd2021-06-23 17:44:56 +100027#include "DynamicMeter.h"
Sohaib Mohamed53bdcab2023-08-22 16:46:59 +100028#include "DynamicScreen.h"
Nathan Scott36389fb2021-03-23 15:04:54 +110029#include "Hashtable.h"
30#include "Header.h"
31#include "IncSet.h"
Benny Baumanne56089e2023-11-28 15:15:03 +010032#include "Machine.h"
Nathan Scott36389fb2021-03-23 15:04:54 +110033#include "MainPanel.h"
34#include "MetersPanel.h"
35#include "Panel.h"
36#include "Platform.h"
37#include "Process.h"
Nathan Scottb74673f2023-08-31 11:56:43 +100038#include "ProcessTable.h"
Nathan Scott36389fb2021-03-23 15:04:54 +110039#include "ScreenManager.h"
40#include "Settings.h"
Benny Baumanne56089e2023-11-28 15:15:03 +010041#include "Table.h"
Nathan Scott36389fb2021-03-23 15:04:54 +110042#include "UsersTable.h"
43#include "XUtils.h"
44
45
46static void printVersionFlag(const char* name) {
47 printf("%s " VERSION "\n", name);
48}
49
50static void printHelpFlag(const char* name) {
51 printf("%s " VERSION "\n"
Benny Baumann68edf922021-07-14 19:20:16 +020052 COPYRIGHT "\n"
Daniel Lange94ad1112021-09-22 11:33:00 +020053 "Released under the GNU GPLv2+.\n\n"
Benny Baumann68edf922021-07-14 19:20:16 +020054 "-C --no-color Use a monochrome color scheme\n"
55 "-d --delay=DELAY Set the delay between updates, in tenths of seconds\n"
56 "-F --filter=FILTER Show only the commands matching the given filter\n"
57 "-h --help Print this help screen\n"
Daniel Langedf955c82022-04-07 12:33:22 +020058 "-H --highlight-changes[=DELAY] Highlight new and old processes\n", name);
Daniel Lange6a7b3fd2022-04-07 11:52:22 +020059#ifdef HAVE_GETMOUSE
Daniel Langedf955c82022-04-07 12:33:22 +020060 printf("-M --no-mouse Disable the mouse\n");
Daniel Lange6a7b3fd2022-04-07 11:52:22 +020061#endif
Sahil Siddiq87db3792023-01-31 21:20:57 +053062 printf("-n --max-iterations=NUMBER Exit htop after NUMBER iterations/frame updates\n"
63 "-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
Benny Baumann68edf922021-07-14 19:20:16 +020064 " --readonly Disable all system and process changing features\n"
65 "-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n"
66 "-t --tree Show the tree view (can be combined with -s)\n"
67 "-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
68 "-U --no-unicode Do not use unicode but plain ASCII\n"
Daniel Langedf955c82022-04-07 12:33:22 +020069 "-V --version Print version info\n");
Nathan Scott36389fb2021-03-23 15:04:54 +110070 Platform_longOptionsUsage(name);
71 printf("\n"
Benny Baumann68edf922021-07-14 19:20:16 +020072 "Press F1 inside %s for online help.\n"
73 "See 'man %s' for more information.\n", name, name);
Nathan Scott36389fb2021-03-23 15:04:54 +110074}
75
76// ----------------------------------------
77
78typedef struct CommandLineSettings_ {
79 Hashtable* pidMatchList;
80 char* commFilter;
81 uid_t userId;
82 int sortKey;
83 int delay;
Sahil Siddiq87db3792023-01-31 21:20:57 +053084 int iterationsRemaining;
Nathan Scott36389fb2021-03-23 15:04:54 +110085 bool useColors;
Christian Göttsche1b5e0072022-08-09 20:12:08 +020086#ifdef HAVE_GETMOUSE
Nathan Scott36389fb2021-03-23 15:04:54 +110087 bool enableMouse;
Christian Göttsche1b5e0072022-08-09 20:12:08 +020088#endif
Nathan Scott36389fb2021-03-23 15:04:54 +110089 bool treeView;
90 bool allowUnicode;
91 bool highlightChanges;
92 int highlightDelaySecs;
Christian Göttsche36880cd2021-01-21 20:27:37 +010093 bool readonly;
Nathan Scott36389fb2021-03-23 15:04:54 +110094} CommandLineSettings;
95
Nathan Scott14da84f2023-04-04 16:47:11 +100096static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettings* flags) {
Nathan Scott36389fb2021-03-23 15:04:54 +110097
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +030098 *flags = (CommandLineSettings) {
Nathan Scott36389fb2021-03-23 15:04:54 +110099 .pidMatchList = NULL,
100 .commFilter = NULL,
101 .userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2))
102 .sortKey = 0,
103 .delay = -1,
Sahil Siddiq87db3792023-01-31 21:20:57 +0530104 .iterationsRemaining = -1,
Nathan Scott36389fb2021-03-23 15:04:54 +1100105 .useColors = true,
Christian Göttsche1b5e0072022-08-09 20:12:08 +0200106#ifdef HAVE_GETMOUSE
Nathan Scott36389fb2021-03-23 15:04:54 +1100107 .enableMouse = true,
Christian Göttsche1b5e0072022-08-09 20:12:08 +0200108#endif
Nathan Scott36389fb2021-03-23 15:04:54 +1100109 .treeView = false,
110 .allowUnicode = true,
111 .highlightChanges = false,
112 .highlightDelaySecs = -1,
Christian Göttsche36880cd2021-01-21 20:27:37 +0100113 .readonly = false,
Nathan Scott36389fb2021-03-23 15:04:54 +1100114 };
115
116 const struct option long_opts[] =
117 {
118 {"help", no_argument, 0, 'h'},
119 {"version", no_argument, 0, 'V'},
120 {"delay", required_argument, 0, 'd'},
Sahil Siddiq87db3792023-01-31 21:20:57 +0530121 {"max-iterations", required_argument, 0, 'n'},
Nathan Scott36389fb2021-03-23 15:04:54 +1100122 {"sort-key", required_argument, 0, 's'},
123 {"user", optional_argument, 0, 'u'},
124 {"no-color", no_argument, 0, 'C'},
125 {"no-colour", no_argument, 0, 'C'},
126 {"no-mouse", no_argument, 0, 'M'},
127 {"no-unicode", no_argument, 0, 'U'},
128 {"tree", no_argument, 0, 't'},
129 {"pid", required_argument, 0, 'p'},
130 {"filter", required_argument, 0, 'F'},
131 {"highlight-changes", optional_argument, 0, 'H'},
Christian Göttsche36880cd2021-01-21 20:27:37 +0100132 {"readonly", no_argument, 0, 128},
Nathan Scott36389fb2021-03-23 15:04:54 +1100133 PLATFORM_LONG_OPTIONS
Benny Baumann0d85af22021-07-14 19:18:27 +0200134 {0, 0, 0, 0}
Nathan Scott36389fb2021-03-23 15:04:54 +1100135 };
136
Benny Baumann0d85af22021-07-14 19:18:27 +0200137 int opt, opti = 0;
Nathan Scott36389fb2021-03-23 15:04:54 +1100138 /* Parse arguments */
Sahil Siddiq87db3792023-01-31 21:20:57 +0530139 while ((opt = getopt_long(argc, argv, "hVMCs:td:n:u::Up:F:H::", long_opts, &opti))) {
Benny Baumanne7f8d7b2021-07-14 19:11:18 +0200140 if (opt == EOF)
141 break;
Benny Baumann6aa9ef22023-11-23 12:22:02 +0100142
Nathan Scott36389fb2021-03-23 15:04:54 +1100143 switch (opt) {
144 case 'h':
145 printHelpFlag(program);
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300146 return STATUS_OK_EXIT;
Nathan Scott36389fb2021-03-23 15:04:54 +1100147 case 'V':
148 printVersionFlag(program);
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300149 return STATUS_OK_EXIT;
Nathan Scott36389fb2021-03-23 15:04:54 +1100150 case 's':
151 assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
152 if (String_eq(optarg, "help")) {
153 for (int j = 1; j < LAST_PROCESSFIELD; j++) {
154 const char* name = Process_fields[j].name;
155 const char* description = Process_fields[j].description;
Benny Baumann40104582022-10-22 19:19:39 +0200156 if (name)
157 printf("%19s %s\n", name, description);
Nathan Scott36389fb2021-03-23 15:04:54 +1100158 }
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300159 return STATUS_OK_EXIT;
Nathan Scott36389fb2021-03-23 15:04:54 +1100160 }
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300161 flags->sortKey = 0;
Nathan Scott36389fb2021-03-23 15:04:54 +1100162 for (int j = 1; j < LAST_PROCESSFIELD; j++) {
163 if (Process_fields[j].name == NULL)
164 continue;
165 if (String_eq(optarg, Process_fields[j].name)) {
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300166 flags->sortKey = j;
Nathan Scott36389fb2021-03-23 15:04:54 +1100167 break;
168 }
169 }
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300170 if (flags->sortKey == 0) {
Nathan Scott36389fb2021-03-23 15:04:54 +1100171 fprintf(stderr, "Error: invalid column \"%s\".\n", optarg);
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300172 return STATUS_ERROR_EXIT;
Nathan Scott36389fb2021-03-23 15:04:54 +1100173 }
174 break;
175 case 'd':
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300176 if (sscanf(optarg, "%16d", &(flags->delay)) == 1) {
Benny Baumann40104582022-10-22 19:19:39 +0200177 if (flags->delay < 1)
178 flags->delay = 1;
179 if (flags->delay > 100)
180 flags->delay = 100;
Nathan Scott36389fb2021-03-23 15:04:54 +1100181 } else {
182 fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg);
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300183 return STATUS_ERROR_EXIT;
Nathan Scott36389fb2021-03-23 15:04:54 +1100184 }
185 break;
Sahil Siddiq87db3792023-01-31 21:20:57 +0530186 case 'n':
187 if (sscanf(optarg, "%16d", &flags->iterationsRemaining) == 1) {
188 if (flags->iterationsRemaining <= 0) {
189 fprintf(stderr, "Error: maximum iteration count must be positive.\n");
190 return STATUS_ERROR_EXIT;
191 }
192 } else {
193 fprintf(stderr, "Error: invalid maximum iteration count \"%s\".\n", optarg);
194 return STATUS_ERROR_EXIT;
195 }
196 break;
Benny Baumann6aa9ef22023-11-23 12:22:02 +0100197 case 'u': {
Benny Baumann40104582022-10-22 19:19:39 +0200198 const char* username = optarg;
Nathan Scott36389fb2021-03-23 15:04:54 +1100199 if (!username && optind < argc && argv[optind] != NULL &&
200 (argv[optind][0] != '\0' && argv[optind][0] != '-')) {
201 username = argv[optind++];
202 }
203
204 if (!username) {
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300205 flags->userId = geteuid();
206 } else if (!Action_setUserOnly(username, &(flags->userId))) {
Benny Baumann40104582022-10-22 19:19:39 +0200207 for (const char* itr = username; *itr; ++itr)
набdfa62502021-10-04 15:08:55 +0200208 if (!isdigit((unsigned char)*itr)) {
209 fprintf(stderr, "Error: invalid user \"%s\".\n", username);
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300210 return STATUS_ERROR_EXIT;
набdfa62502021-10-04 15:08:55 +0200211 }
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300212 flags->userId = atol(username);
Nathan Scott36389fb2021-03-23 15:04:54 +1100213 }
214 break;
215 }
216 case 'C':
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300217 flags->useColors = false;
Nathan Scott36389fb2021-03-23 15:04:54 +1100218 break;
219 case 'M':
niae8f27eb2021-07-14 21:07:43 +0200220#ifdef HAVE_GETMOUSE
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300221 flags->enableMouse = false;
niae8f27eb2021-07-14 21:07:43 +0200222#endif
Nathan Scott36389fb2021-03-23 15:04:54 +1100223 break;
224 case 'U':
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300225 flags->allowUnicode = false;
Nathan Scott36389fb2021-03-23 15:04:54 +1100226 break;
227 case 't':
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300228 flags->treeView = true;
Nathan Scott36389fb2021-03-23 15:04:54 +1100229 break;
230 case 'p': {
231 assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
232 char* argCopy = xStrdup(optarg);
233 char* saveptr;
234 const char* pid = strtok_r(argCopy, ",", &saveptr);
235
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300236 if (!flags->pidMatchList) {
237 flags->pidMatchList = Hashtable_new(8, false);
Nathan Scott36389fb2021-03-23 15:04:54 +1100238 }
239
Benny Baumann40104582022-10-22 19:19:39 +0200240 while (pid) {
241 unsigned int num_pid = atoi(pid);
242 // deepcode ignore CastIntegerToAddress: we just want a non-NULL pointer here
243 Hashtable_put(flags->pidMatchList, num_pid, (void*) 1);
244 pid = strtok_r(NULL, ",", &saveptr);
Nathan Scott36389fb2021-03-23 15:04:54 +1100245 }
246 free(argCopy);
247
248 break;
249 }
Benny Baumann6aa9ef22023-11-23 12:22:02 +0100250 case 'F':
Nathan Scott36389fb2021-03-23 15:04:54 +1100251 assert(optarg);
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300252 free_and_xStrdup(&flags->commFilter, optarg);
Nathan Scott36389fb2021-03-23 15:04:54 +1100253 break;
Nathan Scott36389fb2021-03-23 15:04:54 +1100254 case 'H': {
Benny Baumann40104582022-10-22 19:19:39 +0200255 const char* delay = optarg;
Nathan Scott36389fb2021-03-23 15:04:54 +1100256 if (!delay && optind < argc && argv[optind] != NULL &&
257 (argv[optind][0] != '\0' && argv[optind][0] != '-')) {
Benny Baumann40104582022-10-22 19:19:39 +0200258 delay = argv[optind++];
Nathan Scott36389fb2021-03-23 15:04:54 +1100259 }
260 if (delay) {
Benny Baumann40104582022-10-22 19:19:39 +0200261 if (sscanf(delay, "%16d", &(flags->highlightDelaySecs)) == 1) {
262 if (flags->highlightDelaySecs < 1)
263 flags->highlightDelaySecs = 1;
264 } else {
265 fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
266 return STATUS_ERROR_EXIT;
267 }
Nathan Scott36389fb2021-03-23 15:04:54 +1100268 }
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300269 flags->highlightChanges = true;
Nathan Scott36389fb2021-03-23 15:04:54 +1100270 break;
271 }
Christian Göttsche36880cd2021-01-21 20:27:37 +0100272 case 128:
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300273 flags->readonly = true;
Christian Göttsche36880cd2021-01-21 20:27:37 +0100274 break;
Nathan Scott36389fb2021-03-23 15:04:54 +1100275
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300276 default: {
277 CommandLineStatus status;
278 if ((status = Platform_getLongOption(opt, argc, argv)) != STATUS_OK)
279 return status;
280 break;
281 }
Nathan Scott36389fb2021-03-23 15:04:54 +1100282 }
283 }
Christian Göttsche2f387af2022-10-20 14:57:42 +0200284
285 if (optind < argc) {
286 fprintf(stderr, "Error: unsupported non-option ARGV-elements:");
287 while (optind < argc)
288 fprintf(stderr, " %s", argv[optind++]);
289 fprintf(stderr, "\n");
290 return STATUS_ERROR_EXIT;
291 }
292
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300293 return STATUS_OK;
Nathan Scott36389fb2021-03-23 15:04:54 +1100294}
295
Nathan Scott0bdade12023-05-02 09:02:22 +1000296static void CommandLine_delay(Machine* host, unsigned long millisec) {
Nathan Scott36389fb2021-03-23 15:04:54 +1100297 struct timespec req = {
298 .tv_sec = 0,
299 .tv_nsec = millisec * 1000000L
300 };
Nathan Scott36756112021-04-08 09:26:48 +1000301 while (nanosleep(&req, &req) == -1)
Nathan Scott36389fb2021-03-23 15:04:54 +1100302 continue;
Nathan Scott0bdade12023-05-02 09:02:22 +1000303 Platform_gettime_realtime(&host->realtime, &host->realtimeMs);
Nathan Scott36389fb2021-03-23 15:04:54 +1100304}
305
306static void setCommFilter(State* state, char** commFilter) {
Nathan Scott0f751e92023-08-22 16:11:05 +1000307 Table* table = state->host->activeTable;
Nathan Scott36389fb2021-03-23 15:04:54 +1100308 IncSet* inc = state->mainPanel->inc;
309
310 IncSet_setFilter(inc, *commFilter);
Nathan Scott0f751e92023-08-22 16:11:05 +1000311 table->incFilter = IncSet_filter(inc);
Nathan Scott36389fb2021-03-23 15:04:54 +1100312
313 free(*commFilter);
314 *commFilter = NULL;
315}
316
Nathan Scott14da84f2023-04-04 16:47:11 +1000317int CommandLine_run(int argc, char** argv) {
Nathan Scott36389fb2021-03-23 15:04:54 +1100318
319 /* initialize locale */
320 const char* lc_ctype;
321 if ((lc_ctype = getenv("LC_CTYPE")) || (lc_ctype = getenv("LC_ALL")))
322 setlocale(LC_CTYPE, lc_ctype);
323 else
324 setlocale(LC_CTYPE, "");
325
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300326 CommandLineStatus status = STATUS_OK;
327 CommandLineSettings flags = { 0 };
328
Nathan Scott14da84f2023-04-04 16:47:11 +1000329 if ((status = parseArguments(argc, argv, &flags)) != STATUS_OK)
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300330 return status != STATUS_OK_EXIT ? 1 : 0;
Nathan Scott36389fb2021-03-23 15:04:54 +1100331
Christian Göttsche36880cd2021-01-21 20:27:37 +0100332 if (flags.readonly)
333 Settings_enableReadonly();
334
Volodymyr Vasiutyk2ef70ad2021-10-06 10:45:07 +0300335 if (!Platform_init())
336 return 1;
Nathan Scott36389fb2021-03-23 15:04:54 +1100337
Nathan Scott36389fb2021-03-23 15:04:54 +1100338 UsersTable* ut = UsersTable_new();
Nathan Scottf0ed0fd2021-06-23 17:44:56 +1000339 Hashtable* dm = DynamicMeters_new();
Nathan Scotte7f447b2023-04-04 16:24:37 +1000340 Hashtable* dc = DynamicColumns_new();
Sohaib Mohamed53bdcab2023-08-22 16:46:59 +1000341 Hashtable* ds = DynamicScreens_new();
Nathan Scott36389fb2021-03-23 15:04:54 +1100342
Nathan Scott0bdade12023-05-02 09:02:22 +1000343 Machine* host = Machine_new(ut, flags.userId);
Nathan Scottb74673f2023-08-31 11:56:43 +1000344 ProcessTable* pt = ProcessTable_new(host, flags.pidMatchList);
Nathan Scottf3306db2024-09-03 17:39:17 +1000345 Settings* settings = Settings_new(host, dm, dc, ds);
Nathan Scottb74673f2023-08-31 11:56:43 +1000346 Machine_populateTablesFromSettings(host, settings, &pt->super);
Nathan Scott36389fb2021-03-23 15:04:54 +1100347
Nathan Scott0bdade12023-05-02 09:02:22 +1000348 Header* header = Header_new(host, 2);
Nathan Scott36389fb2021-03-23 15:04:54 +1100349 Header_populateFromSettings(header);
350
351 if (flags.delay != -1)
352 settings->delay = flags.delay;
353 if (!flags.useColors)
354 settings->colorScheme = COLORSCHEME_MONOCHROME;
niae8f27eb2021-07-14 21:07:43 +0200355#ifdef HAVE_GETMOUSE
Nathan Scott36389fb2021-03-23 15:04:54 +1100356 if (!flags.enableMouse)
357 settings->enableMouse = false;
niae8f27eb2021-07-14 21:07:43 +0200358#endif
Nathan Scott36389fb2021-03-23 15:04:54 +1100359 if (flags.treeView)
Hisham Muhammad72ba20f2021-08-31 15:38:52 +1000360 settings->ss->treeView = true;
Nathan Scott36389fb2021-03-23 15:04:54 +1100361 if (flags.highlightChanges)
362 settings->highlightChanges = true;
363 if (flags.highlightDelaySecs != -1)
364 settings->highlightDelaySecs = flags.highlightDelaySecs;
365 if (flags.sortKey > 0) {
366 // -t -s <key> means "tree sorted by key"
367 // -s <key> means "list sorted by key" (previous existing behavior)
368 if (!flags.treeView) {
Hisham Muhammad72ba20f2021-08-31 15:38:52 +1000369 settings->ss->treeView = false;
Nathan Scott36389fb2021-03-23 15:04:54 +1100370 }
Hisham Muhammad72ba20f2021-08-31 15:38:52 +1000371 ScreenSettings_setSortKey(settings->ss, flags.sortKey);
Nathan Scott36389fb2021-03-23 15:04:54 +1100372 }
373
Sahil Siddiq87db3792023-01-31 21:20:57 +0530374 host->iterationsRemaining = flags.iterationsRemaining;
Sahil Siddiqdc883b22023-05-22 11:09:11 +0530375 CRT_init(settings, flags.allowUnicode, flags.iterationsRemaining != -1);
Nathan Scott36389fb2021-03-23 15:04:54 +1100376
377 MainPanel* panel = MainPanel_new();
Sohaib Mohamed53bdcab2023-08-22 16:46:59 +1000378 Machine_setTablesPanel(host, (Panel*) panel);
Nathan Scott36389fb2021-03-23 15:04:54 +1100379
Daniel Langec6f946e2022-03-25 14:51:14 +0100380 MainPanel_updateLabels(panel, settings->ss->treeView, flags.commFilter);
Nathan Scott36389fb2021-03-23 15:04:54 +1100381
382 State state = {
Nathan Scott0bdade12023-05-02 09:02:22 +1000383 .host = host,
Nathan Scott36389fb2021-03-23 15:04:54 +1100384 .mainPanel = panel,
385 .header = header,
Nathan Scotte4ebe182023-02-14 11:51:54 +1100386 .pauseUpdate = false,
387 .hideSelection = false,
Christian Göttsche15fe50d2022-10-20 15:03:17 +0200388 .hideMeters = false,
Nathan Scott36389fb2021-03-23 15:04:54 +1100389 };
390
391 MainPanel_setState(panel, &state);
392 if (flags.commFilter)
393 setCommFilter(&state, &(flags.commFilter));
394
Nathan Scott0bdade12023-05-02 09:02:22 +1000395 ScreenManager* scr = ScreenManager_new(header, host, &state, true);
Nathan Scott36389fb2021-03-23 15:04:54 +1100396 ScreenManager_add(scr, (Panel*) panel, -1);
397
Nathan Scott72235d82023-05-02 16:56:18 +1000398 Machine_scan(host);
Nathan Scott0f751e92023-08-22 16:11:05 +1000399 Machine_scanTables(host);
Nathan Scott0bdade12023-05-02 09:02:22 +1000400 CommandLine_delay(host, 75);
Nathan Scott72235d82023-05-02 16:56:18 +1000401 Machine_scan(host);
Nathan Scott0f751e92023-08-22 16:11:05 +1000402 Machine_scanTables(host);
Nathan Scott36389fb2021-03-23 15:04:54 +1100403
Hisham Muhammad72ba20f2021-08-31 15:38:52 +1000404 if (settings->ss->allBranchesCollapsed)
Nathan Scottb74673f2023-08-31 11:56:43 +1000405 Table_collapseAllBranches(&pt->super);
Nathan Scott36389fb2021-03-23 15:04:54 +1100406
Hisham Muhammad72ba20f2021-08-31 15:38:52 +1000407 ScreenManager_run(scr, NULL, NULL, NULL);
Nathan Scott36389fb2021-03-23 15:04:54 +1100408
Nathan Scott36389fb2021-03-23 15:04:54 +1100409 Platform_done();
410
411 CRT_done();
412
413 if (settings->changed) {
Sefa Eyeogluf7c9ede2024-03-12 09:49:28 +0100414#ifndef NDEBUG
415 if (!String_eq(settings->initialFilename, settings->filename))
416 fprintf(stderr, "Configuration %s was resolved to %s\n", settings->initialFilename, settings->filename);
417#endif /* NDEBUG */
Christian Göttsche1f5f40c2021-05-16 19:55:31 +0200418 int r = Settings_write(settings, false);
Nathan Scott36389fb2021-03-23 15:04:54 +1100419 if (r < 0)
420 fprintf(stderr, "Can not save configuration to %s: %s\n", settings->filename, strerror(-r));
421 }
422
423 Header_delete(header);
Nathan Scott0bdade12023-05-02 09:02:22 +1000424 Machine_delete(host);
Nathan Scott36389fb2021-03-23 15:04:54 +1100425
426 ScreenManager_delete(scr);
427 MetersPanel_cleanup();
428
429 UsersTable_delete(ut);
Nathan Scott36389fb2021-03-23 15:04:54 +1100430
431 if (flags.pidMatchList)
432 Hashtable_delete(flags.pidMatchList);
433
Christian Göttsche68460b22021-08-14 19:52:26 +0200434 CRT_resetSignalHandlers();
435
Sohaib Mohamed6f2021f2021-07-11 03:11:29 +0200436 /* Delete these last, since they can get accessed in the crash handler */
Christian Göttsche1f5f40c2021-05-16 19:55:31 +0200437 Settings_delete(settings);
Nathan Scottc0c2bb92021-09-03 12:11:31 +1000438 DynamicColumns_delete(dc);
439 DynamicMeters_delete(dm);
Sohaib Mohamed53bdcab2023-08-22 16:46:59 +1000440 DynamicScreens_delete(ds);
Christian Göttsche1f5f40c2021-05-16 19:55:31 +0200441
Nathan Scott36389fb2021-03-23 15:04:54 +1100442 return 0;
443}