1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 
9 #include <zircon/syscalls.h>
10 #include <task-utils/walker.h>
11 
12 typedef struct {
13     zx_koid_t task_id;
14     zx_signals_t clear_mask;
15     zx_signals_t set_mask;
16 } signal_target_t;
17 
callback(void * ctx,int depth,zx_handle_t process,zx_koid_t koid,zx_koid_t parent_koid)18 static zx_status_t callback(void* ctx, int depth, zx_handle_t process,
19                             zx_koid_t koid, zx_koid_t parent_koid) {
20     signal_target_t* sigt = (signal_target_t*)ctx;
21     if (koid == sigt->task_id) {
22         zx_status_t status = zx_object_signal(process, sigt->clear_mask, sigt->set_mask);
23         if (status == ZX_OK) {
24             printf("signalled process %ld\n", sigt->task_id);
25         } else {
26             printf("something wrong with signalling process %ld, status: %d\n", sigt->task_id, status);
27         }
28         // found and signaled the task - abort the search
29         return ZX_ERR_STOP;
30     }
31     return ZX_OK;
32 }
33 
usage(const char * progname)34 static void usage(const char* progname) {
35     fprintf(stderr, "usage: %s <task id> signal-number <set|clear>\n", progname);
36     fprintf(stderr, "signal number is in the range [0-7] and refers to ZX_USER_SIGNAL_[0-7] bits\n");
37     fprintf(stderr, "set|clear indicates wether the signal is added to the set_mask (set) or to the clear_mask (clear)\n");
38 }
39 
main(int argc,const char ** argv)40 int main(int argc, const char** argv) {
41     if (argc < 4) {
42         usage(argv[0]);
43         return -1;
44     }
45 
46     char* endptr;
47     zx_koid_t task_id = strtol(argv[1], &endptr, 10);
48     if (*endptr != '\0') {
49         fprintf(stderr, "\"%s\" is not a valid task id\n", argv[1]);
50         return -1;
51     }
52 
53     long signal = strtol(argv[2], &endptr, 10);
54     if (*endptr != '\0' || signal < 0 || signal > 7) {
55         fprintf(stderr, "\"%s\" is not a valid signal number\n", argv[2]);
56         usage(argv[0]);
57         return -1;
58     }
59 
60     static const zx_signals_t user_signal[8] = {
61         ZX_USER_SIGNAL_0,
62         ZX_USER_SIGNAL_1,
63         ZX_USER_SIGNAL_2,
64         ZX_USER_SIGNAL_3,
65         ZX_USER_SIGNAL_4,
66         ZX_USER_SIGNAL_5,
67         ZX_USER_SIGNAL_6,
68         ZX_USER_SIGNAL_7
69     };
70 
71     bool is_up;
72     if (strcmp(argv[3], "set") == 0) {
73         is_up = true;
74     } else if (strcmp(argv[3], "clear") == 0) {
75         is_up = false;
76     } else {
77         usage(argv[0]);
78         return -1;
79     }
80 
81     signal_target_t sigt = {
82         .task_id = task_id,
83         .clear_mask = is_up ? 0 : user_signal[signal],
84         .set_mask = is_up ? user_signal[signal] : 0
85     };
86 
87     zx_status_t status = walk_root_job_tree(callback, callback, NULL, &sigt);
88     if (status == ZX_OK) {
89         fprintf(stderr, "task %lu not found\n", task_id);
90         return -1;
91     }
92 
93     return 0;
94 }
95