Subversion Repositories Kolibri OS

Rev

Rev 9337 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9325 Boppan 1
/*
2
    UMKa - User-Mode KolibriOS developer tools
3
    umka_shell - interactive shell
4
    Copyright (C) 2018--2020  Ivan Baravy 
5
 
6
    This program is free software: you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation, either version 2 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program.  If not, see .
18
*/
19
 
20
#include 
21
#include 
22
#include 
23
#include 
24
#include 
25
#include 
26
#include 
27
#include 
9337 Boppan 28
 
29
#include "getopt.h"
9325 Boppan 30
#include "vdisk.h"
31
#include "umka.h"
32
#include "trace.h"
33
#include "pci.h"
34
#include "lodepng.h"
35
 
36
#define PATH_MAX 4096
37
#define FGETS_BUF_LEN 4096
38
#define MAX_COMMAND_ARGS 42
39
#define PRINT_BYTES_PER_LINE 32
40
#define MAX_DIRENTS_TO_READ 100
41
#define MAX_BYTES_TO_READ (1024*1024)
42
 
43
#define DEFAULT_READDIR_ENCODING UTF8
44
#define DEFAULT_PATH_ENCODING UTF8
45
 
46
FILE *fin, *fout;
47
 
48
char cur_dir[PATH_MAX] = "/";
49
const char *last_dir = cur_dir;
50
bool cur_dir_changed = true;
51
 
52
char cmd_buf[FGETS_BUF_LEN];
53
 
54
typedef struct {
55
    char *name;
56
    void (*func) (int, char **);
57
} func_table_t;
58
 
59
const char *f70_status_name[] = {
60
                                 "success",
61
                                 "disk_base",
62
                                 "unsupported_fs",
63
                                 "unknown_fs",
64
                                 "partition",
65
                                 "file_not_found",
66
                                 "end_of_file",
67
                                 "memory_pointer",
68
                                 "disk_full",
69
                                 "fs_fail",
70
                                 "access_denied",
71
                                 "device",
72
                                 "out_of_memory"
73
                                };
74
 
75
static const char *
76
get_f70_status_name(int s) {
77
    switch (s) {
78
    case ERROR_SUCCESS:
79
//        return "";
80
    case ERROR_DISK_BASE:
81
    case ERROR_UNSUPPORTED_FS:
82
    case ERROR_UNKNOWN_FS:
83
    case ERROR_PARTITION:
84
    case ERROR_FILE_NOT_FOUND:
85
    case ERROR_END_OF_FILE:
86
    case ERROR_MEMORY_POINTER:
87
    case ERROR_DISK_FULL:
88
    case ERROR_FS_FAIL:
89
    case ERROR_ACCESS_DENIED:
90
    case ERROR_DEVICE:
91
    case ERROR_OUT_OF_MEMORY:
92
        return f70_status_name[s];
93
    default:
94
        return "unknown";
95
    }
96
}
97
 
98
static void
99
convert_f70_file_attr(uint32_t attr, char s[KF_ATTR_CNT+1]) {
100
    s[0] = (attr & KF_READONLY) ? 'r' : '-';
101
    s[1] = (attr & KF_HIDDEN)   ? 'h' : '-';
102
    s[2] = (attr & KF_SYSTEM)   ? 's' : '-';
103
    s[3] = (attr & KF_LABEL)    ? 'l' : '-';
104
    s[4] = (attr & KF_FOLDER)   ? 'f' : '-';
105
    s[5] = '\0';
106
}
107
 
108
static void
109
print_f70_status(f7080ret_t *r, int use_ebx) {
110
    fprintf(fout, "status = %d %s", r->status, get_f70_status_name(r->status));
111
    if (use_ebx &&
112
        (r->status == ERROR_SUCCESS || r->status == ERROR_END_OF_FILE))
113
        fprintf(fout, ", count = %d", r->count);
114
    fputc('\n', fout);
115
}
116
 
117
static bool
118
parse_uintmax(const char *str, uintmax_t *res) {
119
    char *endptr;
120
    *res = strtoumax(str, &endptr, 0);
121
    bool ok = (str != endptr) && (*endptr == '\0');
122
    return ok;
123
}
124
 
125
static bool
126
parse_uint32(const char *str, uint32_t *res) {
127
    uintmax_t x;
128
    if (parse_uintmax(str, &x) && x <= UINT32_MAX) {
129
        *res = (uint32_t)x;
130
        return true;
131
    } else {
132
        perror("invalid number");
133
        return false;
134
    }
135
}
136
 
137
static bool
138
parse_uint64(const char *str, uint64_t *res) {
139
    uintmax_t x;
140
    if (parse_uintmax(str, &x) && x <= UINT64_MAX) {
141
        *res = x;
142
        return true;
143
    } else {
144
        perror("invalid number");
145
        return false;
146
    }
147
}
148
 
