init.c revision ebc6ff105a114ff5b5465e64fa0f3889730da19d
1/* 2 * Copyright (C) 2008 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 <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <unistd.h> 21#include <fcntl.h> 22#include <ctype.h> 23#include <signal.h> 24#include <sys/wait.h> 25#include <sys/mount.h> 26#include <sys/stat.h> 27#include <sys/poll.h> 28#include <errno.h> 29#include <stdarg.h> 30#include <mtd/mtd-user.h> 31#include <sys/types.h> 32#include <sys/socket.h> 33#include <sys/un.h> 34 35#include <cutils/sockets.h> 36#include <cutils/iosched_policy.h> 37#include <termios.h> 38 39#include <sys/system_properties.h> 40 41#include "devices.h" 42#include "init.h" 43#include "property_service.h" 44#include "bootchart.h" 45#include "signal_handler.h" 46#include "keychords.h" 47#include "parser.h" 48#include "util.h" 49 50static int property_triggers_enabled = 0; 51 52#if BOOTCHART 53static int bootchart_count; 54#endif 55 56static char console[32]; 57static char serialno[32]; 58static char bootmode[32]; 59static char baseband[32]; 60static char carrier[32]; 61static char bootloader[32]; 62static char hardware[32]; 63static unsigned revision = 0; 64static char qemu[32]; 65 66static struct action *cur_action = NULL; 67static struct command *cur_command = NULL; 68static struct listnode *command_queue = NULL; 69 70void notify_service_state(const char *name, const char *state) 71{ 72 char pname[PROP_NAME_MAX]; 73 int len = strlen(name); 74 if ((len + 10) > PROP_NAME_MAX) 75 return; 76 snprintf(pname, sizeof(pname), "init.svc.%s", name); 77 property_set(pname, state); 78} 79 80static int have_console; 81static char *console_name = "/dev/console"; 82static time_t process_needs_restart; 83 84static const char *ENV[32]; 85 86/* add_environment - add "key=value" to the current environment */ 87int add_environment(const char *key, const char *val) 88{ 89 int n; 90 91 for (n = 0; n < 31; n++) { 92 if (!ENV[n]) { 93 size_t len = strlen(key) + strlen(val) + 2; 94 char *entry = malloc(len); 95 snprintf(entry, len, "%s=%s", key, val); 96 ENV[n] = entry; 97 return 0; 98 } 99 } 100 101 return 1; 102} 103 104static void zap_stdio(void) 105{ 106 int fd; 107 fd = open("/dev/null", O_RDWR); 108 dup2(fd, 0); 109 dup2(fd, 1); 110 dup2(fd, 2); 111 close(fd); 112} 113 114static void open_console() 115{ 116 int fd; 117 if ((fd = open(console_name, O_RDWR)) < 0) { 118 fd = open("/dev/null", O_RDWR); 119 } 120 dup2(fd, 0); 121 dup2(fd, 1); 122 dup2(fd, 2); 123 close(fd); 124} 125 126static void publish_socket(const char *name, int fd) 127{ 128 char key[64] = ANDROID_SOCKET_ENV_PREFIX; 129 char val[64]; 130 131 strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1, 132 name, 133 sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX)); 134 snprintf(val, sizeof(val), "%d", fd); 135 add_environment(key, val); 136 137 /* make sure we don't close-on-exec */ 138 fcntl(fd, F_SETFD, 0); 139} 140 141void service_start(struct service *svc, const char *dynamic_args) 142{ 143 struct stat s; 144 pid_t pid; 145 int needs_console; 146 int n; 147 148 /* starting a service removes it from the disabled 149 * state and immediately takes it out of the restarting 150 * state if it was in there 151 */ 152 svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING)); 153 svc->time_started = 0; 154 155 /* running processes require no additional work -- if 156 * they're in the process of exiting, we've ensured 157 * that they will immediately restart on exit, unless 158 * they are ONESHOT 159 */ 160 if (svc->flags & SVC_RUNNING) { 161 return; 162 } 163 164 needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0; 165 if (needs_console && (!have_console)) { 166 ERROR("service '%s' requires console\n", svc->name); 167 svc->flags |= SVC_DISABLED; 168 return; 169 } 170 171 if (stat(svc->args[0], &s) != 0) { 172 ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); 173 svc->flags |= SVC_DISABLED; 174 return; 175 } 176 177 if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { 178 ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", 179 svc->args[0]); 180 svc->flags |= SVC_DISABLED; 181 return; 182 } 183 184 NOTICE("starting '%s'\n", svc->name); 185 186 pid = fork(); 187 188 if (pid == 0) { 189 struct socketinfo *si; 190 struct svcenvinfo *ei; 191 char tmp[32]; 192 int fd, sz; 193 194 get_property_workspace(&fd, &sz); 195 sprintf(tmp, "%d,%d", dup(fd), sz); 196 add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); 197 198 for (ei = svc->envvars; ei; ei = ei->next) 199 add_environment(ei->name, ei->value); 200 201 for (si = svc->sockets; si; si = si->next) { 202 int s = create_socket(si->name, 203 !strcmp(si->type, "dgram") ? 204 SOCK_DGRAM : SOCK_STREAM, 205 si->perm, si->uid, si->gid); 206 if (s >= 0) { 207 publish_socket(si->name, s); 208 } 209 } 210 211 if (svc->ioprio_class != IoSchedClass_NONE) { 212 if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { 213 ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", 214 getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno)); 215 } 216 } 217 218 if (needs_console) { 219 setsid(); 220 open_console(); 221 } else { 222 zap_stdio(); 223 } 224 225#if 0 226 for (n = 0; svc->args[n]; n++) { 227 INFO("args[%d] = '%s'\n", n, svc->args[n]); 228 } 229 for (n = 0; ENV[n]; n++) { 230 INFO("env[%d] = '%s'\n", n, ENV[n]); 231 } 232#endif 233 234 setpgid(0, getpid()); 235 236 /* as requested, set our gid, supplemental gids, and uid */ 237 if (svc->gid) { 238 setgid(svc->gid); 239 } 240 if (svc->nr_supp_gids) { 241 setgroups(svc->nr_supp_gids, svc->supp_gids); 242 } 243 if (svc->uid) { 244 setuid(svc->uid); 245 } 246 247 if (!dynamic_args) { 248 if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { 249 ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); 250 } 251 } else { 252 char *arg_ptrs[SVC_MAXARGS+1]; 253 int arg_idx = svc->nargs; 254 char *tmp = strdup(dynamic_args); 255 char *next = tmp; 256 char *bword; 257 258 /* Copy the static arguments */ 259 memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *))); 260 261 while((bword = strsep(&next, " "))) { 262 arg_ptrs[arg_idx++] = bword; 263 if (arg_idx == SVC_MAXARGS) 264 break; 265 } 266 arg_ptrs[arg_idx] = '\0'; 267 execve(svc->args[0], (char**) arg_ptrs, (char**) ENV); 268 } 269 _exit(127); 270 } 271 272 if (pid < 0) { 273 ERROR("failed to start '%s'\n", svc->name); 274 svc->pid = 0; 275 return; 276 } 277 278 svc->time_started = gettime(); 279 svc->pid = pid; 280 svc->flags |= SVC_RUNNING; 281 282 notify_service_state(svc->name, "running"); 283} 284 285void service_stop(struct service *svc) 286{ 287 /* we are no longer running, nor should we 288 * attempt to restart 289 */ 290 svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING)); 291 292 /* if the service has not yet started, prevent 293 * it from auto-starting with its class 294 */ 295 svc->flags |= SVC_DISABLED; 296 297 if (svc->pid) { 298 NOTICE("service '%s' is being killed\n", svc->name); 299 kill(-svc->pid, SIGTERM); 300 notify_service_state(svc->name, "stopping"); 301 } else { 302 notify_service_state(svc->name, "stopped"); 303 } 304} 305 306void property_changed(const char *name, const char *value) 307{ 308 if (property_triggers_enabled) 309 queue_property_triggers(name, value); 310} 311 312static void restart_service_if_needed(struct service *svc) 313{ 314 time_t next_start_time = svc->time_started + 5; 315 316 if (next_start_time <= gettime()) { 317 svc->flags &= (~SVC_RESTARTING); 318 service_start(svc, NULL); 319 return; 320 } 321 322 if ((next_start_time < process_needs_restart) || 323 (process_needs_restart == 0)) { 324 process_needs_restart = next_start_time; 325 } 326} 327 328static void restart_processes() 329{ 330 process_needs_restart = 0; 331 service_for_each_flags(SVC_RESTARTING, 332 restart_service_if_needed); 333} 334 335static void msg_start(const char *name) 336{ 337 struct service *svc; 338 char *tmp = NULL; 339 char *args = NULL; 340 341 if (!strchr(name, ':')) 342 svc = service_find_by_name(name); 343 else { 344 tmp = strdup(name); 345 args = strchr(tmp, ':'); 346 *args = '\0'; 347 args++; 348 349 svc = service_find_by_name(tmp); 350 } 351 352 if (svc) { 353 service_start(svc, args); 354 } else { 355 ERROR("no such service '%s'\n", name); 356 } 357 if (tmp) 358 free(tmp); 359} 360 361static void msg_stop(const char *name) 362{ 363 struct service *svc = service_find_by_name(name); 364 365 if (svc) { 366 service_stop(svc); 367 } else { 368 ERROR("no such service '%s'\n", name); 369 } 370} 371 372void handle_control_message(const char *msg, const char *arg) 373{ 374 if (!strcmp(msg,"start")) { 375 msg_start(arg); 376 } else if (!strcmp(msg,"stop")) { 377 msg_stop(arg); 378 } else { 379 ERROR("unknown control msg '%s'\n", msg); 380 } 381} 382 383static void import_kernel_nv(char *name, int in_qemu) 384{ 385 char *value = strchr(name, '='); 386 387 if (value == 0) return; 388 *value++ = 0; 389 if (*name == 0) return; 390 391 if (!in_qemu) 392 { 393 /* on a real device, white-list the kernel options */ 394 if (!strcmp(name,"qemu")) { 395 strlcpy(qemu, value, sizeof(qemu)); 396 } else if (!strcmp(name,"androidboot.console")) { 397 strlcpy(console, value, sizeof(console)); 398 } else if (!strcmp(name,"androidboot.mode")) { 399 strlcpy(bootmode, value, sizeof(bootmode)); 400 } else if (!strcmp(name,"androidboot.serialno")) { 401 strlcpy(serialno, value, sizeof(serialno)); 402 } else if (!strcmp(name,"androidboot.baseband")) { 403 strlcpy(baseband, value, sizeof(baseband)); 404 } else if (!strcmp(name,"androidboot.carrier")) { 405 strlcpy(carrier, value, sizeof(carrier)); 406 } else if (!strcmp(name,"androidboot.bootloader")) { 407 strlcpy(bootloader, value, sizeof(bootloader)); 408 } else if (!strcmp(name,"androidboot.hardware")) { 409 strlcpy(hardware, value, sizeof(hardware)); 410 } else { 411 qemu_cmdline(name, value); 412 } 413 } else { 414 /* in the emulator, export any kernel option with the 415 * ro.kernel. prefix */ 416 char buff[32]; 417 int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name ); 418 if (len < (int)sizeof(buff)) { 419 property_set( buff, value ); 420 } 421 } 422} 423 424static void import_kernel_cmdline(int in_qemu) 425{ 426 char cmdline[1024]; 427 char *ptr; 428 int fd; 429 430 fd = open("/proc/cmdline", O_RDONLY); 431 if (fd >= 0) { 432 int n = read(fd, cmdline, 1023); 433 if (n < 0) n = 0; 434 435 /* get rid of trailing newline, it happens */ 436 if (n > 0 && cmdline[n-1] == '\n') n--; 437 438 cmdline[n] = 0; 439 close(fd); 440 } else { 441 cmdline[0] = 0; 442 } 443 444 ptr = cmdline; 445 while (ptr && *ptr) { 446 char *x = strchr(ptr, ' '); 447 if (x != 0) *x++ = 0; 448 import_kernel_nv(ptr, in_qemu); 449 ptr = x; 450 } 451 452 /* don't expose the raw commandline to nonpriv processes */ 453 chmod("/proc/cmdline", 0440); 454} 455 456static void get_hardware_name(void) 457{ 458 char data[1024]; 459 int fd, n; 460 char *x, *hw, *rev; 461 462 /* Hardware string was provided on kernel command line */ 463 if (hardware[0]) 464 return; 465 466 fd = open("/proc/cpuinfo", O_RDONLY); 467 if (fd < 0) return; 468 469 n = read(fd, data, 1023); 470 close(fd); 471 if (n < 0) return; 472 473 data[n] = 0; 474 hw = strstr(data, "\nHardware"); 475 rev = strstr(data, "\nRevision"); 476 477 if (hw) { 478 x = strstr(hw, ": "); 479 if (x) { 480 x += 2; 481 n = 0; 482 while (*x && !isspace(*x)) { 483 hardware[n++] = tolower(*x); 484 x++; 485 if (n == 31) break; 486 } 487 hardware[n] = 0; 488 } 489 } 490 491 if (rev) { 492 x = strstr(rev, ": "); 493 if (x) { 494 revision = strtoul(x + 2, 0, 16); 495 } 496 } 497} 498 499static struct command *get_first_command(struct action *act) 500{ 501 struct listnode *node; 502 node = list_head(&act->commands); 503 if (!node) 504 return NULL; 505 506 return node_to_item(node, struct command, clist); 507} 508 509static struct command *get_next_command(struct action *act, struct command *cmd) 510{ 511 struct listnode *node; 512 node = cmd->clist.next; 513 if (!node) 514 return NULL; 515 if (node == &act->commands) 516 return NULL; 517 518 return node_to_item(node, struct command, clist); 519} 520 521static int is_last_command(struct action *act, struct command *cmd) 522{ 523 return (list_tail(&act->commands) == &cmd->clist); 524} 525 526void execute_one_command(void) 527{ 528 int ret; 529 530 if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) { 531 cur_action = action_remove_queue_head(); 532 if (!cur_action) 533 return; 534 INFO("processing action %p (%s)\n", cur_action, cur_action->name); 535 cur_command = get_first_command(cur_action); 536 } else { 537 cur_command = get_next_command(cur_action, cur_command); 538 } 539 540 if (!cur_command) 541 return; 542 543 ret = cur_command->func(cur_command->nargs, cur_command->args); 544 INFO("command '%s' r=%d\n", cur_command->args[0], ret); 545} 546 547void open_devnull_stdio(void) 548{ 549 int fd; 550 static const char *name = "/dev/__null__"; 551 if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { 552 fd = open(name, O_RDWR); 553 unlink(name); 554 if (fd >= 0) { 555 dup2(fd, 0); 556 dup2(fd, 1); 557 dup2(fd, 2); 558 if (fd > 2) { 559 close(fd); 560 } 561 return; 562 } 563 } 564 565 exit(1); 566} 567 568static int device_init_action(int nargs, char **args) 569{ 570 INFO("device init\n"); 571 device_init(); 572 return 0; 573} 574 575static int property_init_action(int nargs, char **args) 576{ 577 INFO("property init\n"); 578 property_init(); 579 return 0; 580} 581 582static int keychord_init_action(int nargs, char **args) 583{ 584 keychord_init(); 585 return 0; 586} 587 588static int console_init_action(int nargs, char **args) 589{ 590 int fd; 591 char tmp[PROP_VALUE_MAX]; 592 593 if (console[0]) { 594 snprintf(tmp, sizeof(tmp), "/dev/%s", console); 595 console_name = strdup(tmp); 596 } 597 598 fd = open(console_name, O_RDWR); 599 if (fd >= 0) 600 have_console = 1; 601 close(fd); 602 603 if( load_565rle_image(INIT_IMAGE_FILE) ) { 604 fd = open("/dev/tty0", O_WRONLY); 605 if (fd >= 0) { 606 const char *msg; 607 msg = "\n" 608 "\n" 609 "\n" 610 "\n" 611 "\n" 612 "\n" 613 "\n" // console is 40 cols x 30 lines 614 "\n" 615 "\n" 616 "\n" 617 "\n" 618 "\n" 619 "\n" 620 "\n" 621 " A N D R O I D "; 622 write(fd, msg, strlen(msg)); 623 close(fd); 624 } 625 } 626 return 0; 627} 628 629static int set_init_properties_action(int nargs, char **args) 630{ 631 char tmp[PROP_VALUE_MAX]; 632 633 if (qemu[0]) 634 import_kernel_cmdline(1); 635 636 if (!strcmp(bootmode,"factory")) 637 property_set("ro.factorytest", "1"); 638 else if (!strcmp(bootmode,"factory2")) 639 property_set("ro.factorytest", "2"); 640 else 641 property_set("ro.factorytest", "0"); 642 643 property_set("ro.serialno", serialno[0] ? serialno : ""); 644 property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown"); 645 property_set("ro.baseband", baseband[0] ? baseband : "unknown"); 646 property_set("ro.carrier", carrier[0] ? carrier : "unknown"); 647 property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown"); 648 649 property_set("ro.hardware", hardware); 650 snprintf(tmp, PROP_VALUE_MAX, "%d", revision); 651 property_set("ro.revision", tmp); 652 return 0; 653} 654 655static int property_service_init_action(int nargs, char **args) 656{ 657 /* read any property files on system or data and 658 * fire up the property service. This must happen 659 * after the ro.foo properties are set above so 660 * that /data/local.prop cannot interfere with them. 661 */ 662 start_property_service(); 663 return 0; 664} 665 666static int signal_init_action(int nargs, char **args) 667{ 668 signal_init(); 669 return 0; 670} 671 672static int check_startup_action(int nargs, char **args) 673{ 674 /* make sure we actually have all the pieces we need */ 675 if ((get_device_fd() < 0) || 676 (get_property_set_fd() < 0) || 677 (get_signal_fd() < 0)) { 678 ERROR("init startup failure\n"); 679 exit(1); 680 } 681 return 0; 682} 683 684static int queue_property_triggers_action(int nargs, char **args) 685{ 686 queue_all_property_triggers(); 687 /* enable property triggers */ 688 property_triggers_enabled = 1; 689 return 0; 690} 691 692#if BOOTCHART 693static int bootchart_init_action(int nargs, char **args) 694{ 695 bootchart_count = bootchart_init(); 696 if (bootchart_count < 0) { 697 ERROR("bootcharting init failure\n"); 698 } else if (bootchart_count > 0) { 699 NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS); 700 } else { 701 NOTICE("bootcharting ignored\n"); 702 } 703} 704#endif 705 706int main(int argc, char **argv) 707{ 708 int fd_count = 0; 709 struct pollfd ufds[4]; 710 char *tmpdev; 711 char* debuggable; 712 char tmp[32]; 713 int device_fd_init = 0; 714 int property_set_fd_init = 0; 715 int signal_fd_init = 0; 716 int keychord_fd_init = 0; 717 718 /* clear the umask */ 719 umask(0); 720 721 /* Get the basic filesystem setup we need put 722 * together in the initramdisk on / and then we'll 723 * let the rc file figure out the rest. 724 */ 725 mkdir("/dev", 0755); 726 mkdir("/proc", 0755); 727 mkdir("/sys", 0755); 728 729 mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755"); 730 mkdir("/dev/pts", 0755); 731 mkdir("/dev/socket", 0755); 732 mount("devpts", "/dev/pts", "devpts", 0, NULL); 733 mount("proc", "/proc", "proc", 0, NULL); 734 mount("sysfs", "/sys", "sysfs", 0, NULL); 735 736 /* We must have some place other than / to create the 737 * device nodes for kmsg and null, otherwise we won't 738 * be able to remount / read-only later on. 739 * Now that tmpfs is mounted on /dev, we can actually 740 * talk to the outside world. 741 */ 742 open_devnull_stdio(); 743 log_init(); 744 745 INFO("reading config file\n"); 746 parse_config_file("/init.rc"); 747 748 /* pull the kernel commandline and ramdisk properties file in */ 749 qemu_init(); 750 import_kernel_cmdline(0); 751 752 get_hardware_name(); 753 snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); 754 parse_config_file(tmp); 755 756 action_for_each_trigger("early-init", action_add_queue_tail); 757 758 queue_builtin_action(device_init_action, "device_init"); 759 queue_builtin_action(property_init_action, "property_init"); 760 queue_builtin_action(keychord_init_action, "keychord_init"); 761 queue_builtin_action(console_init_action, "console_init"); 762 queue_builtin_action(set_init_properties_action, "set_init_properties"); 763 764 /* execute all the boot actions to get us started */ 765 action_for_each_trigger("init", action_add_queue_tail); 766 action_for_each_trigger("early-fs", action_add_queue_tail); 767 action_for_each_trigger("fs", action_add_queue_tail); 768 action_for_each_trigger("post-fs", action_add_queue_tail); 769 770 queue_builtin_action(property_service_init_action, "property_service_init"); 771 queue_builtin_action(signal_init_action, "signal_init"); 772 queue_builtin_action(check_startup_action, "check_startup"); 773 774 /* execute all the boot actions to get us started */ 775 action_for_each_trigger("early-boot", action_add_queue_tail); 776 action_for_each_trigger("boot", action_add_queue_tail); 777 778 /* run all property triggers based on current state of the properties */ 779 queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers"); 780 781 782#if BOOTCHART 783 queue_builtin_action(bootchart_init_action, "bootchart_init"); 784#endif 785 786 for(;;) { 787 int nr, i, timeout = -1; 788 789 execute_one_command(); 790 restart_processes(); 791 792 if (!device_fd_init && get_device_fd() > 0) { 793 ufds[fd_count].fd = get_device_fd(); 794 ufds[fd_count].events = POLLIN; 795 ufds[fd_count].revents = 0; 796 fd_count++; 797 device_fd_init = 1; 798 } 799 if (!property_set_fd_init && get_property_set_fd() > 0) { 800 ufds[fd_count].fd = get_property_set_fd(); 801 ufds[fd_count].events = POLLIN; 802 ufds[fd_count].revents = 0; 803 fd_count++; 804 property_set_fd_init = 1; 805 } 806 if (!signal_fd_init && get_signal_fd() > 0) { 807 ufds[fd_count].fd = get_signal_fd(); 808 ufds[fd_count].events = POLLIN; 809 ufds[fd_count].revents = 0; 810 fd_count++; 811 signal_fd_init = 1; 812 } 813 if (!keychord_fd_init && get_keychord_fd() > 0) { 814 ufds[fd_count].fd = get_keychord_fd(); 815 ufds[fd_count].events = POLLIN; 816 ufds[fd_count].revents = 0; 817 fd_count++; 818 keychord_fd_init = 1; 819 } 820 821 if (process_needs_restart) { 822 timeout = (process_needs_restart - gettime()) * 1000; 823 if (timeout < 0) 824 timeout = 0; 825 } 826 827 if (!action_queue_empty() || cur_command) 828 timeout = 0; 829 830#if BOOTCHART 831 if (bootchart_count > 0) { 832 if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) 833 timeout = BOOTCHART_POLLING_MS; 834 if (bootchart_step() < 0 || --bootchart_count == 0) { 835 bootchart_finish(); 836 bootchart_count = 0; 837 } 838 } 839#endif 840 841 nr = poll(ufds, fd_count, timeout); 842 if (nr <= 0) 843 continue; 844 845 for (i = 0; i < fd_count; i++) { 846 if (ufds[i].revents == POLLIN) { 847 if (ufds[i].fd == get_device_fd()) 848 handle_device_fd(); 849 else if (ufds[i].fd == get_property_set_fd()) 850 handle_property_set_fd(); 851 else if (ufds[i].fd == get_keychord_fd()) 852 handle_keychord(); 853 else if (ufds[i].fd == get_signal_fd()) 854 handle_signal(); 855 } 856 } 857 } 858 859 return 0; 860} 861