• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2013-2014, The Android Open Source Project
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 <errno.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <poll.h>
21 #include <signal.h>
22 #include <stdbool.h>
23 #include <stddef.h>
24 #define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/cdefs.h>
28 #include <unistd.h>
29 
30 #include <cutils/list.h>
31 #include <cutils/sockets.h>
32 #include <log/log.h>
33 #include <log/logger.h>
34 #include <private/android_filesystem_config.h>
35 #include <private/android_logger.h>
36 
37 /* branchless on many architectures. */
38 #define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
39 
40 #if (defined(USE_MINGW) || defined(HAVE_WINSOCK))
41 #define WEAK static
42 #else
43 #define WEAK __attribute__((weak))
44 #endif
45 #ifndef __unused
46 #define __unused __attribute__((unused))
47 #endif
48 
49 /* Private copy of ../libcutils/socket_local_client.c prevent library loops */
50 
51 #ifdef HAVE_WINSOCK
52 
socket_local_client(const char * name,int namespaceId,int type)53 int WEAK socket_local_client(const char *name, int namespaceId, int type)
54 {
55     errno = ENOSYS;
56     return -ENOSYS;
57 }
58 
59 #else /* !HAVE_WINSOCK */
60 
61 #include <sys/socket.h>
62 #include <sys/un.h>
63 #include <sys/select.h>
64 #include <sys/types.h>
65 
66 /* Private copy of ../libcutils/socket_local.h prevent library loops */
67 #define FILESYSTEM_SOCKET_PREFIX "/tmp/"
68 #define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
69 /* End of ../libcutils/socket_local.h */
70 
71 #define LISTEN_BACKLOG 4
72 
73 /* Documented in header file. */
socket_make_sockaddr_un(const char * name,int namespaceId,struct sockaddr_un * p_addr,socklen_t * alen)74 int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
75                                  struct sockaddr_un *p_addr, socklen_t *alen)
76 {
77     memset (p_addr, 0, sizeof (*p_addr));
78     size_t namelen;
79 
80     switch (namespaceId) {
81     case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
82 #if defined(__linux__)
83         namelen  = strlen(name);
84 
85         /* Test with length +1 for the *initial* '\0'. */
86         if ((namelen + 1) > sizeof(p_addr->sun_path)) {
87             goto error;
88         }
89 
90         /*
91          * Note: The path in this case is *not* supposed to be
92          * '\0'-terminated. ("man 7 unix" for the gory details.)
93          */
94 
95         p_addr->sun_path[0] = 0;
96         memcpy(p_addr->sun_path + 1, name, namelen);
97 #else
98         /* this OS doesn't have the Linux abstract namespace */
99 
100         namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
101         /* unix_path_max appears to be missing on linux */
102         if (namelen > sizeof(*p_addr)
103                 - offsetof(struct sockaddr_un, sun_path) - 1) {
104             goto error;
105         }
106 
107         strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
108         strcat(p_addr->sun_path, name);
109 #endif
110         break;
111 
112     case ANDROID_SOCKET_NAMESPACE_RESERVED:
113         namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
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, ANDROID_RESERVED_SOCKET_PREFIX);
121         strcat(p_addr->sun_path, name);
122         break;
123 
124     case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
125         namelen = strlen(name);
126         /* unix_path_max appears to be missing on linux */
127         if (namelen > sizeof(*p_addr)
128                 - offsetof(struct sockaddr_un, sun_path) - 1) {
129             goto error;
130         }
131 
132         strcpy(p_addr->sun_path, name);
133         break;
134 
135     default:
136         /* invalid namespace id */
137         return -1;
138     }
139 
140     p_addr->sun_family = AF_LOCAL;
141     *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
142     return 0;
143 error:
144     return -1;
145 }
146 
147 /**
148  * connect to peer named "name" on fd
149  * returns same fd or -1 on error.
150  * fd is not closed on error. that's your job.
151  *
152  * Used by AndroidSocketImpl
153  */
socket_local_client_connect(int fd,const char * name,int namespaceId,int type __unused)154 int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
155                                      int type __unused)
156 {
157     struct sockaddr_un addr;
158     socklen_t alen;
159     int err;
160 
161     err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
162 
163     if (err < 0) {
164         goto error;
165     }
166 
167     if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
168         goto error;
169     }
170 
171     return fd;
172 
173 error:
174     return -1;
175 }
176 
177 /**
178  * connect to peer named "name"
179  * returns fd or -1 on error
180  */
socket_local_client(const char * name,int namespaceId,int type)181 int WEAK socket_local_client(const char *name, int namespaceId, int type)
182 {
183     int s;
184 
185     s = socket(AF_LOCAL, type, 0);
186     if(s < 0) return -1;
187 
188     if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
189         close(s);
190         return -1;
191     }
192 
193     return s;
194 }
195 
196 #endif /* !HAVE_WINSOCK */
197 /* End of ../libcutils/socket_local_client.c */
198 
199 #define logger_for_each(logger, logger_list) \
200     for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
201          logger != node_to_item(&(logger_list)->node, struct logger, node); \
202          logger = node_to_item((logger)->node.next, struct logger, node))
203 
204 /* In the future, we would like to make this list extensible */
205 static const char *LOG_NAME[LOG_ID_MAX] = {
206     [LOG_ID_MAIN] = "main",
207     [LOG_ID_RADIO] = "radio",
208     [LOG_ID_EVENTS] = "events",
209     [LOG_ID_SYSTEM] = "system",
210     [LOG_ID_CRASH] = "crash",
211     [LOG_ID_KERNEL] = "kernel",
212 };
213 
android_log_id_to_name(log_id_t log_id)214 const char *android_log_id_to_name(log_id_t log_id)
215 {
216     if (log_id >= LOG_ID_MAX) {
217         log_id = LOG_ID_MAIN;
218     }
219     return LOG_NAME[log_id];
220 }
221 
android_name_to_log_id(const char * logName)222 log_id_t android_name_to_log_id(const char *logName)
223 {
224     const char *b;
225     int ret;
226 
227     if (!logName) {
228         return -1; /* NB: log_id_t is unsigned */
229     }
230     b = strrchr(logName, '/');
231     if (!b) {
232         b = logName;
233     } else {
234         ++b;
235     }
236 
237     for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
238         const char *l = LOG_NAME[ret];
239         if (l && !strcmp(b, l)) {
240             return ret;
241         }
242     }
243     return -1;   /* should never happen */
244 }
245 
246 struct logger_list {
247     struct listnode node;
248     int mode;
249     unsigned int tail;
250     log_time start;
251     pid_t pid;
252     int sock;
253 };
254 
255 struct logger {
256     struct listnode node;
257     struct logger_list *top;
258     log_id_t id;
259 };
260 
261 /* android_logger_alloc unimplemented, no use case */
262 /* android_logger_free not exported */
android_logger_free(struct logger * logger)263 static void android_logger_free(struct logger *logger)
264 {
265     if (!logger) {
266         return;
267     }
268 
269     list_remove(&logger->node);
270 
271     free(logger);
272 }
273 
274 /* android_logger_alloc unimplemented, no use case */
275 
276 /* method for getting the associated sublog id */
android_logger_get_id(struct logger * logger)277 log_id_t android_logger_get_id(struct logger *logger)
278 {
279     return logger->id;
280 }
281 
282 /* worker for sending the command to the logger */
send_log_msg(struct logger * logger,const char * msg,char * buf,size_t buf_size)283 static ssize_t send_log_msg(struct logger *logger,
284                             const char *msg, char *buf, size_t buf_size)
285 {
286     ssize_t ret;
287     size_t len;
288     char *cp;
289     int errno_save = 0;
290     int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
291                                    SOCK_STREAM);
292     if (sock < 0) {
293         return sock;
294     }
295 
296     if (msg) {
297         snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
298     }
299 
300     len = strlen(buf) + 1;
301     ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
302     if (ret <= 0) {
303         goto done;
304     }
305 
306     len = buf_size;
307     cp = buf;
308     while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
309         struct pollfd p;
310 
311         if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
312             break;
313         }
314 
315         len -= ret;
316         cp += ret;
317 
318         memset(&p, 0, sizeof(p));
319         p.fd = sock;
320         p.events = POLLIN;
321 
322         /* Give other side 20ms to refill pipe */
323         ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
324 
325         if (ret <= 0) {
326             break;
327         }
328 
329         if (!(p.revents & POLLIN)) {
330             ret = 0;
331             break;
332         }
333     }
334 
335     if (ret >= 0) {
336         ret += buf_size - len;
337     }
338 
339 done:
340     if ((ret == -1) && errno) {
341         errno_save = errno;
342     }
343     close(sock);
344     if (errno_save) {
345         errno = errno_save;
346     }
347     return ret;
348 }
349 
check_log_success(char * buf,ssize_t ret)350 static int check_log_success(char *buf, ssize_t ret)
351 {
352     if (ret < 0) {
353         return ret;
354     }
355 
356     if (strncmp(buf, "success", 7)) {
357         errno = EINVAL;
358         return -1;
359     }
360 
361     return 0;
362 }
363 
364 /* Determine the credentials of the caller */
uid_has_log_permission(uid_t uid)365 static bool uid_has_log_permission(uid_t uid)
366 {
367     return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT);
368 }
369 
get_best_effective_uid()370 static uid_t get_best_effective_uid()
371 {
372     uid_t euid;
373     uid_t uid;
374     gid_t gid;
375     ssize_t i;
376     static uid_t last_uid = (uid_t) -1;
377 
378     if (last_uid != (uid_t) -1) {
379         return last_uid;
380     }
381     uid = getuid();
382     if (uid_has_log_permission(uid)) {
383         return last_uid = uid;
384     }
385     euid = geteuid();
386     if (uid_has_log_permission(euid)) {
387         return last_uid = euid;
388     }
389     gid = getgid();
390     if (uid_has_log_permission(gid)) {
391         return last_uid = gid;
392     }
393     gid = getegid();
394     if (uid_has_log_permission(gid)) {
395         return last_uid = gid;
396     }
397     i = getgroups((size_t) 0, NULL);
398     if (i > 0) {
399         gid_t list[i];
400 
401         getgroups(i, list);
402         while (--i >= 0) {
403             if (uid_has_log_permission(list[i])) {
404                 return last_uid = list[i];
405             }
406         }
407     }
408     return last_uid = uid;
409 }
410 
android_logger_clear(struct logger * logger)411 int android_logger_clear(struct logger *logger)
412 {
413     char buf[512];
414 
415     if (logger->top->mode & ANDROID_LOG_PSTORE) {
416         if (uid_has_log_permission(get_best_effective_uid())) {
417             return unlink("/sys/fs/pstore/pmsg-ramoops-0");
418         }
419         errno = EPERM;
420         return -1;
421     }
422     return check_log_success(buf,
423         send_log_msg(logger, "clear %d", buf, sizeof(buf)));
424 }
425 
426 /* returns the total size of the log's ring buffer */
android_logger_get_log_size(struct logger * logger)427 long android_logger_get_log_size(struct logger *logger)
428 {
429     char buf[512];
430 
431     ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
432     if (ret < 0) {
433         return ret;
434     }
435 
436     if ((buf[0] < '0') || ('9' < buf[0])) {
437         return -1;
438     }
439 
440     return atol(buf);
441 }
442 
android_logger_set_log_size(struct logger * logger,unsigned long size)443 int android_logger_set_log_size(struct logger *logger, unsigned long size)
444 {
445     char buf[512];
446 
447     snprintf(buf, sizeof(buf), "setLogSize %d %lu",
448         logger ? logger->id : (unsigned) -1, size);
449 
450     return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
451 }
452 
453 /*
454  * returns the readable size of the log's ring buffer (that is, amount of the
455  * log consumed)
456  */
android_logger_get_log_readable_size(struct logger * logger)457 long android_logger_get_log_readable_size(struct logger *logger)
458 {
459     char buf[512];
460 
461     ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
462     if (ret < 0) {
463         return ret;
464     }
465 
466     if ((buf[0] < '0') || ('9' < buf[0])) {
467         return -1;
468     }
469 
470     return atol(buf);
471 }
472 
473 /*
474  * returns the logger version
475  */
android_logger_get_log_version(struct logger * logger __unused)476 int android_logger_get_log_version(struct logger *logger __unused)
477 {
478     return 3;
479 }
480 
481 /*
482  * returns statistics
483  */
android_logger_get_statistics(struct logger_list * logger_list,char * buf,size_t len)484 ssize_t android_logger_get_statistics(struct logger_list *logger_list,
485                                       char *buf, size_t len)
486 {
487     struct logger *logger;
488     char *cp = buf;
489     size_t remaining = len;
490     size_t n;
491 
492     n = snprintf(cp, remaining, "getStatistics");
493     n = min(n, remaining);
494     remaining -= n;
495     cp += n;
496 
497     logger_for_each(logger, logger_list) {
498         n = snprintf(cp, remaining, " %d", logger->id);
499         n = min(n, remaining);
500         remaining -= n;
501         cp += n;
502     }
503     return send_log_msg(NULL, NULL, buf, len);
504 }
505 
android_logger_get_prune_list(struct logger_list * logger_list __unused,char * buf,size_t len)506 ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
507                                       char *buf, size_t len)
508 {
509     return send_log_msg(NULL, "getPruneList", buf, len);
510 }
511 
android_logger_set_prune_list(struct logger_list * logger_list __unused,char * buf,size_t len)512 int android_logger_set_prune_list(struct logger_list *logger_list __unused,
513                                   char *buf, size_t len)
514 {
515     const char cmd[] = "setPruneList ";
516     const size_t cmdlen = sizeof(cmd) - 1;
517 
518     if (strlen(buf) > (len - cmdlen)) {
519         return -ENOMEM; /* KISS */
520     }
521     memmove(buf + cmdlen, buf, len - cmdlen);
522     buf[len - 1] = '\0';
523     memcpy(buf, cmd, cmdlen);
524 
525     return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
526 }
527 
android_logger_list_alloc(int mode,unsigned int tail,pid_t pid)528 struct logger_list *android_logger_list_alloc(int mode,
529                                               unsigned int tail,
530                                               pid_t pid)
531 {
532     struct logger_list *logger_list;
533 
534     logger_list = calloc(1, sizeof(*logger_list));
535     if (!logger_list) {
536         return NULL;
537     }
538 
539     list_init(&logger_list->node);
540     logger_list->mode = mode;
541     logger_list->start.tv_sec = 0;
542     logger_list->start.tv_nsec = 0;
543     logger_list->tail = tail;
544     logger_list->pid = pid;
545     logger_list->sock = -1;
546 
547     return logger_list;
548 }
549 
android_logger_list_alloc_time(int mode,log_time start,pid_t pid)550 struct logger_list *android_logger_list_alloc_time(int mode,
551                                                    log_time start,
552                                                    pid_t pid)
553 {
554     struct logger_list *logger_list;
555 
556     logger_list = calloc(1, sizeof(*logger_list));
557     if (!logger_list) {
558         return NULL;
559     }
560 
561     list_init(&logger_list->node);
562     logger_list->mode = mode;
563     logger_list->start = start;
564     logger_list->tail = 0;
565     logger_list->pid = pid;
566     logger_list->sock = -1;
567 
568     return logger_list;
569 }
570 
571 /* android_logger_list_register unimplemented, no use case */
572 /* android_logger_list_unregister unimplemented, no use case */
573 
574 /* Open the named log and add it to the logger list */
android_logger_open(struct logger_list * logger_list,log_id_t id)575 struct logger *android_logger_open(struct logger_list *logger_list,
576                                    log_id_t id)
577 {
578     struct logger *logger;
579 
580     if (!logger_list || (id >= LOG_ID_MAX)) {
581         goto err;
582     }
583 
584     logger_for_each(logger, logger_list) {
585         if (logger->id == id) {
586             goto ok;
587         }
588     }
589 
590     logger = calloc(1, sizeof(*logger));
591     if (!logger) {
592         goto err;
593     }
594 
595     logger->id = id;
596     list_add_tail(&logger_list->node, &logger->node);
597     logger->top = logger_list;
598     goto ok;
599 
600 err:
601     logger = NULL;
602 ok:
603     return logger;
604 }
605 
606 /* Open the single named log and make it part of a new logger list */
android_logger_list_open(log_id_t id,int mode,unsigned int tail,pid_t pid)607 struct logger_list *android_logger_list_open(log_id_t id,
608                                              int mode,
609                                              unsigned int tail,
610                                              pid_t pid)
611 {
612     struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
613     if (!logger_list) {
614         return NULL;
615     }
616 
617     if (!android_logger_open(logger_list, id)) {
618         android_logger_list_free(logger_list);
619         return NULL;
620     }
621 
622     return logger_list;
623 }
624 
android_logger_list_read_pstore(struct logger_list * logger_list,struct log_msg * log_msg)625 static int android_logger_list_read_pstore(struct logger_list *logger_list,
626                                            struct log_msg *log_msg)
627 {
628     ssize_t ret;
629     off_t current, next;
630     uid_t uid;
631     struct logger *logger;
632     struct __attribute__((__packed__)) {
633         android_pmsg_log_header_t p;
634         android_log_header_t l;
635     } buf;
636     static uint8_t preread_count;
637 
638     memset(log_msg, 0, sizeof(*log_msg));
639 
640     if (logger_list->sock < 0) {
641         int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY);
642 
643         if (fd < 0) {
644             return -errno;
645         }
646         logger_list->sock = fd;
647         preread_count = 0;
648     }
649 
650     ret = 0;
651     while(1) {
652         if (preread_count < sizeof(buf)) {
653             ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
654                                           &buf.p.magic + preread_count,
655                                           sizeof(buf) - preread_count));
656             if (ret < 0) {
657                 return -errno;
658             }
659             preread_count += ret;
660         }
661         if (preread_count != sizeof(buf)) {
662             return preread_count ? -EIO : -EAGAIN;
663         }
664         if ((buf.p.magic != LOGGER_MAGIC)
665          || (buf.p.len <= sizeof(buf))
666          || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
667          || (buf.l.id >= LOG_ID_MAX)
668          || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
669             do {
670                 memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
671             } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
672             continue;
673         }
674         preread_count = 0;
675 
676         logger_for_each(logger, logger_list) {
677             if (buf.l.id != logger->id) {
678                 continue;
679             }
680 
681             if ((logger_list->start.tv_sec || logger_list->start.tv_nsec)
682              && ((logger_list->start.tv_sec > buf.l.realtime.tv_sec)
683               || ((logger_list->start.tv_sec == buf.l.realtime.tv_sec)
684                && (logger_list->start.tv_nsec > buf.l.realtime.tv_nsec)))) {
685                 break;
686             }
687 
688             if (logger_list->pid && (logger_list->pid != buf.p.pid)) {
689                 break;
690             }
691 
692             uid = get_best_effective_uid();
693             if (!uid_has_log_permission(uid) && (uid != buf.p.uid)) {
694                 break;
695             }
696 
697             ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
698                                           log_msg->entry_v3.msg,
699                                           buf.p.len - sizeof(buf)));
700             if (ret < 0) {
701                 return -errno;
702             }
703             if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
704                 return -EIO;
705             }
706 
707             log_msg->entry_v3.len = buf.p.len - sizeof(buf);
708             log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
709             log_msg->entry_v3.pid = buf.p.pid;
710             log_msg->entry_v3.tid = buf.l.tid;
711             log_msg->entry_v3.sec = buf.l.realtime.tv_sec;
712             log_msg->entry_v3.nsec = buf.l.realtime.tv_nsec;
713             log_msg->entry_v3.lid = buf.l.id;
714 
715             return ret;
716         }
717 
718         current = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
719                                            (off_t)0, SEEK_CUR));
720         if (current < 0) {
721             return -errno;
722         }
723         next = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
724                                         (off_t)(buf.p.len - sizeof(buf)),
725                                         SEEK_CUR));
726         if (next < 0) {
727             return -errno;
728         }
729         if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
730             return -EIO;
731         }
732     }
733 }
734 
caught_signal(int signum __unused)735 static void caught_signal(int signum __unused)
736 {
737 }
738 
739 /* Read from the selected logs */
android_logger_list_read(struct logger_list * logger_list,struct log_msg * log_msg)740 int android_logger_list_read(struct logger_list *logger_list,
741                              struct log_msg *log_msg)
742 {
743     int ret, e;
744     struct logger *logger;
745     struct sigaction ignore;
746     struct sigaction old_sigaction;
747     unsigned int old_alarm = 0;
748 
749     if (!logger_list) {
750         return -EINVAL;
751     }
752 
753     if (logger_list->mode & ANDROID_LOG_PSTORE) {
754         return android_logger_list_read_pstore(logger_list, log_msg);
755     }
756 
757     if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
758         memset(&ignore, 0, sizeof(ignore));
759         ignore.sa_handler = caught_signal;
760         sigemptyset(&ignore.sa_mask);
761     }
762 
763     if (logger_list->sock < 0) {
764         char buffer[256], *cp, c;
765 
766         int sock = socket_local_client("logdr",
767                                        ANDROID_SOCKET_NAMESPACE_RESERVED,
768                                        SOCK_SEQPACKET);
769         if (sock < 0) {
770             if ((sock == -1) && errno) {
771                 return -errno;
772             }
773             return sock;
774         }
775 
776         strcpy(buffer,
777                (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
778         cp = buffer + strlen(buffer);
779 
780         strcpy(cp, " lids");
781         cp += 5;
782         c = '=';
783         int remaining = sizeof(buffer) - (cp - buffer);
784         logger_for_each(logger, logger_list) {
785             ret = snprintf(cp, remaining, "%c%u", c, logger->id);
786             ret = min(ret, remaining);
787             remaining -= ret;
788             cp += ret;
789             c = ',';
790         }
791 
792         if (logger_list->tail) {
793             ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
794             ret = min(ret, remaining);
795             remaining -= ret;
796             cp += ret;
797         }
798 
799         if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
800             ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
801                            logger_list->start.tv_sec,
802                            logger_list->start.tv_nsec);
803             ret = min(ret, remaining);
804             remaining -= ret;
805             cp += ret;
806         }
807 
808         if (logger_list->pid) {
809             ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
810             ret = min(ret, remaining);
811             remaining -= ret;
812             cp += ret;
813         }
814 
815         if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
816             /* Deal with an unresponsive logd */
817             sigaction(SIGALRM, &ignore, &old_sigaction);
818             old_alarm = alarm(30);
819         }
820         ret = write(sock, buffer, cp - buffer);
821         e = errno;
822         if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
823             if (e == EINTR) {
824                 e = ETIMEDOUT;
825             }
826             alarm(old_alarm);
827             sigaction(SIGALRM, &old_sigaction, NULL);
828         }
829 
830         if (ret <= 0) {
831             close(sock);
832             if ((ret == -1) && e) {
833                 return -e;
834             }
835             if (ret == 0) {
836                 return -EIO;
837             }
838             return ret;
839         }
840 
841         logger_list->sock = sock;
842     }
843 
844     ret = 0;
845     while(1) {
846         memset(log_msg, 0, sizeof(*log_msg));
847 
848         if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
849             /* particularily useful if tombstone is reporting for logd */
850             sigaction(SIGALRM, &ignore, &old_sigaction);
851             old_alarm = alarm(30);
852         }
853         /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
854         ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
855         e = errno;
856         if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
857             if ((ret == 0) || (e == EINTR)) {
858                 e = EAGAIN;
859                 ret = -1;
860             }
861             alarm(old_alarm);
862             sigaction(SIGALRM, &old_sigaction, NULL);
863         }
864 
865         if (ret <= 0) {
866             if ((ret == -1) && e) {
867                 return -e;
868             }
869             return ret;
870         }
871 
872         logger_for_each(logger, logger_list) {
873             if (log_msg->entry.lid == logger->id) {
874                 return ret;
875             }
876         }
877     }
878     /* NOTREACH */
879     return ret;
880 }
881 
882 /* Close all the logs */
android_logger_list_free(struct logger_list * logger_list)883 void android_logger_list_free(struct logger_list *logger_list)
884 {
885     if (logger_list == NULL) {
886         return;
887     }
888 
889     while (!list_empty(&logger_list->node)) {
890         struct listnode *node = list_head(&logger_list->node);
891         struct logger *logger = node_to_item(node, struct logger, node);
892         android_logger_free(logger);
893     }
894 
895     if (logger_list->sock >= 0) {
896         close (logger_list->sock);
897     }
898 
899     free(logger_list);
900 }
901