149
static void
150
print_bytes(uint8_t *x, size_t len) {
151
    for (size_t i = 0; i < len; i++) {
152
        if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) {
153
            fputc('\n', fout);
154
        }
155
        fprintf(fout, "%2.2x", x[i]);
156
    }
157
    fputc('\n', fout);
158
}
159
 
160
static void
161
print_hash(uint8_t *x, size_t len) {
162
    hash_context ctx;
163
    hash_oneshot(&ctx, x, len);
164
    for (size_t i = 0; i < HASH_SIZE; i++) {
165
        fprintf(fout, "%2.2x", ctx.hash[i]);
166
    }
167
    fputc('\n', fout);
168
}
169
 
170
static const char *
171
get_last_dir(const char *path) {
172
    const char *last = strrchr(path, '/');
173
    if (!last) {
174
        last = path;
175
    } else if (last != path || last[1] != '\0') {
176
        last++;
177
    }
178
    return last;
179
}
180
 
181
static void
182
prompt() {
183
    if (cur_dir_changed) {
184
        if (umka_initialized) {
185
            COVERAGE_ON();
186
            umka_sys_get_cwd(cur_dir, PATH_MAX);
187
            COVERAGE_OFF();
188
        }
189
        last_dir = get_last_dir(cur_dir);
190
        cur_dir_changed = false;
191
    }
192
    fprintf(fout, "%s> ", last_dir);
193
    fflush(fout);
194
}
195
 
196
static int
9337 Boppan 197
next_line(int is_tty) {
9325 Boppan 198
    if (is_tty) {
199
        prompt();
200
    }
9337 Boppan 201
    return fgets(cmd_buf, FGETS_BUF_LEN, fin) != NULL;
9325 Boppan 202
}
203
 
204
static int
205
split_args(char *s, char **argv) {
206
    int argc = -1;
207
    for (; (argv[++argc] = strtok(s, " \t\n\r")) != NULL; s = NULL);
208
    return argc;
209
}
210
 
211
static void
212
shell_umka_init(int argc, char **argv) {
213
    const char *usage = \
214
        "usage: umka_init";
215
    (void)argv;
216
    if (argc < 0) {
217
        fputs(usage, fout);
218
        return;
219
    }
220
    COVERAGE_ON();
221
    umka_init();
222
    COVERAGE_OFF();
223
}
224
 
225
static void
226
shell_umka_set_boot_params(int argc, char **argv) {
227
    const char *usage = \
228
        "usage: umka_set_boot_params [--x_res ] [--y_res ]\n"
229
        "  --x_res     screen width\n"
230
        "  --y_res     screen height";
231
 
232
    argc -= 1;
233
    argv += 1;
234
 
235
    while (argc) {
236
        if (!strcmp(argv[0], "--x_res") && argc > 1) {
237
            kos_boot.x_res = strtoul(argv[1], NULL, 0);
238
            kos_boot.pitch = kos_boot.x_res * 4;    // assume 32bpp
239
            argc -= 2;
240
            argv += 2;
241
            continue;
242
        } else if (!strcmp(argv[0], "--y_res") && argc > 1) {
243
            kos_boot.y_res = strtoul(argv[1], NULL, 0);
244
            argc -= 2;
245
            argv += 2;
246
            continue;
247
        } else {
248
            printf("bad option: %s\n", argv[0]);
249
            puts(usage);
250
            exit(1);
251
        }
252
    }
253
 
254
}
255
 
256
static void
257
shell_i40(int argc, char **argv) {
258
    const char *usage = \
259
        "usage: i40  [ebx [ecx [edx [esi [edi [ebp]]]]]]...\n"
260
        "  see '/kernel/docs/sysfuncs.txt' for details";
261
    if (argc < 2 || argc > 8) {
262
        fputs(usage, fout);
263
        return;
264
    }
265
    pushad_t regs = {0, 0, 0, 0, 0, 0, 0, 0};
266
    if (argv[1]) regs.eax = strtoul(argv[1], NULL, 0);
267
    if (argv[2]) regs.ebx = strtoul(argv[2], NULL, 0);
268
    if (argv[3]) regs.ecx = strtoul(argv[3], NULL, 0);
269
    if (argv[4]) regs.edx = strtoul(argv[4], NULL, 0);
270
    if (argv[5]) regs.esi = strtoul(argv[5], NULL, 0);
271
    if (argv[6]) regs.edi = strtoul(argv[6], NULL, 0);
272
    if (argv[7]) regs.ebp = strtoul(argv[7], NULL, 0);
273
    COVERAGE_ON();
274
    umka_i40(®s);
275
    COVERAGE_OFF();
276
    fprintf(fout, "eax = %8.8x  %" PRIu32 "  %" PRIi32 "\n"
277
           "ebx = %8.8x  %" PRIu32 "  %" PRIi32 "\n",
278
           regs.eax, regs.eax, (int32_t)regs.eax,
279
           regs.ebx, regs.ebx, (int32_t)regs.ebx);
280
}
281
 
