int main(void) { struct timer periodic_timer, arp_timer; // Flash the status LED two times to indicate that the AVR controller is living STATUS_LED_on(); _delay_ms(20); STATUS_LED_off(); _delay_ms(100); STATUS_LED_on(); _delay_ms(20); STATUS_LED_off(); // Initialize direction and level of I/O pins init_io_pins(); #if ADC_CHANNELS > 0 // initialize ADC converter initADC(); #endif // enable io functions isBusy=0; // Initialize system clock timers. clock_init(); timer_set(&periodic_timer, CLOCK_SECOND); timer_set(&arp_timer, CLOCK_SECOND*10); // check if the config reset jumper is connected. check_for_reset_jumper(); #ifdef SERIAL // start the serial port server seriald_init(); #endif // SERIAL // initialize ethernet controller // loop until link comes up while (init_CP2200()==0) { _delay_ms(200); } // replace config by hardcoded defaults if the flash is unprogrammed (all bits 1) if (uip_ipaddr_cmp(config.ipaddr, all_ones_addr) && uip_ipaddr_cmp(config.netmask, all_ones_addr) && uip_ipaddr_cmp(config.gateway, all_ones_addr)) { set_defaults(); } // initialize uIP protocol uip_arp_init(); uip_init(); // Configure the IP-Adrdess IP_config(); #ifdef EMAIL_APP // Initialize the email application email_app_init(); #endif // EMAIL_APP // Initialize the inetd inetd_init(); // main loop, dispatches network and timer events while (1) { uip_len = network_device_read(); if (uip_len > 0) { if (BUF->type == htons(UIP_ETHTYPE_IP)) { uip_arp_ipin(); uip_input(); // If the above function invocation resulted in data that // should be sent out on the network, the global variable // uip_len is set to a value > 0. if (uip_len > 0) { uip_arp_out(); network_device_send(); } } else if (BUF->type == htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); // If the above function invocation resulted in data that // should be sent out on the network, the global variable // uip_len is set to a value > 0. if (uip_len > 0) { network_device_send(); } } } else if (timer_expired(&periodic_timer)) { timer_reset(&periodic_timer); for (int i = 0; i < UIP_CONNS; i++) { uip_periodic(i); // If the above function invocation resulted in data that // should be sent out on the network, the global variable // uip_len is set to a value > 0. if (uip_len > 0) { uip_arp_out(); network_device_send(); } } #if UIP_UDP for (int i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_periodic(i); // If the above function invocation resulted in data that // should be sent out on the network, the global variable // uip_len is set to a value > 0. if (uip_len > 0) { uip_arp_out(); network_device_send(); } } #endif // UIP_UDP // Call the ARP timer function every 10 seconds. if (timer_expired(&arp_timer)) { timer_reset(&arp_timer); uip_arp_timer(); } } #ifdef EMAIL_APP email_app_main_loop(); #endif //EMAIL_APP } return 0; }
/** * svc_register - Register service, task or run commands * @type: %SVC_CMD_SERVICE(0), %SVC_CMD_TASK(1), %SVC_CMD_RUN(2) * @line: A complete command line with -- separated description text * @username: Optional username to run service as, or %NULL to run as root * * This function is used to register commands to be run on different * system runlevels with optional username. The @type argument details * if it's service to bo monitored/respawned (daemon), a one-shot task * or a command that must run in sequence and not in parallell, like * service and task commands do. * * The @line can optionally start with a username, denoted by an @ * character. Like this: * * "service @username [!0-6,S] /path/to/daemon arg -- Description text" * "task @username [!0-6,S] /path/to/task arg -- Description text" * "run @username [!0-6,S] /path/to/cmd arg -- Description text" * "inetd tcp/ssh nowait [2345] @root:root /usr/sbin/sshd -i -- Description" * * If the username is left out the command is started as root. * Inetd services, launched on demand (SVC_CMD_INETD) * The [] brackets are there to denote the allowed runlevels. Allowed * runlevels mimic that of SysV init with the addition of the 'S' * runlevel, which is only run once at startup. It can be seen as the * system bootstrap. If a task or run command is listed in more than the * [S] runlevel they will be called when changing runlevel. * * Returns: * POSIX OK(0) on success, or non-zero errno exit status on failure. */ int svc_register(int type, char *line, char *username) { int i = 0; #ifndef INETD_DISABLED int forking = 0; #endif char *service = NULL, *proto = NULL, *iface = NULL, *port = NULL; char *cmd, *desc, *runlevels = NULL; svc_t *svc; plugin_t *plugin = NULL; if (!line) { _e("Invalid input argument."); return errno = EINVAL; } desc = strstr(line, "-- "); if (desc) *desc = 0; cmd = strtok(line, " "); if (!cmd) { incomplete: _e("Incomplete service, cannot register."); return errno = ENOENT; } while (cmd) { if (cmd[0] != '/' && strchr(cmd, '/')) service = cmd; /* inetd service/proto */ #ifndef INETD_DISABLED else if (!strncasecmp(cmd, "nowait", 6)) forking = 1; else if (!strncasecmp(cmd, "wait", 4)) forking = 0; #endif else if (cmd[0] == '@') /* @username[:group] */ username = &cmd[1]; else if (cmd[0] == '[') /* [runlevels] */ runlevels = &cmd[0]; else break; /* Check if valid command follows... */ cmd = strtok(NULL, " "); if (!cmd) goto incomplete; } /* Example: inetd ssh@eth0:222/tcp */ if (service) { proto = strchr(service, '/'); if (!proto) goto incomplete; *proto++ = 0; port = strchr(service, ':'); if (port) *port++ = 0; iface = strchr(service, '@'); if (iface) *iface++ = 0; } #ifndef INETD_DISABLED /* Find plugin that provides a callback for this inetd service */ if (type == SVC_CMD_INETD && !strncasecmp(cmd, "internal", 8)) { plugin = plugin_find(service); if (!plugin || !plugin->inetd.cmd) { _e("Inetd service %s has no internal plugin, skipping.", service); return errno = ENOENT; } } /* Check if known inetd, then add ifname for filtering only. */ svc = svc_find_inetd(cmd, service, proto, port); if (svc) return inetd_allow(&svc->inetd, iface); #endif svc = svc_new(); if (!svc) { _e("Out of memory, cannot register service %s", cmd); return errno = ENOMEM; } svc->type = type; if (desc) strlcpy(svc->desc, desc + 3, sizeof(svc->desc)); if (username) { char *ptr = strchr(username, ':'); if (ptr) { *ptr++ = 0; strlcpy(svc->group, ptr, sizeof(svc->group)); } strlcpy(svc->username, username, sizeof(svc->username)); } #ifndef INETD_DISABLED if (svc->type == SVC_CMD_INETD) { int result; result = inetd_new(&svc->inetd, service, proto, forking); result += inetd_init(&svc->inetd, svc, iface, port); if (result) { _e("Failed registering new inetd service %s.", service); inetd_del(&svc->inetd); return svc_del(svc); } } #endif if (plugin) { /* Internal plugin provides this service */ svc->inetd.cmd = plugin->inetd.cmd; } else { /* External program to call */ strlcpy(svc->cmd, cmd, sizeof(svc->cmd)); strlcpy(svc->args[i++], cmd, sizeof(svc->args[0])); while ((cmd = strtok(NULL, " "))) strlcpy(svc->args[i++], cmd, sizeof(svc->args[0])); svc->args[i][0] = 0; plugin = plugin_find(svc->cmd); if (plugin && plugin->svc.cb) { svc->cb = plugin->svc.cb; svc->dynamic = plugin->svc.dynamic; svc->dynamic_stop = plugin->svc.dynamic_stop; } } svc->runlevels = parse_runlevels(runlevels); _d("Service %s runlevel 0x%2x", svc->cmd, svc->runlevels); return 0; }