df2c1955a71d3fb007b8f73247f55b24a9d2dab4
[platform/core/connectivity/stc-manager.git] / plugin / procfs / stc-plugin-procfs.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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  */
16
17 #include <stdbool.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <sys/socket.h>
25 #include <linux/netlink.h>
26 #include <linux/connector.h>
27 #include <linux/cn_proc.h>
28 #include <glib.h>
29
30 #include "stc-plugin-procfs.h"
31 #include "stc-monitor.h"
32 #include "helper-procfs.h"
33
34 //LCOV_EXCL_START
35 typedef struct {
36         pid_t pid;
37 } proc_key_s;
38
39 typedef struct {
40         char cmdline[PROC_NAME_MAX];
41         char status[PROC_STATUS_CNT][PROC_BUF_MAX];
42 } proc_value_s;
43
44 typedef struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
45         struct nlmsghdr nl_hdr;
46         struct __attribute__ ((__packed__)) {
47                 struct cn_msg cn_msg;
48                 enum proc_cn_mcast_op cn_mcast;
49         };
50 } nl_connector_msg_s;
51
52 typedef struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
53         struct nlmsghdr nl_hdr;
54         struct __attribute__ ((__packed__)) {
55                 struct cn_msg cn_msg;
56                 struct proc_event proc_ev;
57         };
58 } nl_connector_proc_event_s;
59
60 static int nl_connector_sock = -1;
61 static guint nl_connector_gsource_id = 0;
62 static GTree *proc_tree;
63
64
65 static gboolean __process_nl_connector_message(GIOChannel *source,
66                                                GIOCondition condition,
67                                                gpointer user_data);
68
69 static int __proc_tree_key_compare(gconstpointer a, gconstpointer b,
70                                    gpointer UNUSED user_data)
71 {
72         proc_key_s *key_a = (proc_key_s *)a;
73         proc_key_s *key_b = (proc_key_s *)b;
74
75         return key_a->pid - key_b->pid;
76 }
77
78 static void __proc_tree_value_free(gpointer data)
79 {
80         proc_value_s *value = (proc_value_s *)data;
81
82         FREE(value);
83 }
84
85 static void __proc_tree_key_free(gpointer data)
86 {
87         proc_key_s *key = (proc_key_s *)data;
88
89         FREE(key);
90 }
91
92 static proc_value_s * __proc_tree_lookup(const proc_key_s *key)
93 {
94         proc_value_s *lookup;
95
96         if (proc_tree == NULL) {
97                 STC_LOGE("tree is null");
98                 return NULL;
99         }
100
101         lookup = g_tree_lookup(proc_tree, key);
102         return lookup;
103 }
104
105 static gboolean __proc_tree_foreach_print(gpointer key, gpointer value,
106                                           gpointer data)
107 {
108         proc_key_s *proc_key = (proc_key_s *)key;
109         proc_value_s *proc_value = (proc_value_s *)value;
110
111         STC_LOGD("Proc pid [\033[1;33m%d\033[0;m] ppid [\033[1;35m%s\033[0;m] "
112                 "cmdline [\033[0;34m%s\033[0;m]", proc_key->pid,
113                 proc_value->status[PROC_STATUS_PPID], proc_value->cmdline);
114
115         return FALSE;
116 }
117
118 static void __proc_tree_printall(void)
119 {
120         g_tree_foreach(proc_tree, __proc_tree_foreach_print, NULL);
121 }
122
123 static proc_value_s * __proc_tree_find_parent(proc_value_s *value)
124 {
125         proc_value_s *parent = NULL;
126         proc_value_s *lookup = value;
127
128         do {
129                 proc_key_s key;
130                 key.pid = atoi(lookup->status[PROC_STATUS_PPID]);
131                 lookup = __proc_tree_lookup(&key);
132                 if (lookup != NULL)
133                         parent = lookup;
134         } while (lookup);
135
136         if (STC_DEBUG_LOG) {
137                 if (parent != NULL)
138                         STC_LOGD("\033[0;35mPARENT\033[0;m: tgid[\033[1;33m%s\033[0;m] pid[%s] "
139                                 "ppid[\033[1;35m%s\033[0;m] cmdline[\033[0;34m%s\033[0;m] name[%s]",
140                                 parent->status[PROC_STATUS_TGID], parent->status[PROC_STATUS_PID],
141                                 parent->status[PROC_STATUS_PPID], parent->cmdline,
142                                 parent->status[PROC_STATUS_NAME]);
143         }
144
145         return parent;
146 }
147
148 static void __proc_tree_add(proc_key_s *key,
149                             proc_value_s *value)
150 {
151         proc_value_s *lookup;
152         proc_value_s *parent;
153
154         if (proc_tree == NULL) {
155                 STC_LOGE("tree is null");
156                 return;
157         }
158
159         lookup = g_tree_lookup(proc_tree, key);
160         if (lookup) {
161                 if (STC_DEBUG_LOG)
162                         STC_LOGD("LOOKUP: tgid[\033[1;33m%s\033[0;m] pid[%s] ppid[\033[1;35m%s\033[0;m] "
163                                 "cmdline[\033[0;34m%s\033[0;m] name[%s]", lookup->status[PROC_STATUS_TGID],
164                                 lookup->status[PROC_STATUS_PID], lookup->status[PROC_STATUS_PPID],
165                                 lookup->cmdline, lookup->status[PROC_STATUS_NAME]);
166                 return;
167         }
168
169         if (STC_DEBUG_LOG)
170                 STC_LOGD("cmdline [%s] pid[%s] ppid[%s]", value->cmdline,
171                         value->status[PROC_STATUS_PID], value->status[PROC_STATUS_PPID]);
172
173         g_tree_insert(proc_tree, key, value);
174
175         if (STC_DEBUG_LOG)
176                 __proc_tree_printall();
177
178         parent = __proc_tree_find_parent(value);
179         if (parent != NULL)
180                 stc_plugin_procfs_status_changed(STC_CMD_SET_SERVICE_LAUNCHED, key->pid,
181                         parent->cmdline, parent->cmdline, STC_APP_TYPE_SERVICE);
182         else
183                 stc_plugin_procfs_status_changed(STC_CMD_SET_SERVICE_LAUNCHED, key->pid,
184                         value->cmdline, value->cmdline, STC_APP_TYPE_SERVICE);
185 }
186
187 static void __proc_tree_remove(const proc_key_s *key)
188 {
189         if (proc_tree == NULL) {
190                 STC_LOGE("tree is null");
191                 return;
192         }
193
194         stc_plugin_procfs_status_changed(STC_CMD_SET_TERMINATED, key->pid, NULL,
195                                        NULL, STC_APP_TYPE_NONE);
196
197         g_tree_remove(proc_tree, key);
198
199         if (STC_DEBUG_LOG)
200                 __proc_tree_printall();
201 }
202
203 static gboolean __check_excn(char *cmdline)
204 {
205         stc_error_e ret = STC_ERROR_NONE;
206
207         if (cmdline[0] == '(')
208                 return TRUE;
209
210         ret = stc_monitor_check_excn_by_cmdline(cmdline);
211         if (ret == STC_ERROR_UNINITIALIZED ||
212                 ret == STC_ERROR_NO_DATA)
213                 return FALSE;
214         else
215                 return TRUE;
216 }
217
218 static void __open_nl_connector_sock(void)
219 {
220         __STC_LOG_FUNC_ENTER__;
221         GIOChannel *gio = NULL;
222
223         if (nl_connector_sock != -1 &&
224             nl_connector_gsource_id != 0) {
225                 STC_LOGE("Socket is already open");
226                 __STC_LOG_FUNC_EXIT__;
227                 return;
228         }
229
230         if (nl_connector_sock != -1) {
231                 close(nl_connector_sock);
232                 nl_connector_sock = -1;
233         }
234
235         if (nl_connector_gsource_id != 0) {
236                 g_source_remove(nl_connector_gsource_id);
237                 nl_connector_gsource_id = 0;
238         }
239
240         nl_connector_sock = create_netlink(NETLINK_CONNECTOR, CN_IDX_PROC);
241         if (nl_connector_sock == -1) {
242                 __STC_LOG_FUNC_EXIT__;
243                 return;
244         }
245
246         gio = g_io_channel_unix_new(nl_connector_sock);
247         nl_connector_gsource_id =
248                 g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP,
249                                (GIOFunc) __process_nl_connector_message,
250                                NULL);
251         g_io_channel_unref(gio);
252         __STC_LOG_FUNC_EXIT__;
253 }
254
255 static void __close_nl_connector_sock(void)
256 {
257         __STC_LOG_FUNC_ENTER__;
258         if (nl_connector_sock != -1) {
259                 close(nl_connector_sock);
260                 nl_connector_sock = -1;
261         }
262
263         if (nl_connector_gsource_id != 0) {
264                 g_source_remove(nl_connector_gsource_id);
265                 nl_connector_gsource_id = 0;
266         }
267         __STC_LOG_FUNC_EXIT__;
268 }
269
270 static void __reopen_nl_connector_sock(void)
271 {
272         __close_nl_connector_sock();
273         __open_nl_connector_sock();
274 }
275
276 static void __process_event_fork(int tgid, int pid)
277 {
278         char cmdline[PROC_NAME_MAX] = {0, };
279         char status[PROC_STATUS_CNT][PROC_BUF_MAX];
280
281         memset(status, 0x0, sizeof(status));
282
283         if (STC_ERROR_NONE == proc_get_cmdline(pid, cmdline) &&
284             STC_ERROR_NONE == proc_get_status(pid, status)) {
285
286                 if (__check_excn(cmdline)) {
287                         if (STC_DEBUG_LOG)
288                                 STC_LOGD("[%s] monitoring is excepted", cmdline);
289                         return;
290                 }
291
292                 unsigned int i;
293                 proc_key_s *key;
294                 proc_value_s *value;
295
296                 key = MALLOC0(proc_key_s, 1);
297                 if (key == NULL) {
298                         STC_LOGE("memory allocation failed");
299                         return;
300                 }
301
302                 value = MALLOC0(proc_value_s, 1);
303                 if (value == NULL) {
304                         STC_LOGE("memory allocation failed");
305                         FREE(key);
306                         return;
307                 }
308
309                 key->pid = tgid;
310                 for (i = 0; i < PROC_STATUS_CNT; ++i)
311                         g_strlcpy(value->status[i], status[i], sizeof(value->status[i]));
312                 g_strlcpy(value->cmdline, cmdline, sizeof(value->cmdline));
313
314                 if (STC_DEBUG_LOG) {
315                         STC_LOGD("\033[1;34mFORK\033[0;m: tgid[\033[1;33m%d\033[0;m] ppid=[\033[1;35m%s\033[0;m] "
316                                 "cmdline[\033[0;34m%s\033[0;m] pid[%d]", tgid, status[PROC_STATUS_PPID], cmdline, pid);
317                         STC_LOGD("STATUS: tgid[%s] pid[%s] ppid[%s] name[%s] state[%s] tracerpid[%s]",
318                                 status[PROC_STATUS_TGID], status[PROC_STATUS_PID], status[PROC_STATUS_PPID],
319                                 status[PROC_STATUS_NAME], status[PROC_STATUS_STATE], status[PROC_STATUS_TRACERPID]);
320                 }
321
322                 __proc_tree_add(key, value);
323         }
324 }
325
326 static void __process_event_exec(int tgid, int pid)
327 {
328         char cmdline[PROC_NAME_MAX] = {0, };
329         char status[PROC_STATUS_CNT][PROC_BUF_MAX];
330
331         memset(status, 0x0, sizeof(status));
332
333         if (STC_ERROR_NONE == proc_get_cmdline(pid, cmdline) &&
334             STC_ERROR_NONE == proc_get_status(pid, status)) {
335
336                 if (__check_excn(cmdline)) {
337                         if (STC_DEBUG_LOG)
338                                 STC_LOGD("[%s] monitoring is excepted", cmdline);
339                         return;
340                 }
341
342                 unsigned int i;
343                 proc_key_s *key;
344                 proc_value_s *value;
345
346                 key = MALLOC0(proc_key_s, 1);
347                 if (key == NULL) {
348                         STC_LOGE("memory allocation failed");
349                         return;
350                 }
351
352                 value = MALLOC0(proc_value_s, 1);
353                 if (value == NULL) {
354                         STC_LOGE("memory allocation failed");
355                         FREE(key);
356                         return;
357                 }
358
359                 key->pid = tgid;
360                 for (i = 0; i < PROC_STATUS_CNT; ++i)
361                         g_strlcpy(value->status[i], status[i], sizeof(value->status[i]));
362                 g_strlcpy(value->cmdline, cmdline, sizeof(value->cmdline));
363
364                 if (STC_DEBUG_LOG) {
365                         STC_LOGD("\033[1;32mEXEC\033[0;m: tgid[\033[1;33m%d\033[0;m] ppid=[\033[1;35m%s\033[0;m] "
366                                 "cmdline[\033[0;34m%s\033[0;m] pid[%d]", tgid, status[PROC_STATUS_PPID], cmdline, pid);
367                         STC_LOGD("STATUS: tgid[%s] pid[%s] ppid[%s] name[%s] state[%s] tracerpid[%s]",
368                                 status[PROC_STATUS_TGID], status[PROC_STATUS_PID], status[PROC_STATUS_PPID],
369                                 status[PROC_STATUS_NAME], status[PROC_STATUS_STATE], status[PROC_STATUS_TRACERPID]);
370                 }
371
372                 __proc_tree_add(key, value);
373         }
374 }
375
376 static void __process_event_exit(int tgid, int pid, int exit_code)
377 {
378         proc_key_s key;
379         proc_value_s *lookup;
380
381         if (tgid != pid)
382                 return;
383
384         key.pid = tgid;
385         lookup = __proc_tree_lookup(&key);
386         if (lookup == NULL) /* unmonitored process */
387                 return;
388
389         if (STC_DEBUG_LOG)
390                 STC_LOGD("\033[1;31mEXIT\033[0;m: tgid[\033[1;33m%d\033[0;m] "
391                         "pid[%d] exitcode[\033[0;31m%d\033[0;m]", tgid, pid, exit_code);
392
393         __proc_tree_remove(&key);
394 }
395
396 static gboolean __process_nl_connector_message(GIOChannel *source,
397                                                GIOCondition condition,
398                                                gpointer user_data)
399 {
400         int ret;
401         int sock = g_io_channel_unix_get_fd(source);
402         nl_connector_proc_event_s msg;
403
404         if ((condition & G_IO_ERR) || (condition & G_IO_HUP) ||
405             (condition & G_IO_NVAL)) {
406                 /* G_IO_ERR/G_IO_HUP/G_IO_NVAL received */
407
408                 STC_LOGE("Netlink Connector socket received G_IO event, closing"
409                          " socket. G_IO_ERR [%u], G_IO_HUP [%u], G_IO_NVAL [%u]",
410                          (condition & G_IO_ERR), (condition & G_IO_HUP),
411                          (condition & G_IO_NVAL));
412                 __reopen_nl_connector_sock();
413                 __STC_LOG_FUNC_EXIT__;
414                 return FALSE;
415         }
416
417         memset(&msg, 0, sizeof(nl_connector_proc_event_s));
418
419         ret = read(sock, &msg, sizeof(nl_connector_proc_event_s));
420         if (ret == 0) {
421                 __STC_LOG_FUNC_EXIT__;
422                 return TRUE;
423         }
424
425         switch (msg.proc_ev.what) {
426         case PROC_EVENT_FORK:
427                 __process_event_fork(msg.proc_ev.event_data.fork.child_tgid,
428                                      msg.proc_ev.event_data.fork.child_pid);
429                 break;
430         case PROC_EVENT_EXEC:
431                 __process_event_exec(msg.proc_ev.event_data.exec.process_tgid,
432                                      msg.proc_ev.event_data.exec.process_pid);
433                 break;
434         case PROC_EVENT_EXIT:
435                 __process_event_exit(msg.proc_ev.event_data.exit.process_tgid,
436                                      msg.proc_ev.event_data.exit.process_pid,
437                                      msg.proc_ev.event_data.exit.exit_code);
438                 break;
439         default:
440                 ; /* Do nothing */
441         }
442
443         return TRUE;
444 }
445
446 static int __subscribe_proc_events(void)
447 {
448         __STC_LOG_FUNC_ENTER__;
449         nl_connector_msg_s msg;
450         int ret;
451         int sock = nl_connector_sock;
452
453         if (sock == -1) {
454                 __STC_LOG_FUNC_EXIT__;
455                 return -1;
456         }
457
458         memset(&msg, 0, sizeof(nl_connector_msg_s));
459
460         msg.nl_hdr.nlmsg_len = sizeof(nl_connector_msg_s);
461         msg.nl_hdr.nlmsg_pid = getpid();
462         msg.nl_hdr.nlmsg_type = NLMSG_DONE;
463
464         msg.cn_msg.id.idx = CN_IDX_PROC;
465         msg.cn_msg.id.val = CN_VAL_PROC;
466         msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
467
468         msg.cn_mcast = PROC_CN_MCAST_LISTEN;
469
470         ret = send(sock, &msg, sizeof(nl_connector_msg_s), 0);
471         if (ret == -1) {
472                 STC_LOGE("Error sending netlink connector message");
473                 __STC_LOG_FUNC_EXIT__;
474                 return -1;
475         }
476
477         __STC_LOG_FUNC_EXIT__;
478         return 0;
479 }
480
481 static int __unsubscribe_proc_events(void)
482 {
483         __STC_LOG_FUNC_ENTER__;
484         nl_connector_msg_s msg;
485         int ret;
486         int sock = nl_connector_sock;
487
488         if (sock == -1) {
489                 __STC_LOG_FUNC_EXIT__;
490                 return -1;
491         }
492
493         memset(&msg, 0, sizeof(nl_connector_msg_s));
494
495         msg.nl_hdr.nlmsg_len = sizeof(nl_connector_msg_s);
496         msg.nl_hdr.nlmsg_pid = getpid();
497         msg.nl_hdr.nlmsg_type = NLMSG_DONE;
498
499         msg.cn_msg.id.idx = CN_IDX_PROC;
500         msg.cn_msg.id.val = CN_VAL_PROC;
501         msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
502
503         msg.cn_mcast = PROC_CN_MCAST_IGNORE;
504
505         ret = send(sock, &msg, sizeof(nl_connector_msg_s), 0);
506         if (ret == -1) {
507                 STC_LOGE("Error sending netlink connector message");
508                 __STC_LOG_FUNC_EXIT__;
509                 return -1;
510         }
511
512         __STC_LOG_FUNC_EXIT__;
513         return 0;
514 }
515
516 int stc_plugin_procfs_initialize(void)
517 {
518         __STC_LOG_FUNC_ENTER__;
519
520         proc_tree = g_tree_new_full(__proc_tree_key_compare, NULL,
521                                     __proc_tree_key_free,
522                                     __proc_tree_value_free);
523
524         /* TODO: Fill proc tree with current procfs state */
525
526         __open_nl_connector_sock();
527         __subscribe_proc_events();
528         __STC_LOG_FUNC_EXIT__;
529         return STC_ERROR_NONE;
530 }
531
532 int stc_plugin_procfs_deinitialize(void)
533 {
534         __STC_LOG_FUNC_ENTER__;
535
536         if (nl_connector_sock == -1) {
537                 STC_LOGD("socket already closed");
538                 return STC_ERROR_NONE;
539         }
540
541         __unsubscribe_proc_events();
542         __close_nl_connector_sock();
543
544         g_tree_destroy(proc_tree);
545         proc_tree = NULL;
546
547         __STC_LOG_FUNC_EXIT__;
548         return STC_ERROR_NONE;
549 }
550
551 stc_error_e stc_plugin_procfs_status_changed(stc_cmd_type_e cmd,
552                                 pid_t pid, const gchar *app_id, const gchar *pkg_id, stc_app_type_e app_type)
553 {
554         stc_error_e ret = STC_ERROR_NONE;
555
556         if ((pkg_id && app_id) && STC_DEBUG_LOG)
557                 STC_LOGD("cmd [%d] pkgid [%s] appid [%s] pid[%d] type [%d]",
558                         cmd, pkg_id, app_id, pid, app_type);
559
560         switch (cmd) {
561         case STC_CMD_SET_FOREGRD:
562         {
563                 stc_app_key_s app_key;
564                 stc_app_value_s app_value;
565                 stc_process_key_s proc_key;
566                 stc_process_value_s proc_value;
567
568                 memset(&app_key, 0, sizeof(stc_app_key_s));
569                 memset(&app_value, 0, sizeof(stc_app_value_s));
570                 memset(&proc_key, 0, sizeof(stc_process_key_s));
571                 memset(&proc_value, 0, sizeof(stc_process_value_s));
572
573                 app_key.pkg_id = g_strdup(pkg_id);
574                 app_key.app_id = g_strdup(app_id);
575
576                 app_value.type = app_type;
577                 app_value.processes = NULL;
578
579                 proc_key.pid = pid;
580
581                 proc_value.ground = STC_APP_STATE_FOREGROUND;
582
583                 stc_monitor_application_add(app_key, app_value);
584                 stc_monitor_process_add(app_key, proc_key, proc_value);
585                 stc_monitor_process_update_ground(app_key, proc_key,
586                                                   STC_APP_STATE_FOREGROUND);
587
588                 FREE(app_key.pkg_id);
589                 FREE(app_key.app_id);
590                 break;
591         }
592         case STC_CMD_SET_BACKGRD:
593         {
594                 stc_app_key_s app_key;
595                 stc_app_value_s app_value;
596                 stc_process_key_s proc_key;
597                 stc_process_value_s proc_value;
598
599                 memset(&app_key, 0, sizeof(stc_app_key_s));
600                 memset(&app_value, 0, sizeof(stc_app_value_s));
601                 memset(&proc_key, 0, sizeof(stc_process_key_s));
602                 memset(&proc_value, 0, sizeof(stc_process_value_s));
603
604                 app_key.pkg_id = g_strdup(pkg_id);
605                 app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX,
606                                              NULL);
607
608                 app_value.type = app_type;
609                 app_value.processes = NULL;
610
611                 proc_key.pid = pid;
612
613                 proc_value.ground = STC_APP_STATE_BACKGROUND;
614
615                 stc_monitor_application_add(app_key, app_value);
616                 stc_monitor_process_add(app_key, proc_key, proc_value);
617                 stc_monitor_process_update_ground(app_key, proc_key,
618                                                   STC_APP_STATE_BACKGROUND);
619
620                 FREE(app_key.pkg_id);
621                 FREE(app_key.app_id);
622                 break;
623         }
624         case STC_CMD_SET_SERVICE_LAUNCHED:
625         {
626                 stc_app_key_s app_key;
627                 stc_app_value_s app_value;
628                 stc_process_key_s proc_key;
629                 stc_process_value_s proc_value;
630
631                 memset(&app_key, 0, sizeof(stc_app_key_s));
632                 memset(&app_value, 0, sizeof(stc_app_value_s));
633                 memset(&proc_key, 0, sizeof(stc_process_key_s));
634                 memset(&proc_value, 0, sizeof(stc_process_value_s));
635
636                 app_key.pkg_id = g_strdup(pkg_id);
637                 app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX,
638                                              NULL);
639
640                 app_value.type = app_type;
641                 app_value.processes = NULL;
642
643                 proc_key.pid = pid;
644
645                 /* services will run always in background. */
646                 proc_value.ground = STC_APP_STATE_BACKGROUND;
647
648                 stc_monitor_application_add(app_key, app_value);
649                 stc_monitor_process_add(app_key, proc_key, proc_value);
650
651                 FREE(app_key.pkg_id);
652                 g_free(app_key.app_id);
653                 break;
654         }
655         case STC_CMD_SET_TERMINATED:
656         {
657                 stc_monitor_process_remove(pid);
658                 break;
659         }
660         default:
661                 STC_LOGE("Unhandled command");
662                 ret = STC_ERROR_INVALID_PARAMETER;
663         }
664
665         return ret;
666 }
667
668 API stc_plugin_procfs_s stc_plugin_procfs = {
669         .initialize_plugin =
670                 stc_plugin_procfs_initialize,
671         .deinitialize_plugin =
672                 stc_plugin_procfs_deinitialize,
673         .procfs_status_changed =
674                 stc_plugin_procfs_status_changed
675 };
676 //LCOV_EXCL_STOP