282
static void
283
disk_list_partitions(disk_t *d) {
284
    for (size_t i = 0; i < d->num_partitions; i++) {
285
        fprintf(fout, "/%s/%d: ", d->name, i+1);
286
        if (d->partitions[i]->fs_user_functions == xfs_user_functions) {
287
            fputs("xfs\n", fout);
288
        } else if (d->partitions[i]->fs_user_functions == ext_user_functions) {
289
            fputs("ext\n", fout);
290
        } else if (d->partitions[i]->fs_user_functions == fat_user_functions) {
291
            fputs("fat\n", fout);
292
        } else if (d->partitions[i]->fs_user_functions == ntfs_user_functions) {
293
            fputs("ntfs\n", fout);
294
        } else {
295
            fputs("???\n", fout);
296
        }
297
    }
298
}
299
 
300
static void
301
shell_ramdisk_init(int argc, char **argv) {
302
    const char *usage = \
303
        "usage: ramdisk_init \n"
304
        "             absolute or relative path";
305
    if (argc != 2) {
306
        fputs(usage, fout);
307
        return;
308
    }
309
    const char *fname = argv[1];
9342 Boppan 310
    FILE *f = fopen(fname, "rb");
9325 Boppan 311
    if (!f) {
312
        fprintf(fout, "[!] can't open file '%s': %s\n", fname, strerror(errno));
313
        return;
314
    }
315
    fseek(f, 0, SEEK_END);
316
    size_t fsize = ftell(f);
317
    if (fsize > 2880*512) {
318
        fprintf(fout, "[!] file '%s' is too big, max size is 1474560 bytes\n",
319
                fname);
320
        return;
321
    }
322
    rewind(f);
323
    fread(kos_ramdisk, fsize, 1, f);
324
    fclose(f);
325
    COVERAGE_ON();
326
    void *ramdisk = kos_ramdisk_init();
327
    COVERAGE_OFF();
328
    disk_list_partitions(ramdisk);
329
}
330
 
331
static void
332
shell_disk_add(int argc, char **argv) {
333
    const char *usage = \
334
        "usage: disk_add   [option]...\n"
335
        "             absolute or relative path\n"
336
        "             disk name, e.g. hd0 or rd\n"
337
        "  -c cache size    size of disk cache in bytes";
338
    if (argc < 3) {
339
        fputs(usage, fout);
340
        return;
341
    }
342
    size_t cache_size = 0;
343
    int adjust_cache_size = 0;
344
    int opt;
345
    optind = 1;
346
    const char *file_name = argv[optind++];
347
    const char *disk_name = argv[optind++];
348
    while ((opt = getopt(argc, argv, "c:")) != -1) {
349
        switch (opt) {
350
        case 'c':
351
            cache_size = strtoul(optarg, NULL, 0);
352
            adjust_cache_size = 1;
353
            break;
354
        default:
355
            fputs(usage, fout);
356
            return;
357
        }
358
    }
359
 
360
    void *userdata = vdisk_init(file_name, adjust_cache_size, cache_size);
361
    if (userdata) {
362
        COVERAGE_ON();
363
        void *vdisk = disk_add(&vdisk_functions, disk_name, userdata, 0);
364
        COVERAGE_OFF();
365
        if (vdisk) {
366
            COVERAGE_ON();
367
            disk_media_changed(vdisk, 1);
368
            COVERAGE_OFF();
369
            disk_list_partitions(vdisk);
370
            return;
371
        }
372
    }
373
    fprintf(fout, "umka: can't add file '%s' as disk '%s'\n", file_name,
374
            disk_name);
375
    return;
376
}
377
 
378
static void
379
disk_del_by_name(const char *name) {
380
    for(disk_t *d = disk_list.next; d != &disk_list; d = d->next) {
381
        if (!strcmp(d->name, name)) {
382
            COVERAGE_ON();
383
            disk_del(d);
384
            COVERAGE_OFF();
385
            return;
386
        }
387
    }
388
    fprintf(fout, "umka: can't find disk '%s'\n", name);
389
}
390
 
391
static void
392
shell_disk_del(int argc, char **argv) {
393
    const char *usage = \
394
        "usage: disk_del \n"
395
        "  name             disk name, i.e. rd or hd0";
396
    if (argc != 2) {
397
        fputs(usage, fout);
398
        return;
399
    }
400
    const char *name = argv[1];
401
    disk_del_by_name(name);
402
    return;
403
}
404
 
