libamxp  1.4.0
Patterns C Implementation
amxp_proc_info.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include <sys/resource.h>
60 
61 #include <stdlib.h>
62 #include <stdio.h>
63 #include <string.h>
64 #include <fcntl.h>
65 #include <errno.h>
66 #include <limits.h>
67 #include <libgen.h>
68 #include <dirent.h>
69 #include <ctype.h>
70 
71 #include <amxc/amxc.h>
72 #include <amxc/amxc_macros.h>
73 #include <amxp/amxp.h>
74 
76  amxc_var_t* value,
77  const char* path,
78  void* priv) {
80  amxp_proc_info_t* pi = (amxp_proc_info_t*) priv;
81 
82  if(strcmp(path, "name") == 0) {
83  amxc_var_set(cstring_t, value, pi->name);
84  } else if(strcmp(path, "parent_pid") == 0) {
85  amxc_var_set(int32_t, value, pi->parent_pid);
86  } else if(strcmp(path, "ppid") == 0) {
87  amxc_var_set(int32_t, value, pi->parent_pid);
88  } else if(strcmp(path, "state") == 0) {
89  amxc_var_set(int8_t, value, pi->state);
90  } else {
92  }
93 
94  return status;
95 }
96 
97 static void amxp_proci_fill(amxp_proc_info_t* proc_info, amxc_var_t* data) {
98  int index = 0;
99  amxc_var_for_each(item, data) {
100  switch(index) {
101  case 0:
102  proc_info->pid = amxc_var_dyncast(int32_t, item);
103  break;
104  case 1: {
105  amxc_string_t name;
106  char* n = amxc_var_take(cstring_t, item);
107  amxc_string_init(&name, 0);
108  amxc_string_push_buffer(&name, n, n == NULL ? 0 : strlen(n) + 1);
109  amxc_string_trim(&name, ispunct);
110  proc_info->name = amxc_string_take_buffer(&name);
111  }
112  break;
113  case 2:
114  proc_info->state = amxc_var_dyncast(int8_t, item);
115  break;
116  case 3:
117  proc_info->parent_pid = amxc_var_dyncast(int32_t, item);
118  break;
119  case 4:
120  proc_info->process_gid = amxc_var_dyncast(int32_t, item);
121  break;
122  case 5:
123  proc_info->session_id = amxc_var_dyncast(int32_t, item);
124  break;
125  }
126  index++;
127  }
128 }
129 
130 static amxp_proc_info_t* amxp_proci_read_stat(amxc_string_t* file) {
131  FILE* fp = NULL;
132  amxp_proc_info_t* proc_info = NULL;
133  amxc_var_t stat;
134  ssize_t read = 0;
135  char* line = NULL;
136  size_t len = 0;
137 
138  amxc_var_init(&stat);
139 
140  fp = fopen(amxc_string_get(file, 0), "r");
141  if(fp == NULL) {
142  goto exit;
143  }
144 
145  read = getline(&line, &len, fp);
146  if(read == -1) {
147  fclose(fp);
148  free(line);
149  goto exit;
150  }
151  fclose(fp);
152 
153  amxc_var_push(ssv_string_t, &stat, line);
154  amxc_var_cast(&stat, AMXC_VAR_ID_LIST);
155 
156  proc_info = (amxp_proc_info_t*) calloc(1, sizeof(amxp_proc_info_t));
157  when_null(proc_info, exit);
158 
159  amxp_proci_fill(proc_info, &stat);
160 
161 exit:
162  amxc_var_clean(&stat);
163  return proc_info;
164 }
165 
166 static int amxp_proci_scan_proc(amxc_llist_t* procs, amxp_expr_t* expr) {
167  int retval = -1;
168  DIR* dp;
169  struct dirent* ep;
170  amxc_string_t filename;
171  amxp_proc_info_t* pi = NULL;
173 
174  amxc_string_init(&filename, 128);
175 
176  dp = opendir("/proc/");
177  when_null(dp, exit);
178 
179  for(ep = readdir(dp); ep; ep = readdir(dp)) {
180  if(ep->d_type != DT_DIR) {
181  continue;
182  }
183 
184  if(ep->d_name[0] == '.') {
185  continue;
186  }
187 
188  amxc_string_reset(&filename);
189  amxc_string_setf(&filename, "/proc/%s/stat", ep->d_name);
190  pi = amxp_proci_read_stat(&filename);
191  if(pi != NULL) {
192  if(expr != NULL) {
193  if(amxp_expr_evaluate(expr, amxp_proci_expr_get_field, pi, &status)) {
194  amxc_llist_append(procs, &pi->it);
195  } else {
196  amxp_proci_free_it(&pi->it);
197  }
198  } else {
199  amxc_llist_append(procs, &pi->it);
200  }
201  }
202 
203  }
204  closedir(dp);
205 
206  retval = 0;
207 
208 exit:
209  amxc_string_clean(&filename);
210  return retval;
211 }
212 
213 void amxp_proci_free_it(amxc_llist_it_t* it) {
214  amxp_proc_info_t* pi = amxc_container_of(it, amxp_proc_info_t, it);
215  free(pi->name);
216  free(pi);
217 }
218 
219 int amxp_proci_findf(amxc_llist_t* result, const char* filter, ...) {
220  int retval = -1;
221  amxc_string_t expression;
222  va_list args;
223  amxp_expr_t expr;
224 
225  amxc_string_init(&expression, 0);
226  when_null(result, exit);
227 
228  if(filter != NULL) {
229  va_start(args, filter);
230  amxc_string_vsetf(&expression, filter, args);
231  va_end(args);
232  when_failed(amxp_expr_init(&expr, amxc_string_get(&expression, 0)), exit);
233  }
234 
235 
236  retval = amxp_proci_scan_proc(result, filter == NULL ? NULL : &expr);
237 
238 exit:
239  if(filter != NULL) {
240  amxp_expr_clean(&expr);
241  }
242  amxc_string_clean(&expression);
243  return retval;
244 }
static void amxp_proci_fill(amxp_proc_info_t *proc_info, amxc_var_t *data)
static amxp_expr_status_t amxp_proci_expr_get_field(UNUSED amxp_expr_t *expr, amxc_var_t *value, const char *path, void *priv)
static amxp_proc_info_t * amxp_proci_read_stat(amxc_string_t *file)
static int amxp_proci_scan_proc(amxc_llist_t *procs, amxp_expr_t *expr)
#define UNUSED
Definition: main.c:68
void amxp_expr_clean(amxp_expr_t *expr)
Clean-up the expression structure.
amxp_expr_status_t amxp_expr_init(amxp_expr_t *expr, const char *expression)
Initializes an expression structure.
bool amxp_expr_evaluate(amxp_expr_t *expr, amxp_expr_get_field_t fn, void *priv, amxp_expr_status_t *status)
Evaluates an expression.
enum _expr_status amxp_expr_status_t
Expression status/error codes.
@ amxp_expr_status_field_not_found
@ amxp_expr_status_ok
void amxp_proci_free_it(amxc_llist_it_t *it)
Delete a amxp_proc_info_t by it is linked list iterator.
int amxp_proci_findf(amxc_llist_t *result, const char *filter,...)
Build a linked list of running processes.
Structure containing the process information.
int32_t session_id
int32_t pid
amxc_llist_it_t it
uint8_t state
int32_t parent_pid
int32_t process_gid
static amxc_string_t path