blob: e4acac2af22d751c7df1e2fc88a5d2a1fda4f264 [file] [log] [blame]
Mark Salyzyn42958412013-11-22 10:50:27 -08001/*
Mark Salyzynd0a83fd2014-01-09 07:45:30 -08002** Copyright 2013-2014, The Android Open Source Project
Mark Salyzyn42958412013-11-22 10:50:27 -08003**
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
Mark Salyzyn42958412013-11-22 10:50:27 -080017#include <errno.h>
18#include <fcntl.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080019#include <signal.h>
20#include <stddef.h>
21#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
Mark Salyzyn42958412013-11-22 10:50:27 -080022#include <stdlib.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080023#include <string.h>
24#include <unistd.h>
25
Mark Salyzyn42958412013-11-22 10:50:27 -080026#include <cutils/list.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080027#include <cutils/sockets.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080028#include <log/log.h>
29#include <log/logger.h>
30
Mark Salyzyn154f4602014-02-20 14:59:07 -080031/* branchless on many architectures. */
32#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn1345f382014-01-14 08:41:27 -080033
Mark Salyzyn154f4602014-02-20 14:59:07 -080034#define WEAK __attribute__((weak))
35#define UNUSED __attribute__((unused))
Mark Salyzyn1345f382014-01-14 08:41:27 -080036
Mark Salyzyn154f4602014-02-20 14:59:07 -080037/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080038
Mark Salyzyn154f4602014-02-20 14:59:07 -080039#ifdef HAVE_WINSOCK
Mark Salyzyn42958412013-11-22 10:50:27 -080040
Mark Salyzyn154f4602014-02-20 14:59:07 -080041int WEAK socket_local_client(const char *name, int namespaceId, int type)
42{
43 errno = ENOSYS;
44 return -ENOSYS;
45}
Mark Salyzyn42958412013-11-22 10:50:27 -080046
Mark Salyzyn154f4602014-02-20 14:59:07 -080047#else /* !HAVE_WINSOCK */
48
49#include <sys/socket.h>
50#include <sys/un.h>
51#include <sys/select.h>
52#include <sys/types.h>
53
54/* Private copy of ../libcutils/socket_local.h prevent library loops */
55#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
56#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
57/* End of ../libcutils/socket_local.h */
58
59#define LISTEN_BACKLOG 4
60
61/* Documented in header file. */
62int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
63 struct sockaddr_un *p_addr, socklen_t *alen)
64{
65 memset (p_addr, 0, sizeof (*p_addr));
66 size_t namelen;
67
68 switch (namespaceId) {
69 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
70#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
71 namelen = strlen(name);
72
73 /* Test with length +1 for the *initial* '\0'. */
74 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
75 goto error;
76 }
77
78 /*
79 * Note: The path in this case is *not* supposed to be
80 * '\0'-terminated. ("man 7 unix" for the gory details.)
81 */
82
83 p_addr->sun_path[0] = 0;
84 memcpy(p_addr->sun_path + 1, name, namelen);
85#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
86 /* this OS doesn't have the Linux abstract namespace */
87
88 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
89 /* unix_path_max appears to be missing on linux */
90 if (namelen > sizeof(*p_addr)
91 - offsetof(struct sockaddr_un, sun_path) - 1) {
92 goto error;
93 }
94
95 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
96 strcat(p_addr->sun_path, name);
97#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
98 break;
99
100 case ANDROID_SOCKET_NAMESPACE_RESERVED:
101 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
102 /* unix_path_max appears to be missing on linux */
103 if (namelen > sizeof(*p_addr)
104 - offsetof(struct sockaddr_un, sun_path) - 1) {
105 goto error;
106 }
107
108 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
109 strcat(p_addr->sun_path, name);
110 break;
111
112 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
113 namelen = strlen(name);
114 /* unix_path_max appears to be missing on linux */
115 if (namelen > sizeof(*p_addr)
116 - offsetof(struct sockaddr_un, sun_path) - 1) {
117 goto error;
118 }
119
120 strcpy(p_addr->sun_path, name);
121 break;
122
123 default:
124 /* invalid namespace id */
125 return -1;
126 }
127
128 p_addr->sun_family = AF_LOCAL;
129 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
130 return 0;
131error:
132 return -1;
133}
134
135/**
136 * connect to peer named "name" on fd
137 * returns same fd or -1 on error.
138 * fd is not closed on error. that's your job.
139 *
140 * Used by AndroidSocketImpl
141 */
142int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
143 int type UNUSED)
144{
145 struct sockaddr_un addr;
146 socklen_t alen;
147 size_t namelen;
148 int err;
149
150 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
151
152 if (err < 0) {
153 goto error;
154 }
155
156 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
157 goto error;
158 }
159
160 return fd;
161
162error:
163 return -1;
164}
165
166/**
167 * connect to peer named "name"
168 * returns fd or -1 on error
169 */
170int WEAK socket_local_client(const char *name, int namespaceId, int type)
171{
172 int s;
173
174 s = socket(AF_LOCAL, type, 0);
175 if(s < 0) return -1;
176
177 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
178 close(s);
179 return -1;
180 }
181
182 return s;
183}
184
185#endif /* !HAVE_WINSOCK */
186/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800187
188#define logger_for_each(logger, logger_list) \
189 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
190 logger != node_to_item(&(logger_list)->node, struct logger, node); \
191 logger = node_to_item((logger)->node.next, struct logger, node))
192
193/* In the future, we would like to make this list extensible */
194static const char *LOG_NAME[LOG_ID_MAX] = {
195 [LOG_ID_MAIN] = "main",
196 [LOG_ID_RADIO] = "radio",
197 [LOG_ID_EVENTS] = "events",
198 [LOG_ID_SYSTEM] = "system"
199};
200
Mark Salyzyn154f4602014-02-20 14:59:07 -0800201const char *android_log_id_to_name(log_id_t log_id)
202{
Mark Salyzyn42958412013-11-22 10:50:27 -0800203 if (log_id >= LOG_ID_MAX) {
204 log_id = LOG_ID_MAIN;
205 }
206 return LOG_NAME[log_id];
207}
208
Mark Salyzyn154f4602014-02-20 14:59:07 -0800209log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800210{
Mark Salyzyn42958412013-11-22 10:50:27 -0800211 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800212 int ret;
213
214 if (!logName) {
215 return -1; /* NB: log_id_t is unsigned */
216 }
217 b = strrchr(logName, '/');
218 if (!b) {
219 b = logName;
220 } else {
221 ++b;
222 }
223
Mark Salyzyn42958412013-11-22 10:50:27 -0800224 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
225 const char *l = LOG_NAME[ret];
226 if (l && !strcmp(b, l)) {
227 return ret;
228 }
229 }
230 return -1; /* should never happen */
231}
232
233struct logger_list {
234 struct listnode node;
235 int mode;
236 unsigned int tail;
237 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800238 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800239};
240
241struct logger {
242 struct listnode node;
243 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800244 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800245};
246
247/* android_logger_alloc unimplemented, no use case */
248/* android_logger_free not exported */
249static void android_logger_free(struct logger *logger)
250{
251 if (!logger) {
252 return;
253 }
254
Mark Salyzyn42958412013-11-22 10:50:27 -0800255 list_remove(&logger->node);
256
257 free(logger);
258}
259
Mark Salyzyn154f4602014-02-20 14:59:07 -0800260/* android_logger_alloc unimplemented, no use case */
261
262/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800263log_id_t android_logger_get_id(struct logger *logger)
264{
265 return logger->id;
266}
267
268/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800269static ssize_t send_log_msg(struct logger *logger,
270 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800271{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800272 ssize_t ret;
273 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
274 SOCK_STREAM);
275 if (sock < 0) {
276 ret = sock;
277 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800278 }
279
Mark Salyzyn154f4602014-02-20 14:59:07 -0800280 if (msg) {
281 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800282 }
283
Mark Salyzyn154f4602014-02-20 14:59:07 -0800284 ret = write(sock, buf, strlen(buf) + 1);
285 if (ret <= 0) {
286 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800287 }
288
Mark Salyzyn154f4602014-02-20 14:59:07 -0800289 ret = read(sock, buf, buf_size);
290
291done:
292 if ((ret == -1) && errno) {
293 ret = -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800294 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800295 close(sock);
Mark Salyzyn42958412013-11-22 10:50:27 -0800296 return ret;
297}
298
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800299static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800300{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800301 if (ret < 0) {
302 return ret;
303 }
304
305 if (strncmp(buf, "success", 7)) {
306 return -1;
307 }
308
309 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800310}
311
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800312int android_logger_clear(struct logger *logger)
313{
314 char buf[512];
315
316 return check_log_success(buf,
317 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
318}
319
Mark Salyzyn42958412013-11-22 10:50:27 -0800320/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800321long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800322{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800323 char buf[512];
324
325 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
326 if (ret < 0) {
327 return ret;
328 }
329
330 if ((buf[0] < '0') || ('9' < buf[0])) {
331 return -1;
332 }
333
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800334 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800335}
336
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800337#ifdef USERDEBUG_BUILD
338
339int android_logger_set_log_size(struct logger *logger, unsigned long size)
340{
341 char buf[512];
342
343 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
344 logger ? logger->id : (unsigned) -1, size);
345
346 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
347}
348
349#endif /* USERDEBUG_BUILD */
350
Mark Salyzyn42958412013-11-22 10:50:27 -0800351/*
352 * returns the readable size of the log's ring buffer (that is, amount of the
353 * log consumed)
354 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800355long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800356{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800357 char buf[512];
358
359 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
360 if (ret < 0) {
361 return ret;
362 }
363
364 if ((buf[0] < '0') || ('9' < buf[0])) {
365 return -1;
366 }
367
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800368 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800369}
370
371/*
372 * returns the logger version
373 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800374int android_logger_get_log_version(struct logger *logger UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800375{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800376 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800377}
378
Mark Salyzyn34facab2014-02-06 14:48:50 -0800379/*
380 * returns statistics
381 */
382ssize_t android_logger_get_statistics(struct logger_list *logger_list,
383 char *buf, size_t len)
384{
385 struct listnode *node;
386 struct logger *logger;
387 char *cp = buf;
388 size_t remaining = len;
389 size_t n;
390
391 n = snprintf(cp, remaining, "getStatistics");
392 n = min(n, remaining);
393 remaining -= n;
394 cp += n;
395
396 logger_for_each(logger, logger_list) {
397 n = snprintf(cp, remaining, " %d", logger->id);
398 n = min(n, remaining);
399 remaining -= n;
400 cp += n;
401 }
402 return send_log_msg(NULL, NULL, buf, len);
403}
404
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800405#ifdef USERDEBUG_BUILD
406
407ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
408 char *buf, size_t len)
409{
410 return send_log_msg(NULL, "getPruneList", buf, len);
411}
412
413int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
414 char *buf, size_t len)
415{
416 const char cmd[] = "setPruneList ";
417 const size_t cmdlen = sizeof(cmd) - 1;
418
419 if (strlen(buf) > (len - cmdlen)) {
420 return -ENOMEM; /* KISS */
421 }
422 memmove(buf + cmdlen, buf, len - cmdlen);
423 buf[len - 1] = '\0';
424 memcpy(buf, cmd, cmdlen);
425
426 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
427}
428
429#endif /* USERDEBUG_BUILD */
430
Mark Salyzyn42958412013-11-22 10:50:27 -0800431struct logger_list *android_logger_list_alloc(int mode,
432 unsigned int tail,
433 pid_t pid)
434{
435 struct logger_list *logger_list;
436
437 logger_list = calloc(1, sizeof(*logger_list));
438 if (!logger_list) {
439 return NULL;
440 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800441
Mark Salyzyn42958412013-11-22 10:50:27 -0800442 list_init(&logger_list->node);
443 logger_list->mode = mode;
444 logger_list->tail = tail;
445 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800446 logger_list->sock = -1;
447
Mark Salyzyn42958412013-11-22 10:50:27 -0800448 return logger_list;
449}
450
451/* android_logger_list_register unimplemented, no use case */
452/* android_logger_list_unregister unimplemented, no use case */
453
454/* Open the named log and add it to the logger list */
455struct logger *android_logger_open(struct logger_list *logger_list,
456 log_id_t id)
457{
458 struct listnode *node;
459 struct logger *logger;
460 char *n;
461
462 if (!logger_list || (id >= LOG_ID_MAX)) {
463 goto err;
464 }
465
466 logger_for_each(logger, logger_list) {
467 if (logger->id == id) {
468 goto ok;
469 }
470 }
471
472 logger = calloc(1, sizeof(*logger));
473 if (!logger) {
474 goto err;
475 }
476
Mark Salyzyn42958412013-11-22 10:50:27 -0800477 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800478 list_add_tail(&logger_list->node, &logger->node);
479 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800480 goto ok;
481
Mark Salyzyn42958412013-11-22 10:50:27 -0800482err:
483 logger = NULL;
484ok:
485 return logger;
486}
487
488/* Open the single named log and make it part of a new logger list */
489struct logger_list *android_logger_list_open(log_id_t id,
490 int mode,
491 unsigned int tail,
492 pid_t pid)
493{
494 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
495 if (!logger_list) {
496 return NULL;
497 }
498
499 if (!android_logger_open(logger_list, id)) {
500 android_logger_list_free(logger_list);
501 return NULL;
502 }
503
504 return logger_list;
505}
506
Mark Salyzyn154f4602014-02-20 14:59:07 -0800507static void caught_signal(int signum UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800508{
Mark Salyzyn42958412013-11-22 10:50:27 -0800509}
510
511/* Read from the selected logs */
512int android_logger_list_read(struct logger_list *logger_list,
513 struct log_msg *log_msg)
514{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800515 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800516 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800517 struct sigaction ignore;
518 struct sigaction old_sigaction;
519 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800520
521 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800522 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800523 }
524
Mark Salyzyn154f4602014-02-20 14:59:07 -0800525 if (logger_list->mode & O_NONBLOCK) {
526 memset(&ignore, 0, sizeof(ignore));
527 ignore.sa_handler = caught_signal;
528 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800529 }
530
Mark Salyzyn154f4602014-02-20 14:59:07 -0800531 if (logger_list->sock < 0) {
532 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800533
Mark Salyzyn154f4602014-02-20 14:59:07 -0800534 int sock = socket_local_client("logdr",
535 ANDROID_SOCKET_NAMESPACE_RESERVED,
536 SOCK_SEQPACKET);
537 if (sock < 0) {
538 if ((sock == -1) && errno) {
539 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800540 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800541 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800542 }
543
Mark Salyzyn154f4602014-02-20 14:59:07 -0800544 strcpy(buffer,
545 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
546 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800547
Mark Salyzyn154f4602014-02-20 14:59:07 -0800548 strcpy(cp, " lids");
549 cp += 5;
550 c = '=';
551 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800552 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800553 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
554 ret = min(ret, remaining);
555 remaining -= ret;
556 cp += ret;
557 c = ',';
558 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800559
Mark Salyzyn154f4602014-02-20 14:59:07 -0800560 if (logger_list->tail) {
561 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
562 ret = min(ret, remaining);
563 remaining -= ret;
564 cp += ret;
565 }
566
567 if (logger_list->pid) {
568 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
569 ret = min(ret, remaining);
570 remaining -= ret;
571 cp += ret;
572 }
573
574 if (logger_list->mode & O_NONBLOCK) {
575 /* Deal with an unresponsive logd */
576 sigaction(SIGALRM, &ignore, &old_sigaction);
577 old_alarm = alarm(30);
578 }
579 ret = write(sock, buffer, cp - buffer);
580 e = errno;
581 if (logger_list->mode & O_NONBLOCK) {
582 if (e == EINTR) {
583 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800584 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800585 alarm(old_alarm);
586 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800587 }
588
589 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800590 close(sock);
591 if ((ret == -1) && e) {
592 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800593 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800594 if (ret == 0) {
595 return -EIO;
596 }
597 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800598 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800599
600 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800601 }
602
Mark Salyzyn154f4602014-02-20 14:59:07 -0800603 ret = 0;
604 while(1) {
605 memset(log_msg, 0, sizeof(*log_msg));
606
607 if (logger_list->mode & O_NONBLOCK) {
608 /* particularily useful if tombstone is reporting for logd */
609 sigaction(SIGALRM, &ignore, &old_sigaction);
610 old_alarm = alarm(30);
611 }
612 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
613 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
614 e = errno;
615 if (logger_list->mode & O_NONBLOCK) {
616 if ((ret == 0) || (e == EINTR)) {
617 e = EAGAIN;
618 ret = -1;
619 }
620 alarm(old_alarm);
621 sigaction(SIGALRM, &old_sigaction, NULL);
622 }
623
624 if (ret <= 0) {
625 if ((ret == -1) && e) {
626 return -e;
627 }
628 return ret;
629 }
630
631 logger_for_each(logger, logger_list) {
632 if (log_msg->entry.lid == logger->id) {
633 return ret;
634 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800635 }
636 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800637 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800638 return ret;
639}
640
641/* Close all the logs */
642void android_logger_list_free(struct logger_list *logger_list)
643{
644 if (logger_list == NULL) {
645 return;
646 }
647
648 while (!list_empty(&logger_list->node)) {
649 struct listnode *node = list_head(&logger_list->node);
650 struct logger *logger = node_to_item(node, struct logger, node);
651 android_logger_free(logger);
652 }
653
Mark Salyzyn154f4602014-02-20 14:59:07 -0800654 if (logger_list->sock >= 0) {
655 close (logger_list->sock);
656 }
657
Mark Salyzyn42958412013-11-22 10:50:27 -0800658 free(logger_list);
659}