405
static void
406
shell_pwd(int argc, char **argv) {
407
    const char *usage = \
408
        "usage: pwd";
409
    if (argc != 1) {
410
        fputs(usage, fout);
411
        return;
412
    }
413
    (void)argv;
414
    bool quoted = false;
415
    const char *quote = quoted ? "'" : "";
416
    COVERAGE_ON();
417
    umka_sys_get_cwd(cur_dir, PATH_MAX);
418
    COVERAGE_OFF();
419
    fprintf(fout, "%s%s%s\n", quote, cur_dir, quote);
420
}
421
 
422
static void
423
shell_set_pixel(int argc, char **argv) {
424
    const char *usage = \
425
        "usage: set_pixel    [-i]\n"
426
        "  x                x window coordinate\n"
427
        "  y                y window coordinate\n"
428
        "  color            argb in hex\n"
429
        "  -i               inverted color";
430
    if (argc < 4) {
431
        fputs(usage, fout);
432
        return;
433
    }
434
    size_t x = strtoul(argv[1], NULL, 0);
435
    size_t y = strtoul(argv[2], NULL, 0);
436
    uint32_t color = strtoul(argv[3], NULL, 16);
437
    int invert = (argc == 5) && !strcmp(argv[4], "-i");
438
    COVERAGE_ON();
439
    umka_sys_set_pixel(x, y, color, invert);
440
    COVERAGE_OFF();
441
}
442
 
443
static void
444
shell_write_text(int argc, char **argv) {
445
    const char *usage = \
446
        "usage: write_text      "
447
            "    "
448
            " \n"
449
        "  x                x window coordinate\n"
450
        "  y                y window coordinate\n"
451
        "  color            argb in hex\n"
452
        "  string           escape spaces\n"
453
        "  asciiz           1 if the string is zero-terminated\n"
454
        "  fill_bg          fill text background with specified color\n"
455
        "  font_and_enc     font size and string encoding\n"
456
        "  draw_to_buf      draw to the buffer pointed to by the next param\n"
457
        "  length           length of the string if it is non-asciiz\n"
458
        "  bg_color_or_buf  argb or pointer";
459
    if (argc != 12) {
460
        fputs(usage, fout);
461
        return;
462
    }
463
    size_t x = strtoul(argv[1], NULL, 0);
464
    size_t y = strtoul(argv[2], NULL, 0);
465
    uint32_t color = strtoul(argv[3], NULL, 16);
466
    const char *string = argv[4];
467
    int asciiz = strtoul(argv[5], NULL, 0);
468
    int fill_background = strtoul(argv[6], NULL, 0);
469
    int font_and_encoding = strtoul(argv[7], NULL, 0);
470
    int draw_to_buffer = strtoul(argv[8], NULL, 0);
471
    int scale_factor = strtoul(argv[9], NULL, 0);
472
    int length = strtoul(argv[10], NULL, 0);
473
    int background_color_or_buffer = strtoul(argv[11], NULL, 0);
474
    COVERAGE_ON();
475
    umka_sys_write_text(x, y, color, asciiz, fill_background, font_and_encoding,
476
                        draw_to_buffer, scale_factor, string, length,
477
                        background_color_or_buffer);
478
    COVERAGE_OFF();
479
}
480
 
481
static void
482
shell_dump_win_stack(int argc, char **argv) {
483
    const char *usage = \
484
        "usage: dump_win_stack [count]\n"
485
        "  count            how many items to dump";
486
    if (argc < 1) {
487
        fputs(usage, fout);
488
        return;
489
    }
490
    int depth = 5;
491
    if (argc > 1) {
492
        depth = strtol(argv[1], NULL, 0);
493
    }
494
    for (int i = 0; i < depth; i++) {
495
        fprintf(fout, "%3i: %3u\n", i, kos_win_stack[i]);
496
    }
497
}
498
 
499
static void
500
shell_dump_win_pos(int argc, char **argv) {
501
    const char *usage = \
502
        "usage: dump_win_pos [count]\n"
503
        "  count            how many items to dump";
504
    if (argc < 1) {
505
        fputs(usage, fout);
506
        return;
507
    }
508
    int depth = 5;
509
    if (argc > 1) {
510
        depth = strtol(argv[1], NULL, 0);
511
    }
512
    for (int i = 0; i < depth; i++) {
513
        fprintf(fout, "%3i: %3u\n", i, kos_win_pos[i]);
514
    }
515
}
516
 
517
static void
518
shell_dump_win_map(int argc, char **argv) {
519
    const char *usage = \
520
        "usage: dump_win_map";
521
    (void)argv;
522
    if (argc < 0) {
523
        fputs(usage, fout);
524
        return;
525
    }
526
    for (size_t y = 0; y < kos_display.height; y++) {
527
        for (size_t x = 0; x < kos_display.width; x++) {
528
            fputc(kos_display.win_map[y * kos_display.width + x] + '0', fout);
529
        }
530
        fputc('\n', fout);
531
    }
532
}
533
 
