blob: 90ac9f0d2b32b32d31cba7166193ec9d24d0508c [file] [log] [blame]
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -07001/* Copyright (c) 2012 The Chromium OS 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
6#include <ctype.h>
Luis Hector Chavez40b25742013-09-22 19:44:06 -07007#include <stdio.h>
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -07008#include <string.h>
9
10#include "util.h"
11
Luis Hector Chavez40b25742013-09-22 19:44:06 -070012#include "libconstants.h"
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -070013#include "libsyscalls.h"
14
Mike Frysingerfccb4c92013-10-19 02:42:07 -040015/*
16 * These are syscalls used by the syslog() C library call. You can find them
17 * by running a simple test program. See below for x86_64 behavior:
18 * $ cat test.c
19 * main() { syslog(0, "foo"); }
20 * $ gcc test.c -static
21 * $ strace ./a.out
22 * ...
23 * socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3 <- look for socket connection
24 * connect(...) <- important
25 * sendto(...) <- important
26 * exit_group(0) <- finish!
27 */
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070028#if defined(__x86_64__)
29const char *log_syscalls[] = { "connect", "sendto" };
30#elif defined(__i386__)
31const char *log_syscalls[] = { "socketcall", "time" };
32#elif defined(__arm__)
33const char *log_syscalls[] = { "connect", "gettimeofday", "send" };
Jorge Lucangeli Obesa21c8fc2015-07-15 16:22:34 -070034#elif defined(__aarch64__) || defined(__powerpc__) || defined(__ia64__) || \
35 defined(__hppa__) || defined(__sparc__) || defined(__mips__)
Mike Frysingerfccb4c92013-10-19 02:42:07 -040036const char *log_syscalls[] = { "connect", "send" };
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070037#else
38#error "Unsupported platform"
39#endif
40
41const size_t log_syscalls_len = sizeof(log_syscalls)/sizeof(log_syscalls[0]);
42
Luis Hector Chavez21224552015-06-27 18:10:39 +000043long int parse_single_constant(char *constant_str, char **endptr);
44
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -070045int lookup_syscall(const char *name)
46{
47 const struct syscall_entry *entry = syscall_table;
48 for (; entry->name && entry->nr >= 0; ++entry)
49 if (!strcmp(entry->name, name))
50 return entry->nr;
51 return -1;
52}
53
54const char *lookup_syscall_name(int nr)
55{
56 const struct syscall_entry *entry = syscall_table;
57 for (; entry->name && entry->nr >= 0; ++entry)
58 if (entry->nr == nr)
59 return entry->name;
60 return NULL;
61}
62
Luis Hector Chavez40b25742013-09-22 19:44:06 -070063long int parse_constant(char *constant_str, char **endptr)
64{
Luis Hector Chavez21224552015-06-27 18:10:39 +000065 long int value = 0;
66 char *group, *lastpos = constant_str;
67 char *original_constant_str = constant_str;
68
69 /*
70 * Try to parse constants separated by pipes. Note that since
71 * |constant_str| is an atom, there can be no spaces between the
72 * constant and the pipe. Constants can be either a named constant
73 * defined in libconstants.gen.c or a number parsed with strtol.
74 *
75 * If there is an error parsing any of the constants, the whole process
76 * fails.
77 */
78 while ((group = tokenize(&constant_str, "|")) != NULL) {
79 char *end = group;
80 value |= parse_single_constant(group, &end);
81 if (end == group) {
82 lastpos = original_constant_str;
83 value = 0;
84 break;
85 }
86 lastpos = end;
87 }
88 if (endptr)
89 *endptr = lastpos;
90 return value;
91}
92
93long int parse_single_constant(char *constant_str, char **endptr)
94{
Luis Hector Chavez40b25742013-09-22 19:44:06 -070095 const struct constant_entry *entry = constant_table;
96 for (; entry->name; ++entry) {
97 if (!strcmp(entry->name, constant_str)) {
98 if (endptr)
99 *endptr = constant_str + strlen(constant_str);
100
101 return entry->value;
102 }
103 }
104
105 return strtol(constant_str, endptr, 0);
106}
107
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -0700108char *strip(char *s)
109{
110 char *end;
111 while (*s && isblank(*s))
112 s++;
113 end = s + strlen(s) - 1;
114 while (end >= s && *end && (isblank(*end) || *end == '\n'))
115 end--;
116 *(end + 1) = '\0';
117 return s;
118}
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800119
Jorge Lucangeli Obesc8b21e12014-06-13 14:26:16 -0700120char *tokenize(char **stringp, const char *delim)
121{
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800122 char *ret = NULL;
123
124 /* If the string is NULL or empty, there are no tokens to be found. */
125 if (stringp == NULL || *stringp == NULL || **stringp == '\0')
126 return NULL;
127
128 /*
129 * If the delimiter is NULL or empty,
130 * the full string makes up the only token.
131 */
132 if (delim == NULL || *delim == '\0') {
133 ret = *stringp;
134 *stringp = NULL;
135 return ret;
136 }
137
138 char *found;
139 while (**stringp != '\0') {
140 found = strstr(*stringp, delim);
141
142 if (!found) {
143 /*
144 * The delimiter was not found, so the full string
145 * makes up the only token, and we're done.
146 */
147 ret = *stringp;
148 *stringp = NULL;
149 break;
150 }
151
152 if (found != *stringp) {
153 /* There's a non-empty token before the delimiter. */
154 *found = '\0';
155 ret = *stringp;
156 *stringp = found + strlen(delim);
157 break;
158 }
159
160 /*
161 * The delimiter was found at the start of the string,
162 * skip it and keep looking for a non-empty token.
163 */
164 *stringp += strlen(delim);
165 }
166
167 return ret;
168}