Rizin
unix-like reverse engineering framework and cli tools
syscmd.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_core.h>
5 #include <errno.h>
6 
7 #define FMT_NONE 0
8 #define FMT_RAW 1
9 #define FMT_JSON 2
10 
11 static int needs_newline = 0;
12 
13 static char *showfile(char *res, const int nth, const char *fpath, const char *name, int printfmt) {
14 #if __UNIX__
15  struct stat sb;
16 #endif
17  const char *n = fpath;
18  char *nn, *u_rwx = NULL;
19  int sz = rz_file_size(n);
20  int perm, uid = 0, gid = 0;
21  int fch = '-';
22  if (!strncmp(fpath, "./", 2)) {
23  fpath = fpath + 2;
24  }
25  const bool isdir = rz_file_is_directory(n);
26  if (isdir) {
27  nn = rz_str_append(strdup(fpath), "/");
28  } else {
29  nn = strdup(fpath);
30  }
31  if (!*nn) {
32  free(nn);
33  return res;
34  }
35  perm = isdir ? 0755 : 0644;
36  if (!printfmt) {
37  needs_newline = ((nth + 1) % 4) ? 1 : 0;
38  res = rz_str_appendf(res, "%18s%s", nn, needs_newline ? " " : "\n");
39  free(nn);
40  return res;
41  }
42  // TODO: escape non-printable chars in filenames
43  // TODO: Implement more real info in ls -l
44  // TODO: handle suid
45 #if __UNIX__
46  if (lstat(n, &sb) != -1) {
47  ut32 ifmt = sb.st_mode & S_IFMT;
48  uid = sb.st_uid;
49  gid = sb.st_gid;
50  perm = sb.st_mode & 0777;
51  if (!(u_rwx = strdup(rz_str_rwx_i(perm >> 6)))) {
52  free(nn);
53  return res;
54  }
55  if (sb.st_mode & S_ISUID) {
56  u_rwx[2] = (sb.st_mode & S_IXUSR) ? 's' : 'S';
57  }
58  if (isdir) {
59  fch = 'd';
60  } else {
61  switch (ifmt) {
62  case S_IFCHR: fch = 'c'; break;
63  case S_IFBLK: fch = 'b'; break;
64  case S_IFLNK: fch = 'l'; break;
65  case S_IFIFO: fch = 'p'; break;
66 #ifdef S_IFSOCK
67  case S_IFSOCK: fch = 's'; break;
68 #endif
69  }
70  }
71  }
72 #else
73  u_rwx = strdup("-");
74  fch = isdir ? 'd' : '-';
75 #endif
76  if (printfmt == 'q') {
77  res = rz_str_appendf(res, "%s\n", nn);
78  } else if (printfmt == 'e') {
79  const char *eDIR = "📁";
80  const char *eIMG = "🌅";
81  const char *eHID = "👀";
82  const char *eANY = " ";
83  // --
84  const char *icon = eANY;
85  if (isdir) {
86  icon = eDIR;
87 #if __UNIX__
88  } else if ((sb.st_mode & S_IFMT) == S_IFLNK) {
89  const char *eLNK = "📎";
90  icon = eLNK;
91  } else if (sb.st_mode & S_ISUID) {
92  const char *eUID = "🔼";
93  icon = eUID;
94 #endif
95  } else if (rz_str_casestr(nn, ".jpg") || rz_str_casestr(nn, ".png") || rz_str_casestr(nn, ".gif")) {
96  icon = eIMG;
97  } else if (*nn == '.') {
98  icon = eHID;
99  }
100  res = rz_str_appendf(res, "%s %s\n", icon, nn);
101  } else if (printfmt == FMT_RAW) {
102  res = rz_str_appendf(res, "%c%s%s%s 1 %4d:%-4d %-10d %s\n",
103  isdir ? 'd' : fch,
104  u_rwx ? u_rwx : "-",
105  rz_str_rwx_i((perm >> 3) & 7),
106  rz_str_rwx_i(perm & 7),
107  uid, gid, sz, nn);
108  } else if (printfmt == FMT_JSON) {
109  if (nth > 0) {
110  res = rz_str_append(res, ",");
111  }
112  res = rz_str_appendf(res, "{\"name\":\"%s\",\"size\":%d,\"uid\":%d,"
113  "\"gid\":%d,\"perm\":%d,\"isdir\":%s}",
114  name, sz, uid, gid, perm, isdir ? "true" : "false");
115  }
116  free(nn);
117  free(u_rwx);
118  return res;
119 }
120 
122  char *res = NULL;
123  const char *path = ".";
124  char *d = NULL;
125  char *p = NULL;
126  char *homepath = NULL;
127  char *pattern = NULL;
128  int printfmt = 0;
129  RzListIter *iter;
130  RzList *files;
131  char *name;
132  char *dir;
133  int off;
134  if (!input) {
135  input = "";
136  path = ".";
137  }
138  if (*input == 'q') {
139  printfmt = 'q';
140  input++;
141  }
142  if (*input && input[0] == ' ') {
143  input++;
144  }
145  if (*input) {
146  if ((!strncmp(input, "-h", 2))) {
147  eprintf("Usage: ls ([-e,-l,-j,-q]) ([path]) # long, json, quiet\n");
148  } else if ((!strncmp(input, "-e", 2))) {
149  printfmt = 'e';
151  } else if ((!strncmp(input, "-q", 2))) {
152  printfmt = 'q';
154  } else if ((!strncmp(input, "-l", 2)) || (!strncmp(input, "-j", 2))) {
155  // mode = 'l';
156  if (input[2]) {
157  printfmt = (input[2] == 'j') ? FMT_JSON : FMT_RAW;
159  if (!*path) {
160  path = ".";
161  }
162  } else {
163  printfmt = FMT_RAW;
164  }
165  } else {
166  path = input;
167  }
168  }
169  if (!path || !*path) {
170  path = ".";
171  } else if (rz_str_startswith(path, "~")) {
172  homepath = rz_path_home_expand(path);
173  if (homepath) {
174  path = (const char *)homepath;
175  }
176  } else if (*path == '$') {
177  if (!strncmp(path + 1, "home", 4) || !strncmp(path + 1, "HOME", 4)) {
178  homepath = rz_str_home((strlen(path) > 5) ? path + 6 : NULL);
179  if (homepath) {
180  path = (const char *)homepath;
181  }
182  }
183  }
184  if (!rz_file_is_directory(path)) {
185  p = strrchr(path, '/');
186  if (p) {
187  off = p - path;
188  d = (char *)calloc(1, off + 1);
189  if (!d) {
190  free(homepath);
191  return NULL;
192  }
193  memcpy(d, path, off);
194  path = (const char *)d;
195  pattern = strdup(p + 1);
196  } else {
197  pattern = strdup(path);
198  path = ".";
199  }
200  } else {
201  pattern = strdup("*");
202  }
203  if (rz_file_is_regular(path)) {
204  res = showfile(res, 0, path, path, printfmt);
205  free(homepath);
206  free(pattern);
207  free(d);
208  return res;
209  }
210  files = rz_sys_dir(path);
211 
212  if (path[strlen(path) - 1] == '/') {
213  dir = strdup(path);
214  } else {
215  dir = rz_str_append(strdup(path), "/");
216  }
217  int nth = 0;
218  if (printfmt == FMT_JSON) {
219  res = strdup("[");
220  }
221  needs_newline = 0;
222  rz_list_foreach (files, iter, name) {
223  char *n = rz_str_append(strdup(dir), name);
224  if (!n) {
225  break;
226  }
227  if (rz_str_glob(name, pattern)) {
228  if (*n) {
229  res = showfile(res, nth, n, name, printfmt);
230  }
231  nth++;
232  }
233  free(n);
234  }
235  if (printfmt == FMT_JSON) {
236  res = rz_str_append(res, "]");
237  }
238  if (needs_newline) {
239  res = rz_str_append(res, "\n");
240  }
241  free(dir);
242  free(d);
243  free(homepath);
244  free(pattern);
246  return res;
247 }
248 
249 static int cmpstr(const void *_a, const void *_b) {
250  const char *a = _a, *b = _b;
251  return (int)strcmp(a, b);
252 }
253 
256 
257  const char *p = NULL;
258  RzList *list = NULL;
259  if ((p = strchr(file, ' '))) {
260  p = p + 1;
261  } else {
262  p = file;
263  }
264  if (p && *p) {
265  char *filename = strdup(p);
267  char *data = rz_file_slurp(filename, NULL);
268  if (!data) {
269  eprintf("No such file or directory\n");
270  } else {
271  list = rz_str_split_list(data, "\n", 0);
273  data = rz_list_to_str(list, '\n');
275  }
276  free(filename);
277  return data;
278  } else {
279  eprintf("Usage: sort [file]\n");
280  }
281  return NULL;
282 }
283 
284 RZ_API RZ_OWN char *rz_syscmd_head(RZ_NONNULL const char *file, int count) {
286 
287  const char *p = NULL;
288  if ((p = strchr(file, ' '))) {
289  p = p + 1;
290  } else {
291  p = file;
292  }
293  if (p && *p) {
294  char *filename = strdup(p);
296  char *data = rz_file_slurp_lines(filename, 1, count);
297  if (!data) {
298  eprintf("No such file or directory\n");
299  }
300  free(filename);
301  return data;
302  } else {
303  eprintf("Usage: head 7 [file]\n");
304  }
305  return NULL;
306 }
307 
308 RZ_API RZ_OWN char *rz_syscmd_tail(RZ_NONNULL const char *file, int count) {
310 
311  const char *p = NULL;
312  if (file) {
313  if ((p = strchr(file, ' '))) {
314  p = p + 1;
315  } else {
316  p = file;
317  }
318  }
319  if (p && *p) {
320  char *filename = strdup(p);
323  if (!data) {
324  eprintf("No such file or directory\n");
325  }
326  free(filename);
327  return data;
328  } else {
329  eprintf("Usage: tail 7 [file]\n");
330  }
331  return NULL;
332 }
333 
336 
337  const char *p = NULL;
338  RzList *list = NULL;
339  if (file) {
340  if ((p = strchr(file, ' '))) {
341  p = p + 1;
342  } else {
343  p = file;
344  }
345  }
346  if (p && *p) {
347  char *filename = strdup(p);
349  char *data = rz_file_slurp(filename, NULL);
350  if (!data) {
351  eprintf("No such file or directory\n");
352  } else {
353  list = rz_str_split_list(data, "\n", 0);
354  RzList *uniq_list = rz_list_uniq(list, cmpstr);
355  data = rz_list_to_str(uniq_list, '\n');
356  rz_list_free(uniq_list);
358  }
359  free(filename);
360  return data;
361  } else {
362  eprintf("Usage: uniq [file]\n");
363  }
364  return NULL;
365 }
366 
367 RZ_API RZ_OWN char *rz_syscmd_join(RZ_NONNULL const char *file1, RZ_NONNULL const char *file2) {
368  rz_return_val_if_fail(file1 && file2, NULL);
369 
370  const char *p1 = NULL, *p2 = NULL;
371  if (file1) {
372  if ((p1 = strchr(file1, ' '))) {
373  p1 = p1 + 1;
374  } else {
375  p1 = file1;
376  }
377  }
378  if (file2) {
379  if ((p2 = strchr(file2, ' '))) {
380  p2 = p2 + 1;
381  } else {
382  p2 = file2;
383  }
384  }
385  if (p1 && *p1 && p2 && *p2) {
386  char *filename1 = strdup(p1);
387  char *filename2 = strdup(p2);
388  rz_str_trim(filename1);
389  rz_str_trim(filename2);
390  char *data1 = rz_file_slurp(filename1, NULL);
391  char *data2 = rz_file_slurp(filename2, NULL);
392  char *data = NULL;
393  if (!data1 && !data2) {
394  eprintf("No such files or directory\n");
395  } else {
397  RzList *list1 = rz_str_split_list(data1, "\n", 0);
398  RzList *list2 = rz_str_split_list(data2, "\n", 0);
399  if (!list || !list1 || !list2) {
400  rz_list_free(list2);
401  rz_list_free(list1);
403  return NULL;
404  }
405  char *str1, *str2;
406  RzListIter *iter1, *iter2;
407  rz_list_foreach (list1, iter1, str1) {
408  char *field = strdup(str1); // extract comman field
409  char *end = strchr(field, ' ');
410  if (end) {
411  *end = '\0';
412  } else {
413  free(field);
414  continue;
415  }
416  rz_list_foreach (list2, iter2, str2) {
417  if (rz_str_startswith(str2, field)) {
418  char *out = rz_str_new(field);
419  char *first = strchr(str1, ' ');
420  char *second = strchr(str2, ' ');
421  rz_str_append(out, first ? first : " ");
422  rz_str_append(out, second ? second : " ");
424  }
425  }
426  free(field);
427  }
428  data = rz_list_to_str(list, '\n');
429  rz_list_free(list2);
430  rz_list_free(list1);
432  }
433  free(filename1);
434  free(filename2);
435  return data;
436  } else {
437  eprintf("Usage: join file1 file2\n");
438  }
439  return NULL;
440 }
441 
444 
445  const char *p = NULL;
446  if (file) {
447  if ((p = strchr(file, ' '))) {
448  p = p + 1;
449  } else {
450  p = file;
451  }
452  }
453  if (p && *p) {
454  char *filename = strdup(p);
456  char *data = rz_file_slurp(filename, NULL);
457  if (!data) {
458  eprintf("No such file or directory\n");
459  }
460  free(filename);
461  return data;
462  } else {
463  eprintf("Usage: cat [file]\n");
464  }
465  return NULL;
466 }
467 
468 RZ_API RZ_OWN char *rz_syscmd_mkdir(RZ_NONNULL const char *dir) {
470 
471  const char *suffix = rz_str_trim_head_ro(strchr(dir, ' '));
472  if (!suffix || !strncmp(suffix, "-p", 3)) {
473  return rz_str_dup(NULL, "Usage: mkdir [-p] [directory]\n");
474  }
475  int ret;
476  char *dirname = (!strncmp(suffix, "-p ", 3))
477  ? strdup(suffix + 3)
478  : strdup(suffix);
479  rz_str_trim(dirname);
480  ret = rz_sys_mkdirp(dirname);
481  if (!ret && rz_sys_mkdir_failed()) {
482  char *res = rz_str_newf("Cannot create \"%s\"\n", dirname);
483  free(dirname);
484  return res;
485  }
486  free(dirname);
487  return NULL;
488 }
static SblHeader sb
Definition: bin_mbn.c:26
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint32_t ut32
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n output MIME type special files
Definition: file_opts.h:46
unsigned char suffix[65536]
Definition: gun.c:164
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char * filename
Definition: ioapi.h:137
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_uniq(RZ_NONNULL const RzList *list, RZ_NONNULL RzListComparator cmp)
Returns a new RzList which contains only unique values.
Definition: list.c:756
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API RZ_OWN char * rz_list_to_str(RZ_NONNULL RzList *list, char ch)
Casts a RzList containg strings into a concatenated string.
Definition: list.c:785
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int n
Definition: mipsasm.c:19
const char * name
Definition: op.c:541
int off
Definition: pal.c:13
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
RZ_API RZ_OWN char * rz_file_slurp_lines_from_bottom(const char *file, int line)
Definition: file.c:708
RZ_API bool rz_file_is_regular(const char *str)
Definition: file.c:159
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API ut64 rz_file_size(const char *str)
Definition: file.c:205
RZ_API char * rz_file_slurp_lines(const char *file, int line, int count)
Definition: file.c:736
RZ_API RZ_OWN char * rz_path_home_expand(RZ_NULLABLE const char *path)
Return a new path with the ~ char expanded to the home directory.
Definition: path.c:268
RZ_API const char * rz_str_rwx_i(int rwx)
Definition: str.c:332
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865
RZ_API char * rz_str_dup(char *ptr, const char *string)
Definition: str.c:1021
RZ_API char * rz_str_home(const char *str)
Definition: str.c:354
RZ_API bool rz_str_glob(const char *str, const char *glob)
Definition: str.c:2368
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API const char * rz_str_casestr(const char *a, const char *b)
Definition: str.c:2757
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
RZ_API bool rz_sys_mkdirp(const char *dir)
Definition: sys.c:691
RZ_API RzList * rz_sys_dir(const char *path)
Definition: sys.c:216
#define rz_sys_mkdir_failed()
Definition: rz_sys.h:91
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: gzappend.c:170
Definition: z80asm.h:102
Definition: sftypes.h:80
RZ_API RZ_OWN char * rz_syscmd_join(RZ_NONNULL const char *file1, RZ_NONNULL const char *file2)
Definition: syscmd.c:367
#define FMT_RAW
Definition: syscmd.c:8
#define FMT_JSON
Definition: syscmd.c:9
static int cmpstr(const void *_a, const void *_b)
Definition: syscmd.c:249
RZ_API RZ_OWN char * rz_syscmd_cat(RZ_NONNULL const char *file)
Definition: syscmd.c:442
RZ_API RZ_OWN char * rz_syscmd_sort(RZ_NONNULL const char *file)
Definition: syscmd.c:254
static char * showfile(char *res, const int nth, const char *fpath, const char *name, int printfmt)
Definition: syscmd.c:13
RZ_API RZ_OWN char * rz_syscmd_mkdir(RZ_NONNULL const char *dir)
Definition: syscmd.c:468
static int needs_newline
Definition: syscmd.c:11
RZ_API RZ_OWN char * rz_syscmd_tail(RZ_NONNULL const char *file, int count)
Definition: syscmd.c:308
RZ_API RZ_OWN char * rz_syscmd_head(RZ_NONNULL const char *file, int count)
Definition: syscmd.c:284
RZ_API RZ_OWN char * rz_syscmd_uniq(RZ_NONNULL const char *file)
Definition: syscmd.c:334
RZ_API RZ_OWN char * rz_syscmd_ls(RZ_NONNULL const char *input)
Definition: syscmd.c:121
#define S_IFLNK
Definition: win.h:68
static int file
Definition: z80asm.c:58
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)