534
static void
535
shell_dump_appdata(int argc, char **argv) {
536
    const char *usage = \
537
        "usage: dump_appdata  [-p]\n"
538
        "  index            index into appdata array to dump\n"
539
        "  -p               print fields that are pointers";
540
    if (argc < 2) {
541
        fputs(usage, fout);
542
        return;
543
    }
544
    int show_pointers = 0;
545
    int idx = strtol(argv[1], NULL, 0);
546
    if (argc > 2 && !strcmp(argv[2], "-p")) {
547
        show_pointers = 1;
548
    }
549
    appdata_t *a = kos_slot_base + idx;
550
    fprintf(fout, "app_name: %s\n", a->app_name);
551
    if (show_pointers) {
552
        fprintf(fout, "process: %p\n", (void*)a->process);
553
        fprintf(fout, "fpu_state: %p\n", (void*)a->fpu_state);
554
        fprintf(fout, "exc_handler: %p\n", (void*)a->exc_handler);
555
    }
556
    fprintf(fout, "except_mask: %" PRIx32 "\n", a->except_mask);
557
    if (show_pointers) {
558
        fprintf(fout, "pl0_stack: %p\n", (void*)a->pl0_stack);
559
        fprintf(fout, "cursor: %p\n", (void*)a->cursor);
560
        fprintf(fout, "fd_ev: %p\n", (void*)a->fd_ev);
561
        fprintf(fout, "bk_ev: %p\n", (void*)a->bk_ev);
562
        fprintf(fout, "fd_obj: %p\n", (void*)a->fd_obj);
563
        fprintf(fout, "bk_obj: %p\n", (void*)a->bk_obj);
564
        fprintf(fout, "saved_esp: %p\n", (void*)a->saved_esp);
565
    }
566
    fprintf(fout, "dbg_state: %u\n", a->dbg_state);
567
    fprintf(fout, "cur_dir: %s\n", a->cur_dir);
568
    fprintf(fout, "draw_bgr_x: %u\n", a->draw_bgr_x);
569
    fprintf(fout, "draw_bgr_y: %u\n", a->draw_bgr_y);
570
    fprintf(fout, "event_mask: %" PRIx32 "\n", a->event_mask);
571
    fprintf(fout, "terminate_protection: %u\n", a->terminate_protection);
572
    fprintf(fout, "keyboard_mode: %u\n", a->keyboard_mode);
573
    fprintf(fout, "captionEncoding: %u\n", a->captionEncoding);
574
    fprintf(fout, "exec_params: %s\n", a->exec_params);
575
    fprintf(fout, "wnd_caption: %s\n", a->wnd_caption);
576
    fprintf(fout, "wnd_clientbox (ltwh): %u %u %u %u\n", a->wnd_clientbox.left,
577
            a->wnd_clientbox.top, a->wnd_clientbox.width,
578
            a->wnd_clientbox.height);
579
    fprintf(fout, "priority: %u\n", a->priority);
580
 
581
    fprintf(fout, "in_schedule: prev");
582
    if (show_pointers) {
583
        fprintf(fout, " %p", (void*)a->in_schedule.prev);
584
    }
585
    fprintf(fout, " (%u), next",
586
            (appdata_t*)a->in_schedule.prev - kos_slot_base);
587
    if (show_pointers) {
588
        fprintf(fout, " %p", (void*)a->in_schedule.next);
589
    }
590
    fprintf(fout, " (%u)\n",
591
            (appdata_t*)a->in_schedule.next - kos_slot_base);
592
}
593
 
594
static void
595
shell_dump_taskdata(int argc, char **argv) {
596
    const char *usage = \
597
        "usage: dump_taskdata \n"
598
        "  index            index into taskdata array to dump";
599
    if (argc < 2) {
600
        fputs(usage, fout);
601
        return;
602
    }
603
    int idx = strtol(argv[1], NULL, 0);
604
    taskdata_t *t = kos_task_table + idx;
605
    fprintf(fout, "event_mask: %" PRIx32 "\n", t->event_mask);
606
    fprintf(fout, "pid: %" PRId32 "\n", t->pid);
607
    fprintf(fout, "state: 0x%" PRIx8 "\n", t->state);
608
    fprintf(fout, "wnd_number: %" PRIu8 "\n", t->wnd_number);
609
    fprintf(fout, "counter_sum: %" PRIu32 "\n", t->counter_sum);
610
    fprintf(fout, "counter_add: %" PRIu32 "\n", t->counter_add);
611
    fprintf(fout, "cpu_usage: %" PRIu32 "\n", t->cpu_usage);
612
}
613
 
