void event_do_wakeup_calls (enum einit_event_code c) { struct wakeup_data *d = event_wd; while (d) { if (d->code == c) { struct lmodule *m = NULL; emutex_lock (&event_wakeup_mutex); if (d->module && (d->module->status & status_suspended)) m = d->module; emutex_unlock (&event_wakeup_mutex); if (m) { mod(einit_module_resume, m, NULL); time_t nt = time(NULL) + 60; emutex_lock (&event_wakeup_mutex); if (!event_snooze_time || ((event_snooze_time+30) < nt)) { event_snooze_time = nt; emutex_unlock (&event_wakeup_mutex); { struct einit_event ev = evstaticinit (einit_timer_set); ev.integer = event_snooze_time; event_emit (&ev, einit_event_flag_broadcast); evstaticdestroy (ev); } } else emutex_unlock (&event_wakeup_mutex); } } d = d->next; } }
void stimer_fired( const uint8_t tnum ) { static unsigned int i; if(tnum == KBRD_ANTIRING_TIMER) { kbrd_clear_ring_buf(); P2IE &= ~0x0f; // Disable interrupts // port_write(4, 0x01, PIN_LO); kbrd_service(); // port_write(4, 0x01, PIN_HI); P2IE |= 0x0f; // Enable interrupts port_write(KBRD_SOUND_PORT, KBRD_SOUND_PIN, PIN_LO); if(kbrd_pressed) event_emit(KBRD_EVT_PRIORITY, KBRD_EVT, 0); } else if(tnum == KBRD_SOUND_TIMER) { port_write(KBRD_SOUND_PORT, KBRD_SOUND_PIN, PIN_LO); } else { stimer_set(1, 1000); update_time(); //toggleLED(LED_FIRE | LED_POWER); } }
void stimer_fired( const uint8_t timer_num) { result_t err; int res; DBG("call fired"); if(timer_num) { DBG("Timer not supported"); return; } if(stage == STAGE_IDLE) { err = event_emit( NORMAL_PRIORITY, TIMER_EVENT, 0); if( ENOERR != err ) DBG("FAIL: emit timer event"); return; } res = init_PyroMeasurement(1); err = stimer_set(TIMER_0, SHOT_PERIOD); if( ENOERR != err ) DBG("FAIL: start usual timer"); DBG("return fired"); return; }
void *event_emit (struct einit_event *event, enum einit_event_emit_flags flags) { pthread_t **threads = NULL; if (!event || !event->type) return NULL; event_do_wakeup_calls (event->type); if (flags & einit_event_flag_spawn_thread) { struct einit_event *ev = evdup(event); if (!ev) return NULL; ethread_spawn_detached_run ((void *(*)(void *))event_subthread, (void *)ev); return NULL; } uint32_t subsystem = event->type & EVENT_SUBSYSTEM_MASK; /* initialise sequence id and timestamp of the event */ event->seqid = cseqid++; event->timestamp = time(NULL); struct event_function *cur = event_functions; while (cur) { if (((cur->type == subsystem) || (cur->type == einit_event_subsystem_any)) && cur->handler) { if (flags & einit_event_flag_spawn_thread_multi_wait) { pthread_t *threadid = emalloc (sizeof (pthread_t)); struct evt_wrapper_data *d = emalloc (sizeof (struct evt_wrapper_data)); d->event = evdup(event); d->handler = cur->handler; ethread_create (threadid, NULL, (void *(*)(void *))event_thread_wrapper, d); threads = (pthread_t **)setadd ((void **)threads, threadid, SET_NOALLOC); } else cur->handler (event); } cur = cur->next; } if (event->chain_type) { event->type = event->chain_type; event->chain_type = 0; event_emit (event, flags); } if ((flags & einit_event_flag_spawn_thread_multi_wait) && threads) { int i = 0; for (; threads[i]; i++) { pthread_join (*(threads[i]), NULL); free (threads[i]); } free (threads); } return NULL; }
void irq_handler( irq_t irq ) { if( GERCON_IRQ == irq ) { /* Обрабатываем прерывание от геркона */ port_attr_t port_attr; /* Перенастраиваем вход от геркона. Если до этого прерывание от геркона генерилось * на спаде, то перенастраиваем на фронт. Если же на фронте, то перенастраиваем на спад. */ port_get_attr( GERCON_PORT, GERCON_PIN, &port_attr ); port_attr.ies ^= GERCON_PIN; port_set_attr( GERCON_PORT, GERCON_PIN, &port_attr ); /* Продолжаем обработку прерывания в обработчике события */ if( PIN_IS_SET( port_attr.ies, GERCON_PIN ) ) event_emit( PRIORITY_HIGH, EV_TYPE_OPEN, 0 ); else event_emit( PRIORITY_HIGH, EV_TYPE_CLOSE, 0 ); } return; }
void event_timer_cancel (time_t t) { struct einit_event ev = evstaticinit (einit_timer_cancel); ev.integer = t; event_emit (&ev, einit_event_flag_broadcast); evstaticdestroy (ev); }
struct lmodule *mod_update (struct lmodule *module) { if (!module->module) return module; struct einit_event ee = evstaticinit (einit_core_update_module); ee.para = (void *)module; event_emit (&ee, einit_event_flag_broadcast); evstaticdestroy(ee); return module; }
void irq_handler( irq_t interrupt ) { uint16_t tmp; // General purpose temporal variable switch(interrupt) { case INT_NUM_ADC12: tmp = adc_int_handler(ADC12IV); event_emit(NORMAL_PRIORITY, ADC12_EVENT, tmp); break; } }
time_t event_timer_register (struct tm *t) { struct einit_event ev = evstaticinit (einit_timer_set); time_t tr = timegm (t); ev.integer = tr; event_emit (&ev, einit_event_flag_broadcast); evstaticdestroy (ev); return tr; }
time_t event_timer_register_timeout (time_t t) { struct einit_event ev = evstaticinit (einit_timer_set); time_t tr = time (NULL) + t; ev.integer = tr; event_emit (&ev, einit_event_flag_broadcast); evstaticdestroy (ev); return tr; }
//size_t msg_recv( msg_t msg ) // Return type has changed in new version void msg_recv( msg_t msg ) { size_t msg_size; OLED_puts(0, 41, 0xff, font6x9, "Message"); msg_size = parse_message(msg); total_msg_count++; event_emit(LOW_PRIORITY, DISPLAY_EVT, 2); msg_destroy(msg); // return msg_size; // return (sizeof(struct msginfo) + minfo.body_size); }
void linux_static_dev_boot_event_handler (struct einit_event *ev) { switch (ev->type) { case einit_boot_early: if (linux_static_dev_run() == status_ok) { struct einit_event eml = evstaticinit(einit_boot_devices_available); event_emit (&eml, einit_event_flag_broadcast | einit_event_flag_spawn_thread_multi_wait); evstaticdestroy(eml); } break; default: break; } }
/* Инициализация портов */ void sys_init() { port_attr_t port_attr; /* Настройка выхода на зелёный светодиод */ PIN_SET( port_attr.dir, GREEN_PIN, PIN_HI ); /* Направление на вывод */ PIN_CLEAR( port_attr.sel, GREEN_PIN ); /* Функция ввода/вывода */ port_set_attr( GREEN_PORT, GREEN_PIN, &port_attr ); port_write( GREEN_PORT, GREEN_PIN, PIN_LO ); /* По умолчанию гасим светодиод */ /* Настройка выхода на красный светодиод */ PIN_SET( port_attr.dir, RED_PIN, PIN_HI ); /* Направление на вывод */ PIN_CLEAR( port_attr.sel, RED_PIN ); /* Функция ввода/вывода */ port_set_attr( RED_PORT, RED_PIN, &port_attr ); port_write( RED_PORT, RED_PIN, PIN_LO ); /* По умолчанию гасим светодиод */ /* Настройка входа от геркона */ { port_t gercon_port = 0x00; event_type_t event_type = 0; result_t res = ENOSYS; port_reset_iflag( GERCON_PORT, GERCON_PIN ); PIN_CLEAR( port_attr.dir, GERCON_PIN ); /* Направление на ввод */ PIN_CLEAR( port_attr.sel, GERCON_PIN ); /* Функция ввода/вывода */ PIN_SET( port_attr.ie, GERCON_PIN, PIN_HI ); /* Разрешаем прерывания от кнопки */ PIN_SET( port_attr.ies, GERCON_PIN, PIN_HI ); /* Ловим изменение с высокого на низкий уровень */ port_set_attr( GERCON_PORT, GERCON_PIN, &port_attr ); port_read( GERCON_PORT, GERCON_PIN, &gercon_port ); /* Определение текущего состояния геркона */ if( PIN_IS_SET( gercon_port, GERCON_PIN) ) { event_type = EV_TYPE_OPEN; } else { PIN_SET( port_attr.ies, GERCON_PIN, PIN_LO ); /* Ловим изменение с низкого на высокий уровень */ port_set_attr( GERCON_PORT, GERCON_PIN, &port_attr ); event_type = EV_TYPE_CLOSE; } res = event_emit( PRIORITY_LOW, event_type, 0 ); if( IS_ERROR(res) ) { /* Не смогли начать работу, зажигаем красный светодиод */ port_write( RED_PORT, RED_PIN, PIN_HI ); } } return; }
void event_handler( event_type_t event_type, unidata_t unidata ) { if( EV_MBREQ_DONE == event_type ) { result_t res; res = mb_master_request( slave_addr[cur_slave], 100, 0,0, &ans_fcode,ans_dptr,&ans_dsize ); if( IS_OK(res) ) { cur_slave++; if( cur_slave >= SLAVE_TOTAL ) cur_slave = 0; return; } event_emit( PRIORITY_HIGH, EV_MBREQ_DONE, (unidata_t)ENOERR ); } }
/* Инициализация портов */ void sys_init() { port_attr_t port_attr; #if defined(BLINK_ON) PIN_SET( port_attr.dir, LED1|LED2|LED3, PIN_HI ); /* Направление на вывод */ PIN_CLEAR( port_attr.sel, LED1|LED2|LED3 ); /* Функция ввода/вывода */ PIN_CLEAR( port_attr.ie, LED1|LED2|LED3 ); /* Запрет прерываний */ port_set_attr( LED_PORT, LED1|LED2|LED3, &port_attr ); port_write( LED_PORT, LED1|LED2|LED3, PIN_LO ); #endif #if defined(PLATFORM_FIRE_BUTTON) PIN_SET( port_attr.dir, CONTROL_PINS, PIN_HI ); /* Направление на вывод */ PIN_CLEAR( port_attr.sel, CONTROL_PINS ); /* Функция ввода/вывода */ PIN_CLEAR( port_attr.ie, CONTROL_PINS ); /* Запрет прерываний */ port_set_attr( CONTROL_PORT, CONTROL_PINS, &port_attr ); port_write( CONTROL_PORT, CONTROL_PINS, PINT1 ); #endif /* Настройка входа от геркона */ { port_t iport = 0x00; event_type_t event_type = 0; result_t res = ENOSYS; port_reset_iflag( IPORT, IPINS ); PIN_CLEAR( port_attr.dir, IPINS ); /* Направление на ввод */ PIN_CLEAR( port_attr.sel, IPINS ); /* Функция ввода/вывода */ PIN_SET( port_attr.ie, IPINS, PIN_HI ); /* Разрешаем прерывания от кнопки */ PIN_SET( port_attr.ies, IPINS, PIN_LO ); /* Ловим изменение с низкого на высокий уровень */ port_set_attr( IPORT, IPINS, &port_attr ); /* Определение текущего состояния входов */ port_read( IPORT, IPINS, &iport ); /* У тех входов, которые уже в 1 настраиваем прерывания на спад */ PIN_SET( port_attr.ies, iport, PIN_HI ); /* Ловим изменение с высокого на низкий уровень */ port_set_attr( IPORT, iport, &port_attr ); res = event_emit( PRIORITY, GIOP_INTERRUPT, (unidata_t)iport ); if( IS_ERROR(res) ) { port_write( LED_PORT, LED1, PIN_HI ); } } return; }
void irq_handler( irq_t irq ) { /* Обрабатываем изменение состояний входов */ if( IPORT_IRQ == irq ) { port_attr_t port_attr; port_t ifg, in; /* Перенастраиваем прерывания от входов */ port_get_attr( IPORT, IPINS, &port_attr ); port_get_iflag( IPORT, IPINS, &ifg ); /* Маска флагов прерываний */ if( ifg ) { port_reset_iflag( IPORT, ifg ); /* Сбрасываем флаги прерываний */ port_attr.ies ^= ifg; /* Меняем условие генерации прерывания, у входов, у которых изменилось состояние */ port_set_attr( IPORT, IPINS, &port_attr ); port_read( IPORT, IPINS, &in ); /* Вычитываем состояние входов, чтобы записать их в атрибут */ /* Продолжаем обработку прерывания в обработчике события */ event_emit( PRIORITY, GIOP_INTERRUPT, in ); } } return; }
void sys_init() { result_t err; DBG("call init_module"); stage = STAGE_IDLE; // Wait for the system to start up err = event_emit( NORMAL_PRIORITY, TIMER_EVENT, 0); if( ENOERR != err ) DBG("FAIL: module start"); cur_MotionState = MOTION_STATE_QUIET; motion_detect_count = 0; middle_point = (4096 / 2) << 4; DBG("return init_module"); return; }
void linux_static_dev_hotplug_handle (char **v) { if (v && v[0]) { int i = 0; char **args = NULL; struct einit_event ev = evstaticinit(einit_hotplug_generic); if (strstr (v[0], "add@") == v[0]) { ev.type = einit_hotplug_add; } else if (strstr (v[0], "remove@") == v[0]) { ev.type = einit_hotplug_remove; } else if (strstr (v[0], "change@") == v[0]) { ev.type = einit_hotplug_change; } else if (strstr (v[0], "online@") == v[0]) { ev.type = einit_hotplug_online; } else if (strstr (v[0], "offline@") == v[0]) { ev.type = einit_hotplug_offline; } else if (strstr (v[0], "move@") == v[0]) { ev.type = einit_hotplug_move; } for (i = 1; v[i]; i++) { char *n = strchr (v[i], '='); if (n) { *n = 0; n++; args = (char **)setadd ((void **)args, v[i], SET_TYPE_STRING); args = (char **)setadd ((void **)args, n, SET_TYPE_STRING); } } ev.stringset = args; /* emit the event, waiting for it to be processed */ event_emit (&ev, einit_event_flag_broadcast); evstaticdestroy (ev); if (args) free (args); } }
void sys_init() { // char str[32]; // unsigned long ul; // struct LogEntry entry; struct NodeCfg ncfg; unsigned long long _ull; FILEDESCR_t fd; int err; static struct child c = {BAD_ADDRESS, 0}; // msg_count = 0; // last_msg_pos = 0; total_msg_count = 0; for(err = MAX_CHILDREN; err--; ) memcopy(&children[err], &c, sizeof(struct child)); //memset(zone_state, 0, sizeof(zone_state)); for(err = STRG_MAX_ZONE_NUM; err--;) zone_state[err] = ZONE_STATE_ON; init_LEDs(); setNormalState(); //switchOnLED(LED_RED); // scroll_pos = 0; // port_attr_t p4; // event_emit(0, INIT_EVT, 0); /* PIN_SET(p4.dir, 0x19, PIN_HI); PIN_CLEAR(p4.sel, 0x19); port_set_attr(4, 0x19, &p4); port_write(4, 0x19, PIN_HI); p4_val = 0x01; */ // SPI_init(); // err = initStorage(); // OLED_init(); // init_kbrd(); // menu_init(0); // OLED_clr(68, 3*9, 2 * 6, 9); // err = mmcReadBlock(23, 3, &ul); //err = logEntriesNum(); //err = logAddEntry(&entry, "Test message3"); //err = strgFindNode(0x66ULL, &ncfg); //itoa(err, fd.filename, 10); //OLED_puts(0, 0, 0xff, font6x9, fd.filename); //out_dump (0, 50, sizeof(struct NodeCfg), &ncfg); /* strcpy(str, "Pos: "); ul = logstat.last_entry_pos; //ul = (unsigned long)syscfg.log_state_pos << 9; ultoa(ul, str + strlen(str), 10); str[strlen(str) + 1] = 0; str[strlen(str)] = ' '; ul = syscfg.log_state_pos; ultoa(ul, str + strlen(str), 10); OLED_puts(0, 0, 0xff, font6x9, str); */ // init_FAT(); // Read_PBR(); // ultoa(fat.root_dir, fd.filename, 16); // OLED_puts(17 * 6, 50, 0xff, font6x9, fd.filename); /* strcpy(fd.filename, "LOG "); if(FindFile(fat.root_dir, &fd) != FAT_SUCCESS) OLED_puts(0, 50, 0xff, font6x9, "FindFile failed"); else { itoa(fd.clust, fd.filename, 16); OLED_puts(0, 50, 0xff, font6x9, fd.filename); ultoa(fd.size, fd.filename, 16); OLED_puts(10 * 6, 50, 0xff, font6x9, fd.filename); } */ event_emit(LOW_PRIORITY, INIT_EVT, 0); // stimer_set(1, 1000); // return; }
int mod (enum einit_module_task task, struct lmodule *module, char *custom_command) { struct einit_event *fb; unsigned int ret; if (!module) return 0; /* wait if the module is already being processed in a different thread */ if (!(task & einit_module_ignore_mutex)) { if ((task & einit_module_suspend) || (task & einit_module_resume)) { if (pthread_mutex_trylock (&module->mutex)) return status_failed; } else emutex_lock (&module->mutex); } if (task & einit_module_suspend) { int retval = mod_suspend (module); if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); return retval; } if (task & einit_module_resume) { int retval = mod_resume (module); if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); return retval; } if (module->status & status_suspended) { if (!(mod_resume (module) == status_ok)) { if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); return status_failed; } } if (task & einit_module_custom) { if (!custom_command) { if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); return status_failed; } goto skipdependencies; } if (task & einit_module_ignore_dependencies) { notice (2, "module: skipping dependency-checks"); task ^= einit_module_ignore_dependencies; goto skipdependencies; } if (module->status & MOD_LOCKED) { // this means the module is locked. maybe we're shutting down just now. if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); if (task & einit_module_enable) return status_failed; else if (task & einit_module_disable) return status_ok; else return status_ok; } module->status |= status_working; /* check if the task requested has already been done (or if it can be done at all) */ if ((task & einit_module_enable) && (!module->enable || (module->status & status_enabled))) { wontload: module->status ^= status_working; if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); return status_idle; } if ((task & einit_module_disable) && (!module->disable || (module->status & status_disabled) || (module->status == status_idle))) goto wontload; if (task & einit_module_enable) { if (!service_usage_query(service_requirements_met, module, NULL)) goto wontload; } else if (task & einit_module_disable) { if (!service_usage_query(service_not_in_use, module, NULL)) goto wontload; } skipdependencies: /* inform everyone about what's going to happen */ { struct einit_event eem = evstaticinit (einit_core_module_update); modules_work_count++; eem.task = task; eem.status = status_working; eem.para = (void *)module; eem.string = (module->module && module->module->rid) ? module->module->rid : module->si->provides[0]; event_emit (&eem, einit_event_flag_broadcast); evstaticdestroy (eem); /* same for services */ if (module->si && module->si->provides) { struct einit_event ees = evstaticinit (einit_core_service_update); ees.task = task; ees.status = status_working; ees.string = (module->module && module->module->rid) ? module->module->rid : module->si->provides[0]; ees.set = (void **)module->si->provides; ees.para = (void *)module; event_emit (&ees, einit_event_flag_broadcast); evstaticdestroy (ees); } } /* actual loading bit */ { fb = evinit (einit_feedback_module_status); fb->para = (void *)module; fb->task = task | einit_module_feedback_show; fb->status = status_working; fb->flag = 0; fb->string = NULL; fb->stringset = (char **)setadd ((void **)NULL, (module->module && module->module->rid) ? module->module->rid : module->si->provides[0], SET_TYPE_STRING); fb->integer = module->fbseq+1; status_update (fb); if (task & einit_module_custom) { if (strmatch (custom_command, "zap")) { char zerror = module->status & status_failed ? 1 : 0; fb->string = "module ZAP'd."; module->status = status_idle; module->status = status_disabled; if (zerror) module->status |= status_failed; } else if (module->custom) { module->status = module->custom(module->param, custom_command, fb); } else { module->status = (module->status & (status_enabled | status_disabled)) | status_failed | status_command_not_implemented; } } else if (task & einit_module_enable) { ret = module->enable (module->param, fb); if (ret & status_ok) { module->status = status_ok | status_enabled; } else { module->status = status_failed | status_disabled; } } else if (task & einit_module_disable) { ret = module->disable (module->param, fb); if (ret & status_ok) { module->status = status_ok | status_disabled; } else { module->status = status_failed | status_enabled; } } fb->status = module->status; module->fbseq = fb->integer + 1; status_update (fb); // event_emit(fb, einit_event_flag_broadcast); // if (fb->task & einit_module_feedback_show) fb->task ^= einit_module_feedback_show; fb->string = NULL; /* module status update */ { struct einit_event eem = evstaticinit (einit_core_module_update); eem.task = task; eem.status = fb->status; eem.para = (void *)module; eem.string = (module->module && module->module->rid) ? module->module->rid : module->si->provides[0]; event_emit (&eem, einit_event_flag_broadcast); evstaticdestroy (eem); /* service status update */ if (module->si && module->si->provides) { struct einit_event ees = evstaticinit (einit_core_service_update); ees.task = task; ees.status = fb->status; ees.string = (module->module && module->module->rid) ? module->module->rid : module->si->provides[0]; ees.set = (void **)module->si->provides; ees.para = (void *)module; event_emit (&ees, einit_event_flag_broadcast); evstaticdestroy (ees); } } free (fb->stringset); evdestroy (fb); service_usage_query(service_update, module, NULL); modules_work_count--; } if (!(task & einit_module_ignore_mutex)) emutex_unlock (&module->mutex); return module->status; }
void sys_init() { event_emit( PRIORITY_HIGH, EV_MBREQ_DONE, (unidata_t)ENOERR ); return; }
void einit_feedback_visual_fbsplash_boot_event_handler(struct einit_event *ev) { /* preinit */ if ((ev->type == einit_boot_devices_available) && !(coremode & einit_mode_ipconly)) { if (einit_initial_environment) { /* check for kernel params */ uint32_t i = 0; char start_splash = 0, *ttypatch = NULL, *splashargs = NULL; for (; einit_initial_environment[i]; i++) { if (strstr (einit_initial_environment[i], "splash=") == einit_initial_environment[i]) { start_splash = 1; splashargs = einit_initial_environment[i]+7; if (!ttypatch) ttypatch = "tty1"; } else if ((strstr (einit_initial_environment[i], "console=") == einit_initial_environment[i]) || (strstr (einit_initial_environment[i], "einitty=") == einit_initial_environment[i])) { ttypatch = einit_initial_environment[i]+8; } } if (splashargs && *splashargs) { char *fbtheme = NULL/*, *fbmode = NULL*/; if (splashargs) { char **p = str2set (',', splashargs); if (p) { for (i = 0; p[i]; i++) { char *sep = strchr (p[i], ':'); if (sep) { *sep = 0; sep++; if (strmatch (p[i], "theme")) { fbtheme = estrdup (sep); } }/* else { fbmode = estrdup(p[i]); }*/ } free (p); } } if (fbtheme) { struct cfgnode *node = cfg_getnode ("configuration-feedback-visual-fbsplash-theme", NULL); if (node && node->arbattrs) { uint32_t u = 0; for (; node->arbattrs[u]; u+=2) { if (strmatch(node->arbattrs[u], "s")) { notice (4, "patching fbsplash theme to %s", fbtheme); node->arbattrs[u+1] = fbtheme; node->svalue = fbtheme; } } } } /* if (fbmode) { }*/ } else fbsplash_disabled = 1; if (ttypatch && *ttypatch) { struct cfgnode *node = cfg_getnode ("configuration-feedback-visual-std-io", NULL); /* patch console */ if (node && node->arbattrs) { uint32_t ri = 0; for (; node->arbattrs[ri]; ri+=2) { if (strmatch (node->arbattrs[ri], "stdio")) { char tx[BUFFERSIZE]; if (ttypatch[0] == '/') esprintf (tx, BUFFERSIZE, "%s", ttypatch); else esprintf (tx, BUFFERSIZE, "/dev/%s", ttypatch); notice (4, "patching stdio output to go to %s", tx); node->arbattrs[ri+1] = estrdup(tx); } else if (strmatch (node->arbattrs[ri], "activate-vt")) { notice (4, "removing activate-vt= instruction"); node->arbattrs = (char **)setdel ((void **)node->arbattrs, node->arbattrs[ri]); node->arbattrs = (char **)setdel ((void **)node->arbattrs, node->arbattrs[ri]); } } } } if (start_splash) { struct einit_event ee = evstaticinit(einit_core_change_service_status); ee.argv = (char **)setadd ((void **)ee.set, "splashd", SET_TYPE_STRING); ee.argv = (char **)setadd ((void **)ee.set, "enable", SET_TYPE_STRING); event_emit (&ee, einit_event_flag_broadcast); evstaticdestroy(ee); notice (4, "enabling feedack (fbsplash)"); einit_feedback_visual_fbsplash_enable(); } } } }
void atimer_fired( uint8_t tnum ) { event_emit( EV_PRIORITY, EV_TYPE, EV_UNIDATA ); return; }
void linux_static_dev_load_kernel_extensions() { struct einit_event eml = evstaticinit(einit_boot_load_kernel_extensions); event_emit (&eml, einit_event_flag_broadcast | einit_event_flag_spawn_thread_multi_wait); evstaticdestroy(eml); }
void event_handler( event_type_t event_type, unidata_t unidata ) { char str[32]; unsigned char ch; static int err; switch(event_type) { case KBRD_EVT: // ltoa((int32_t)unidata, str, 10); // OLED_puts(0, 41, 0xff, font6x9, str); if(kbrd_pressed) { kbrd_pressed = 0; //display_node(kbrd_getch()); ch = kbrd_getch(); /* itoa((int16_t)ch, str, 16); OLED_clr(0, 41, 3 * 6, 9); OLED_puts(0, 41, 0xff, font6x9, str); */ if(!(ch & 0x80)) { ch = active.menu->action(ch); active.menu->display(ch); update_statusbar(); } /* switch((ch = kbrd_getch())) { case 1: case 129: display(0, 0); break; case 16: case 144: display(1, 0); break; case 14: if((scroll_pos < (MSG_TABLE_SIZE - MSG_VIEW_SIZE)) && (scroll_pos < msg_count - 1)) { scroll_pos ++; event_emit(LOW_PRIORITY, DISPLAY_EVT, 2); } case 142: break; case 13: if(scroll_pos) { scroll_pos--; event_emit(LOW_PRIORITY, DISPLAY_EVT, 2); } case 141: break; case 11: OLED_cls(); err = initConfig(); //sprintf(str, "initConfig res: %d", err); //OLED_puts(0, 0, 0xff, font6x9, str); OLED_puts(0, 0, 0xff, font6x9, (err ? "initConfig failed" : "initConfig success")); break; case 134: { struct LogEntry entry; err = STRG_SUCCESS; entry.timestamp = 0; err += logAddEntry(&entry, "Msg 0"); entry.timestamp = 1000; err += logAddEntry(&entry, "Msg 1"); entry.timestamp = 2000; err += logAddEntry(&entry, "Msg 2"); sprintf(str, "Error code: %d", err); OLED_puts(0, 2*9, 0xff, font6x9, str); } break; default: display(2, ch); break; // display(0, 0); } */ /* OLED_puts(64 + 12, 41, 0xff, font6x9, "Key pressed "); itoa(kbrd_getch(), str, 10); OLED_puts(64 + 12 + sizeof("Key pressed ") * 6, 41, 0xff, font6x9, str); OLED_puts(64 + 12 + sizeof("Key pressed ") * 6 + strlen(str) * 6, 41, 0xff, font6x9, " "); */ } /* else OLED_puts(0, 41, 0xff, font6x9, "Key not pressed"); */ break; case INIT_EVT: //OLED_init(); //init_kbrd(); SPI_init(); event_emit(LOW_PRIORITY, INIT_MMC_EVT, 0); break; case INIT_MMC_EVT: initMMC(); err = initStorage(); event_emit(LOW_PRIORITY, INIT_OLED_EVT, 0); break; case INIT_OLED_EVT: OLED_init(); OLED_puts(0, 0 , 0xff, font6x9, "System initialization..."); OLED_puts(0, 1 * 9 , 0xff, font6x9, "SPI init'ed."); OLED_puts(0, 2 * 9 , 0xff, font6x9, "MMC init'ed."); OLED_puts(0, 3 * 9 , 0xff, font6x9, "OLED init'ed."); event_emit(LOW_PRIORITY, INIT_STORAGE_EVT, 0); break; case INIT_STORAGE_EVT: //err = initStorage(); //OLED_puts(0, 4 * 9 , 0xff, font6x9, err ? "Storage init failed!" : "Storage init'ed."); format_str(str, 32, "Storage err: %d", err); OLED_puts(0, 4 * 9 , 0xff, font6x9, err ? str : "Storage init'ed."); /* format_str(str, 32, "ZoneCfg pos: %u", syscfg.zone_cfg_addr); OLED_puts(0, 5 * 9 , 0xff, font6x9, str); err = 1; */ event_emit(LOW_PRIORITY, INIT_USER_IO_EVT, 0); break; case INIT_USER_IO_EVT: init_kbrd(); menu_init(err ? MNU_INIT | MNU_DO_NOT_SHOW : MNU_INIT); //set_sys_time((uint64_t)20000); stimer_set(1, 1000); break; } /* else if(event_type == INIT_SEND_MSGS_EVT) { msg_t msg; struct msginfo minfo; uint16_t addr_attr = 0x0000; uint8_t port_attr = PORT; //attr_write(0x02, &addr_attr); //attr_write(0x07, &port_attr); // This must be the code for us to say ZigZag (Node Dispatcher) // that we are interested in listening for messages and events msg = msg_new(0x00, 0x00, 0x01, 3, MFLAG_DEFAULT); if(msg < 0) OLED_puts(0, 0, 0xff, font6x9, "Error: msg_new"); if(msg_info(msg, &minfo) != ENOERR) OLED_puts(0, 9, 0xff, font6x9, "Error: msg_info"); ((unsigned char *)minfo.body_ptr)[0] = 0x02; ((unsigned char *)minfo.body_ptr)[1] = 0x00; ((unsigned char *)minfo.body_ptr)[2] = 0x00; if(msg_send(msg) != ENOERR) OLED_puts(0, 18, 0xff, font6x9, "Error: msg_send (1)"); msg = msg_new(0x00, 0x00, 0x01, 2, MFLAG_DEFAULT); if(msg < 0) OLED_puts(0, 0, 0xff, font6x9, "Error: msg_new"); if(msg_info(msg, &minfo) != ENOERR) OLED_puts(0, 9, 0xff, font6x9, "Error: msg_info"); ((unsigned char *)minfo.body_ptr)[0] = 0x07; ((unsigned char *)minfo.body_ptr)[1] = (uint8_t)PORT; // ((unsigned char *)minfo.body_ptr)[2] = (uint8_t)(PORT >> 8); if(msg_send(msg) != ENOERR) OLED_puts(0, 18, 0xff, font6x9, "Error: msg_send (2)"); } */ /* else { //sprintf(str, "Evt: %u", (uint16_t)event_type); //OLED_puts(0, 0, 0xff, font6x9, str); } */ }
int main(int argc, char **argv, char **environ) { #else int main(int argc, char **argv) { #endif int i, ret = EXIT_SUCCESS; pid_t pid = getpid(), wpid = 0; char **ipccommands = NULL; int pthread_errno; FILE *commandpipe_in, *commandpipe_out; int commandpipe[2]; int debugsocket[2]; char need_recovery = 0; char debug = 0; int debugme_pipe = 0; char crash_threshold = 5; char *einit_crash_data = NULL; boottime = time(NULL); uname (&osinfo); config_configure(); // initialise subsystems ipc_configure(NULL); // is this the system's init-process? isinit = getpid() == 1; event_listen (einit_event_subsystem_core, core_einit_event_handler); event_listen (einit_event_subsystem_timer, core_timer_event_handler); if (argv) einit_argv = (char **)setdup ((const void **)argv, SET_TYPE_STRING); /* check command line arguments */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') switch (argv[i][1]) { case 'c': if ((++i) < argc) einit_default_startup_configuration_files[0] = argv[i]; else return print_usage_info (); break; case 'h': return print_usage_info (); break; case 'v': eputs("eINIT " EINIT_VERSION_LITERAL "\n", stdout); return 0; case 'L': eputs("eINIT " EINIT_VERSION_LITERAL "\nThis Program is Free Software, released under the terms of this (BSD) License:\n" "--------------------------------------------------------------------------------\n" "Copyright (c) 2006, 2007, Magnus Deininger\n" BSDLICENSE "\n", stdout); return 0; case '-': if (strmatch(argv[i], "--check-configuration") || strmatch(argv[i], "--checkup") || strmatch(argv[i], "--wtf")) { ipccommands = (char **)setadd ((void **)ipccommands, "examine configuration", SET_TYPE_STRING); } else if (strmatch(argv[i], "--help")) return print_usage_info (); else if (strmatch(argv[i], "--ipc-command") && argv[i+1]) ipccommands = (char **)setadd ((void **)ipccommands, (void *)argv[i+1], SET_TYPE_STRING); else if (strmatch(argv[i], "--override-init-check")) initoverride = 1; else if (strmatch(argv[i], "--sandbox")) { einit_default_startup_configuration_files[0] = "lib/einit/einit.xml"; coremode = einit_mode_sandbox; need_recovery = 1; } else if (strmatch(argv[i], "--metadaemon")) { coremode = einit_mode_metadaemon; } else if (strmatch(argv[i], "--bootstrap-modules")) { bootstrapmodulepath = argv[i+1]; } else if (strmatch(argv[i], "--debugme")) { debugme_pipe = parse_integer (argv[i+1]); i++; initoverride = 1; } else if (strmatch(argv[i], "--debug")) { debug = 1; } break; } } /* check environment */ if (environ) { uint32_t e = 0; for (e = 0; environ[e]; e++) { char *ed = estrdup (environ[e]); char *lp = strchr (ed, '='); *lp = 0; lp++; if (strmatch (ed, "softlevel")) { einit_startup_mode_switches = str2set (':', lp); } if (strmatch (ed, "mode")) { /* override default mode-switches with the ones in the environment variable mode= */ einit_startup_mode_switches = str2set (':', lp); } else if (strmatch (ed, "einit")) { /* override default configuration files and/or mode-switches with the ones in the variable einit= */ char **tmpstrset = str2set (',', lp); uint32_t rx = 0; for (rx = 0; tmpstrset[rx]; rx++) { char **atom = str2set (':', tmpstrset[rx]); if (strmatch (atom[0], "file")) { /* specify configuration files */ einit_startup_configuration_files = (char **)setdup ((const void **)atom, SET_TYPE_STRING); einit_startup_configuration_files = (char **)strsetdel (einit_startup_configuration_files, (void *)"file"); } else if (strmatch (atom[0], "mode")) { /* specify mode-switches */ einit_startup_mode_switches = (char **)setdup ((const void **)atom, SET_TYPE_STRING); einit_startup_mode_switches = (char **)strsetdel (einit_startup_mode_switches, (void *)"mode"); } else if (strmatch (atom[0], "stfu")) { einit_quietness = 3; } else if (strmatch (atom[0], "silent")) { einit_quietness = 2; } else if (strmatch (atom[0], "quiet")) { einit_quietness = 1; } free (atom); } free (tmpstrset); } free (ed); } einit_initial_environment = (char **)setdup ((const void **)environ, SET_TYPE_STRING); } if (!einit_startup_mode_switches) einit_startup_mode_switches = einit_default_startup_mode_switches; if (!einit_startup_configuration_files) einit_startup_configuration_files = einit_default_startup_configuration_files; respawn: pipe (commandpipe); fcntl (commandpipe[1], F_SETFD, FD_CLOEXEC); socketpair (AF_UNIX, SOCK_STREAM, 0, debugsocket); fcntl (debugsocket[0], F_SETFD, FD_CLOEXEC); fcntl (debugsocket[1], F_SETFD, FD_CLOEXEC); if (!debug) { fcntl (commandpipe[0], F_SETFD, FD_CLOEXEC); commandpipe_in = fdopen (commandpipe[0], "r"); } commandpipe_out = fdopen (commandpipe[1], "w"); if (!initoverride && ((pid == 1) || ((coremode & einit_mode_sandbox) && !ipccommands))) { // if (pid == 1) { initoverride = 1; #if 0 #ifdef LINUX if ((einit_sub = syscall(__NR_clone, CLONE_PTRACE | SIGCHLD, 0, NULL, NULL, NULL)) < 0) { bitch (bitch_stdio, errno, "Could not fork()"); eputs (" !! Haven't been able to fork a secondary worker process. This is VERY bad, you will get a lot of zombie processes! (provided that things work at all)\n", stderr); } #else #endif #endif if ((einit_sub = fork()) < 0) { bitch (bitch_stdio, errno, "Could not fork()"); eputs (" !! Haven't been able to fork a secondary worker process. This is VERY bad, you will get a lot of zombie processes! (provided that things work at all)\n", stderr); } } if (einit_sub) { /* PID==1 part */ int rstatus; struct sigaction action; /* signal handlers */ action.sa_sigaction = einit_sigint; sigemptyset(&(action.sa_mask)); action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; if ( sigaction (SIGINT, &action, NULL) ) bitch (bitch_stdio, 0, "calling sigaction() failed."); /* ignore sigpipe */ action.sa_sigaction = (void (*)(int, siginfo_t *, void *))SIG_IGN; if ( sigaction (SIGPIPE, &action, NULL) ) bitch (bitch_stdio, 0, "calling sigaction() failed."); close (debugsocket[1]); if (einit_crash_data) { free (einit_crash_data); einit_crash_data = NULL; } while (1) { wpid = waitpid(-1, &rstatus, 0); /* this ought to wait for ANY process */ if (wpid == einit_sub) { // goto respawn; /* try to recover by re-booting */ if (!debug) if (commandpipe_in) fclose (commandpipe_in); if (commandpipe_out) fclose (commandpipe_out); if (WIFEXITED(rstatus) && (WEXITSTATUS(rstatus) != einit_exit_status_die_respawn)) { fprintf (stderr, "eINIT has quit properly.\n"); if (!(coremode & einit_mode_sandbox)) { if (WEXITSTATUS(rstatus) == einit_exit_status_last_rites_halt) { execl (EINIT_LIB_BASE "/bin/last-rites", EINIT_LIB_BASE "/bin/last-rites", "h", NULL); } else if (WEXITSTATUS(rstatus) == einit_exit_status_last_rites_reboot) { execl (EINIT_LIB_BASE "/bin/last-rites", EINIT_LIB_BASE "/bin/last-rites", "r", NULL); } else if (WEXITSTATUS(rstatus) == einit_exit_status_last_rites_kexec) { execl (EINIT_LIB_BASE "/bin/last-rites", EINIT_LIB_BASE "/bin/last-rites", "k", NULL); } } exit (EXIT_SUCCESS); } int n = 5; fprintf (stderr, "The secondary eINIT process has died, waiting a while before respawning.\n"); if ((einit_crash_data = readfd (debugsocket[0]))) { fprintf (stderr, " > neat, received crash data\n"); } while ((n = sleep (n))); fprintf (stderr, "Respawning secondary eINIT process.\n"); if (crash_threshold) crash_threshold--; else debug = 1; need_recovery = 1; initoverride = 0; close (debugsocket[0]); goto respawn; } else { if (commandpipe_out) { if (WIFEXITED(rstatus)) { fprintf (commandpipe_out, "pid %i terminated\n\n", wpid); } else { fprintf (commandpipe_out, "pid %i died\n\n", wpid); } fflush (commandpipe_out); } } } } else { enable_core_dumps (); close (debugsocket[0]); sched_trace_target = debugsocket[1]; if (debug) { char **xargv = (char **)setdup ((const void **)argv, SET_TYPE_STRING); char tbuffer[BUFFERSIZE]; struct stat st; char have_valgrind = 0; char have_gdb = 0; fputs ("eINIT needs to be debugged, starting in debugger mode\n.", stderr); xargv = (char **)setadd ((void **)xargv, (void *)"--debugme", SET_TYPE_STRING); snprintf (tbuffer, BUFFERSIZE, "%i", commandpipe[0]); xargv = (char **)setadd ((void **)xargv, (void *)tbuffer, SET_TYPE_STRING); xargv = strsetdel (xargv, "--debug"); // don't keep the --debug flag if (!stat ("/usr/bin/valgrind", &st)) have_valgrind = 1; if (!stat ("/usr/bin/gdb", &st)) have_gdb = 1; if (have_valgrind) { char **nargv = NULL; uint32_t i = 1; #ifdef LINUX if (!(coremode & einit_mode_sandbox)) { mount ("proc", "/proc", "proc", 0, NULL); mount ("sys", "/sys", "sysfs", 0, NULL); system ("mount / -o remount,rw"); } #endif nargv = (char **)setadd ((void **)nargv, "/usr/bin/valgrind", SET_TYPE_STRING); nargv = (char **)setadd ((void **)nargv, "--log-file=/einit.valgrind", SET_TYPE_STRING); nargv = (char **)setadd ((void **)nargv, (coremode & einit_mode_sandbox) ? "sbin/einit" : "/sbin/einit", SET_TYPE_STRING); for (; xargv[i]; i++) { nargv = (char **)setadd ((void **)nargv, xargv[i], SET_TYPE_STRING); } execv ("/usr/bin/valgrind", nargv); } else { execv ((coremode & einit_mode_sandbox) ? "sbin/einit" : "/sbin/einit", xargv); } } if (debugme_pipe) { // commandpipe[0] fcntl (commandpipe[0], F_SETFD, FD_CLOEXEC); commandpipe_in = fdopen (debugme_pipe, "r"); } /* actual system initialisation */ struct einit_event cev = evstaticinit(einit_core_update_configuration); if (ipccommands && (coremode != einit_mode_sandbox)) { coremode = einit_mode_ipconly; } eprintf (stderr, "eINIT " EINIT_VERSION_LITERAL ": Initialising: %s\n", osinfo.sysname); if ((pthread_errno = pthread_attr_init (&thread_attribute_detached))) { bitch(bitch_epthreads, pthread_errno, "pthread_attr_init() failed."); if (einit_initial_environment) free (einit_initial_environment); return -1; } else { if ((pthread_errno = pthread_attr_setdetachstate (&thread_attribute_detached, PTHREAD_CREATE_DETACHED))) { bitch(bitch_epthreads, pthread_errno, "pthread_attr_setdetachstate() failed."); } } if ((pthread_errno = pthread_key_create(&einit_function_macro_key, NULL))) { bitch(bitch_epthreads, pthread_errno, "pthread_key_create(einit_function_macro_key) failed."); if (einit_initial_environment) free (einit_initial_environment); return -1; } /* this should be a good place to initialise internal modules */ if (coremodules) { uint32_t cp = 0; eputs (" >> initialising in-core modules:", stderr); for (; coremodules[cp]; cp++) { struct lmodule *lmm; eprintf (stderr, " [%s]", (*coremodules[cp])->rid); lmm = mod_add(NULL, (*coremodules[cp])); lmm->source = estrdup("core"); } eputs (" OK\n", stderr); } /* emit events to read configuration files */ if (einit_startup_configuration_files) { uint32_t rx = 0; for (; einit_startup_configuration_files[rx]; rx++) { cev.string = einit_startup_configuration_files[rx]; event_emit (&cev, einit_event_flag_broadcast); } if (einit_startup_configuration_files != einit_default_startup_configuration_files) { free (einit_startup_configuration_files); } } cev.string = NULL; cev.type = einit_core_configuration_update; // make sure we keep updating until everything is sorted out while (cev.type == einit_core_configuration_update) { // notice (2, "stuff changed, updating configuration."); cev.type = einit_core_update_configuration; event_emit (&cev, einit_event_flag_broadcast); } evstaticdestroy(cev); if (ipccommands) { uint32_t rx = 0; for (; ipccommands[rx]; rx++) { ret = ipc_process (ipccommands[rx], stdout); } // if (gmode == EINIT_GMODE_SANDBOX) // cleanup (); free (ipccommands); if (einit_initial_environment) free (einit_initial_environment); return ret; } else if ((coremode == einit_mode_init) && !isinit && !initoverride) { eputs ("WARNING: eINIT is configured to run as init, but is not the init-process (pid=1) and the --override-init-check flag was not specified.\nexiting...\n\n", stderr); exit (EXIT_FAILURE); } else { /* actual init code */ uint32_t e = 0; nice (einit_core_niceness_increment); if (need_recovery) { notice (1, "need to recover from something..."); struct einit_event eml = evstaticinit(einit_core_recover); event_emit (&eml, einit_event_flag_broadcast); evstaticdestroy(eml); } if (einit_crash_data) { notice (1, "submitting crash data..."); struct einit_event eml = evstaticinit(einit_core_crash_data); eml.string = einit_crash_data; event_emit (&eml, einit_event_flag_broadcast); evstaticdestroy(eml); free (einit_crash_data); einit_crash_data = NULL; } { notice (3, "running early bootup code..."); struct einit_event eml = evstaticinit(einit_boot_early); event_emit (&eml, einit_event_flag_broadcast | einit_event_flag_spawn_thread_multi_wait); evstaticdestroy(eml); } notice (2, "scheduling startup switches.\n"); for (e = 0; einit_startup_mode_switches[e]; e++) { struct einit_event ee = evstaticinit(einit_core_switch_mode); ee.string = einit_startup_mode_switches[e]; event_emit (&ee, einit_event_flag_broadcast | einit_event_flag_spawn_thread | einit_event_flag_duplicate); evstaticdestroy(ee); } struct einit_event eml = evstaticinit(einit_core_main_loop_reached); eml.file = commandpipe_in; event_emit (&eml, einit_event_flag_broadcast); evstaticdestroy(eml); } if (einit_initial_environment) free (einit_initial_environment); return ret; } /* this should never be reached... */ if (einit_initial_environment) free (einit_initial_environment); return 0; }
void core_einit_event_handler (struct einit_event *ev) { if (ev->type == einit_core_configuration_update) { struct cfgnode *node; char *str; ev->chain_type = einit_core_update_modules; if ((node = cfg_getnode ("core-mortality-bad-malloc", NULL))) mortality[bitch_emalloc] = node->value; if ((node = cfg_getnode ("core-mortality-bad-stdio", NULL))) mortality[bitch_stdio] = node->value; if ((node = cfg_getnode ("core-mortality-bad-regex", NULL))) mortality[bitch_regex] = node->value; if ((node = cfg_getnode ("core-mortality-bad-expat", NULL))) mortality[bitch_expat] = node->value; if ((node = cfg_getnode ("core-mortality-bad-dl", NULL))) mortality[bitch_dl] = node->value; if ((node = cfg_getnode ("core-mortality-bad-lookup", NULL))) mortality[bitch_lookup] = node->value; if ((node = cfg_getnode ("core-mortality-bad-pthreads", NULL))) mortality[bitch_epthreads] = node->value; if ((node = cfg_getnode ("core-settings-allow-code-unloading", NULL))) einit_allow_code_unloading = node->flag; if ((str = cfg_getstring ("core-scheduler-niceness/core", NULL))) einit_core_niceness_increment = parse_integer (str); if ((str = cfg_getstring ("core-scheduler-niceness/tasks", NULL))) einit_task_niceness_increment = parse_integer (str); } else if (ev->type == einit_core_update_modules) { struct lmodule *lm; repeat: lm = mlist; einit_new_node = 0; while (lm) { if (lm->source && strmatch(lm->source, "core")) { lm = mod_update (lm); // tell module to scan for changes if it's a module-loader if (lm->module && (lm->module->mode & einit_module_loader) && (lm->scanmodules != NULL)) { notice (8, "updating modules (%s)", lm->module->rid ? lm->module->rid : "unknown"); lm->scanmodules (mlist); /* if an actual new node has been added to the configuration, repeat this step */ if (einit_new_node) goto repeat; } } lm = lm->next; } /* give the module-logic code and others a chance at processing the current list */ struct einit_event update_event = evstaticinit(einit_core_module_list_update); update_event.para = mlist; event_emit (&update_event, einit_event_flag_broadcast); evstaticdestroy(update_event); } else if (ev->type == einit_core_recover) { // call everyone's recover-function (if defined) struct lmodule *lm = mlist; while (lm) { if (lm->recover) { lm->recover (lm); } lm = lm->next; } } else if (ev->type == einit_core_suspend_all) { // suspend everyone (if possible) struct lmodule *lm = mlist; int ok = 0; while (lm) { ok += (mod (einit_module_suspend, lm, NULL) == status_ok) ? 1 : 0; lm = lm->next; } if (ok) notice (4, "%i modules suspended", ok); event_snooze_time = event_timer_register_timeout(60); } else if (ev->type == einit_core_resume_all) { // resume everyone (if necessary) struct lmodule *lm = mlist; int ok = 0; while (lm) { ok += (mod (einit_module_resume, lm, NULL) == status_ok) ? 1 : 0; lm = lm->next; } if (ok) notice (4, "%i available", ok); } }