614
static void
615
shell_switch_to_thread(int argc, char **argv) {
616
    const char *usage = \
617
        "usage: switch_to_thread \n"
618
        "            thread id to switch to";
619
    if (argc != 2) {
620
        fputs(usage, fout);
621
        return;
622
    }
623
    uint8_t tid = strtoul(argv[1], NULL, 0);
624
    kos_current_slot_idx = tid;
625
    kos_task_base = kos_task_table + tid;
626
    kos_current_slot = kos_slot_base + tid;
627
}
628
 
629
static void
630
shell_set(int argc, char **argv) {
631
    const char *usage = \
632
        "usage: set  \n"
633
        "            variable to set\n"
634
        "          decimal or hex value";
635
    if (argc != 3) {
636
        fputs(usage, fout);
637
        return;
638
    }
639
    const char *var = argv[1];
640
    size_t value = strtoul(argv[2], NULL, 0);
641
    if (!strcmp(var, "redraw_background")) {
642
        kos_redraw_background = value;
643
    } else {
644
        printf("bad option: %s\n", argv[0]);
645
        puts(usage);
646
        exit(1);
647
    }
648
}
649
 
650
static void
651
shell_new_sys_thread(int argc, char **argv) {
652
    const char *usage = \
653
        "usage: new_sys_thread";
654
    if (!argc) {
655
        fputs(usage, fout);
656
        return;
657
    }
658
    (void)argv;
659
    size_t tid = umka_new_sys_threads(0, NULL, NULL);
660
    fprintf(fout, "tid: %u\n", tid);
661
}
662
 
663
static void
664
shell_mouse_move(int argc, char **argv) {
665
    const char *usage = \
666
        "usage: mouse_move [-l] [-m] [-r] [-x {+|-|=}]"
667
            "[-y {+|-|=}] [-h {+|-}] [-v {+|-}]\n"
668
        "  -l             left button is held\n"
669
        "  -m             middle button is held\n"
670
        "  -r             right button is held\n"
671
        "  -x             increase, decrease or set x coordinate\n"
672
        "  -y             increase, decrease or set y coordinate\n"
673
        "  -h             scroll horizontally\n"
674
        "  -v             scroll vertically\n";
675
    if (!argc) {
676
        fputs(usage, fout);
677
        return;
678
    }
679
    int lbheld = 0, mbheld = 0, rbheld = 0, xabs = 0, yabs = 0;
680
    int32_t xmoving = 0, ymoving = 0, hscroll = 0, vscroll = 0;
681
    int opt;
682
    optind = 1;
683
    while ((opt = getopt(argc, argv, "lmrx:y:h:v:")) != -1) {
684
        switch (opt) {
685
        case 'l':
686
            lbheld = 1;
687
            break;
688
        case 'm':
689
            mbheld = 1;
690
            break;
691
        case 'r':
692
            rbheld = 1;
693
            break;
694
        case 'x':
695
            switch (*optarg++) {
696
            case '=':
697
                xabs = 1;
698
                __attribute__ ((fallthrough));
699
            case '+':
700
                xmoving = strtol(optarg, NULL, 0);
701
                break;
702
            case '-':
703
                xmoving = -strtol(optarg, NULL, 0);
704
                break;
705
            default:
706
                fputs(usage, fout);
707
                return;
708
            }
709
            break;
710
        case 'y':
711
            switch (*optarg++) {
712
            case '=':
713
                yabs = 1;
714
                __attribute__ ((fallthrough));
715
            case '+':
716
                ymoving = strtol(optarg, NULL, 0);
717
                break;
718
            case '-':
719
                ymoving = -strtol(optarg, NULL, 0);
720
                break;
721
            default:
722
                fputs(usage, fout);
723
                return;
724
            }
725
            break;
726
        case 'h':
727
            if ((optarg[0] != '+') && (optarg[0] != '-')) {
728
                fputs(usage, fout);
729
                return;
730
            }
731
            hscroll = strtol(optarg, NULL, 0);
732
            break;
733
        case 'v':
734
            if ((optarg[0] != '+') && (optarg[0] != '-')) {
735
                fputs(usage, fout);
736
                return;
737
            }
738
            vscroll = strtol(optarg, NULL, 0);
739
            break;
740
        default:
741
            fputs(usage, fout);
742
            return;
743
        }
744
    }
745
    COVERAGE_ON();
746
    umka_mouse_move(lbheld, mbheld, rbheld, xabs, xmoving, yabs, ymoving,
747
                    hscroll, vscroll);
748
    COVERAGE_OFF();
749
}
750
 
751
static void
752
shell_process_info(int argc, char **argv) {
753
    const char *usage = \
754
        "usage: process_info \n"
755
        "  pid              process id to dump, -1 for self";
756
    if (argc != 2) {
757
        fputs(usage, fout);
758
        return;
759
    }
760
    process_information_t info;
761
    int32_t pid = strtol(argv[1], NULL, 0);
762
    COVERAGE_ON();
763
    umka_sys_process_info(pid, &info);
764
    COVERAGE_OFF();
765
    fprintf(fout, "cpu_usage: %u\n", info.cpu_usage);
766
    fprintf(fout, "window_stack_position: %u\n", info.window_stack_position);
767
    fprintf(fout, "window_stack_value: %u\n", info.window_stack_value);
768
    fprintf(fout, "process_name: %s\n", info.process_name);
769
    fprintf(fout, "memory_start: 0x%.8" PRIx32 "\n", info.memory_start);
770
    fprintf(fout, "used_memory: %u (0x%x)\n", info.used_memory,
771
            info.used_memory);
772
    fprintf(fout, "pid: %u\n", info.pid);
773
    fprintf(fout, "box: %u %u %u %u\n", info.box.left, info.box.top,
774
            info.box.width, info.box.height);
775
    fprintf(fout, "slot_state: %u\n", info.slot_state);
776
    fprintf(fout, "client_box: %u %u %u %u\n", info.client_box.left,
777
            info.client_box.top, info.client_box.width, info.client_box.height);
778
    fprintf(fout, "wnd_state: 0x%.2" PRIx8 "\n", info.wnd_state);
779
}
780
 
781
static void
782
shell_display_number(int argc, char **argv) {
783
    const char *usage = \
784
        "usage: display_number    "
785
            "       "
786
            "   \n"
787
        "  is_pointer       if num_or_ptr argument is a pointer\n"
788
        "  base             0 - dec, 1 - hex, 2 - bin\n"
789
        "  num_digits       how many digits to print\n"
790
        "  is_qword         if 1, is_pointer = 1 and num_or_ptr is pointer\n"
791
        "  show_lead_zeros  0/1\n"
792
        "  num_or_ptr       number itself or a pointer to it\n"
793
        "  x                x window coord\n"
794
        "  y                y window coord\n"
795
        "  color            argb in hex\n"
796
        "  fill_bg          0/1\n"
797
        "  font             0 = 6x9, 1 = 8x16\n"
798
        "  draw_to_buf      0/1\n"
799
        "  scale_factor     0 = x1, ..., 7 = x8\n"
800
        "  bg_color_or_buf  depending on flags fill_bg and draw_to_buf";
801
    if (argc != 15) {
802
        fputs(usage, fout);
803
        return;
804
    }
805
    int is_pointer = strtoul(argv[1], NULL, 0);
806
    int base = strtoul(argv[2], NULL, 0);
807
    if (base == 10) base = 0;
808
    else if (base == 16) base = 1;
809
    else if (base == 2) base = 2;
810
    else base = 0;
811
    size_t digits_to_display = strtoul(argv[3], NULL, 0);
812
    int is_qword = strtoul(argv[4], NULL, 0);
813
    int show_leading_zeros = strtoul(argv[5], NULL, 0);
814
    uintptr_t number_or_pointer = strtoul(argv[6], NULL, 0);
815
    size_t x = strtoul(argv[7], NULL, 0);
816
    size_t y = strtoul(argv[8], NULL, 0);
817
    uint32_t color = strtoul(argv[9], NULL, 16);
818
    int fill_background = strtoul(argv[10], NULL, 0);
819
    int font = strtoul(argv[11], NULL, 0);
820
    int draw_to_buffer = strtoul(argv[12], NULL, 0);
821
    int scale_factor = strtoul(argv[13], NULL, 0);
822
    uintptr_t background_color_or_buffer = strtoul(argv[14], NULL, 16);
823
    COVERAGE_ON();
824
    umka_sys_display_number(is_pointer, base, digits_to_display, is_qword,
825
                            show_leading_zeros, number_or_pointer, x, y, color,
826
                            fill_background, font, draw_to_buffer, scale_factor,
827
                            background_color_or_buffer);
828
    COVERAGE_OFF();
829
}
830
 
831
static void
832
shell_set_window_colors(int argc, char **argv) {
833
    const char *usage = \
834
        "usage: set_window_colors    "
835
            "     "
836
            " \n"
837
        "  *                all colors are in hex";
838
    if (argc != (1 + sizeof(system_colors_t)/4)) {
839
        fputs(usage, fout);
840
        return;
841
    }
842
    system_colors_t colors;
843
    colors.frame            = strtoul(argv[1], NULL, 16);
844
    colors.grab             = strtoul(argv[2], NULL, 16);
845
    colors.work_3d_dark     = strtoul(argv[3], NULL, 16);
846
    colors.work_3d_light    = strtoul(argv[4], NULL, 16);
847
    colors.grab_text        = strtoul(argv[5], NULL, 16);
848
    colors.work             = strtoul(argv[6], NULL, 16);
849
    colors.work_button      = strtoul(argv[7], NULL, 16);
850
    colors.work_button_text = strtoul(argv[8], NULL, 16);
851
    colors.work_text        = strtoul(argv[9], NULL, 16);
852
    colors.work_graph       = strtoul(argv[10], NULL, 16);
853
    COVERAGE_ON();
854
    umka_sys_set_window_colors(&colors);
855
    COVERAGE_OFF();
856
}
857
 
858
static void
859
shell_get_window_colors(int argc, char **argv) {
860
    const char *usage = \
861
        "usage: get_window_colors";
862
    if (argc != 1) {
863
        fputs(usage, fout);
864
        return;
865
    }
866
    (void)argv;
867
    system_colors_t colors;
868
    memset(&colors, 0xaa, sizeof(colors));
869
    COVERAGE_ON();
870
    umka_sys_get_window_colors(&colors);
871
    COVERAGE_OFF();
872
    fprintf(fout, "0x%.8" PRIx32 " frame\n", colors.frame);
873
    fprintf(fout, "0x%.8" PRIx32 " grab\n", colors.grab);
874
    fprintf(fout, "0x%.8" PRIx32 " work_3d_dark\n", colors.work_3d_dark);
875
    fprintf(fout, "0x%.8" PRIx32 " work_3d_light\n", colors.work_3d_light);
876
    fprintf(fout, "0x%.8" PRIx32 " grab_text\n", colors.grab_text);
877
    fprintf(fout, "0x%.8" PRIx32 " work\n", colors.work);
878
    fprintf(fout, "0x%.8" PRIx32 " work_button\n", colors.work_button);
879
    fprintf(fout, "0x%.8" PRIx32 " work_button_text\n",
880
            colors.work_button_text);
881
    fprintf(fout, "0x%.8" PRIx32 " work_text\n", colors.work_text);
882
    fprintf(fout, "0x%.8" PRIx32 " work_graph\n", colors.work_graph);
883
}
884
 
885
static void
886
shell_get_skin_height(int argc, char **argv) {
887
    const char *usage = \
888
        "usage: get_skin_height";
889
    if (argc != 1) {
890
        fputs(usage, fout);
891
        return;
892
    }
893
    (void)argv;
894
    COVERAGE_ON();
895
    uint32_t skin_height = umka_sys_get_skin_height();
896
    COVERAGE_OFF();
897
    fprintf(fout, "%" PRIu32 "\n", skin_height);
898
}
899
 
900
static void
901
shell_get_screen_area(int argc, char **argv) {
902
    const char *usage = \
903
        "usage: get_screen_area";
904
    if (argc != 1) {
905
        fputs(usage, fout);
906
        return;
907
    }
908
    (void)argv;
909
    rect_t wa;
910
    COVERAGE_ON();
911
    umka_sys_get_screen_area(&wa);
912
    COVERAGE_OFF();
913
    fprintf(fout, "%" PRIu32 " left\n", wa.left);
914
    fprintf(fout, "%" PRIu32 " top\n", wa.top);
915
    fprintf(fout, "%" PRIu32 " right\n", wa.right);
916
    fprintf(fout, "%" PRIu32 " bottom\n", wa.bottom);
917
}
918
 
919
static void
920
shell_set_screen_area(int argc, char **argv) {
921
    const char *usage = \
922
        "usage: set_screen_area    \n"
923
        "  left             left x coord\n"
924
        "  top              top y coord\n"
925
        "  right            right x coord (not length!)\n"
926
        "  bottom           bottom y coord";
927
    if (argc != 5) {
928
        fputs(usage, fout);
929
        return;
930
    }
931
    rect_t wa;
932
    wa.left   = strtoul(argv[1], NULL, 0);
933
    wa.top    = strtoul(argv[2], NULL, 0);
934
    wa.right  = strtoul(argv[3], NULL, 0);
935
    wa.bottom = strtoul(argv[4], NULL, 0);
936
    COVERAGE_ON();
937
    umka_sys_set_screen_area(&wa);
938
    COVERAGE_OFF();
939
}
940
 
941
static void
942
shell_get_skin_margins(int argc, char **argv) {
943
    const char *usage = \
944
        "usage: get_skin_margins";
945
    if (argc != 1) {
946
        fputs(usage, fout);
947
        return;
948
    }
949
    (void)argv;
950
    rect_t wa;
951
    COVERAGE_ON();
952
    umka_sys_get_skin_margins(&wa);
953
    COVERAGE_OFF();
954
    fprintf(fout, "%" PRIu32 " left\n", wa.left);
955
    fprintf(fout, "%" PRIu32 " top\n", wa.top);
956
    fprintf(fout, "%" PRIu32 " right\n", wa.right);
957
    fprintf(fout, "%" PRIu32 " bottom\n", wa.bottom);
958
}
959
 
960
static void
961
shell_set_button_style(int argc, char **argv) {
962
    const char *usage = \
963
        "usage: set_button_style