int main() { char *x; unsigned int i, j, k; unsigned long cachesize; static stralloc sa = {0}; x = env_get("INTERFACE"); if (x) scan_ulong(x,&interface); x = env_get("IP"); if (!x) strerr_die2x(111,FATAL,"$IP not set"); if (!ip6_scan(x,myipincoming)) strerr_die3x(111,FATAL,"unable to parse IP address ",x); #if 0 /* if if IP is a mapped-IPv4 address, disable IPv6 functionality */ /* this is actually a bad idea */ if (ip6_isv4mapped(myipincoming)) noipv6 = 1; #endif udp53 = socket_udp6(); if (udp53 == -1) strerr_die2sys(111,FATAL,"unable to create UDP socket: "); if (socket_bind6_reuse(udp53,myipincoming,53,interface) == -1) strerr_die2sys(111,FATAL,"unable to bind UDP socket: "); tcp53 = socket_tcp6(); if (tcp53 == -1) strerr_die2sys(111,FATAL,"unable to create TCP socket: "); if (socket_bind6_reuse(tcp53,myipincoming,53,interface) == -1) strerr_die2sys(111,FATAL,"unable to bind TCP socket: "); droproot(FATAL); socket_tryreservein(udp53,131072); byte_zero(seed,sizeof seed); read(0,seed,sizeof seed); dns_random_init(seed); close(0); x = env_get("IPSEND"); if (!x) strerr_die2x(111,FATAL,"$IPSEND not set"); if (!ip6_scan(x,myipoutgoing)) strerr_die3x(111,FATAL,"unable to parse IP address ",x); x = env_get("CACHESIZE"); if (!x) strerr_die2x(111,FATAL,"$CACHESIZE not set"); scan_ulong(x,&cachesize); if (!cache_init(cachesize)) strerr_die3x(111,FATAL,"not enough memory for cache of size ",x); if (openreadclose("ignoreip",&sa,64) < 0) strerr_die2x(111,FATAL,"trouble reading ignoreip"); for(j = k = i = 0; i < sa.len; i++) if (sa.s[i] == '\n') { sa.s[i] = '\0'; if (!stralloc_readyplus(&ignoreip,16)) strerr_die2x(111,FATAL,"out of memory parsing ignoreip"); if (!ip6_scan(sa.s+k,ignoreip.s+j)) strerr_die3x(111,FATAL,"unable to parse address in ignoreip ",ignoreip.s+k); j += 16; k = i + 1; } ignoreip.len = j; if (env_get("HIDETTL")) response_hidettl(); if (env_get("FORWARDONLY")) query_forwardonly(); if (!roots_init()) strerr_die2sys(111,FATAL,"unable to read servers: "); if (socket_listen(tcp53,20) == -1) strerr_die2sys(111,FATAL,"unable to listen on TCP socket: "); log_startup(); doit(); }
/*===========================================================================* * cstart * *===========================================================================*/ void cstart() { /* Perform system initializations prior to calling main(). Most settings are * determined with help of the environment strings passed by MINIX' loader. */ register char *value; /* value in key=value pair */ int h; /* low-level initialization */ prot_init(); /* determine verbosity */ if ((value = env_get(VERBOSEBOOTVARNAME))) verboseboot = atoi(value); /* Get clock tick frequency. */ value = env_get("hz"); if(value) system_hz = atoi(value); if(!value || system_hz < 2 || system_hz > 50000) /* sanity check */ system_hz = DEFAULT_HZ; DEBUGEXTRA(("cstart\n")); /* Record miscellaneous information for user-space servers. */ kinfo.nr_procs = NR_PROCS; kinfo.nr_tasks = NR_TASKS; strlcpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release)); strlcpy(kinfo.version, OS_VERSION, sizeof(kinfo.version)); /* Load average data initialization. */ kloadinfo.proc_last_slot = 0; for(h = 0; h < _LOAD_HISTORY; h++) kloadinfo.proc_load_history[h] = 0; #ifdef USE_APIC value = env_get("no_apic"); if(value) config_no_apic = atoi(value); else config_no_apic = 1; value = env_get("apic_timer_x"); if(value) config_apic_timer_x = atoi(value); else config_apic_timer_x = 1; #endif #ifdef USE_WATCHDOG value = env_get("watchdog"); if (value) watchdog_enabled = atoi(value); #endif #ifdef CONFIG_SMP if (config_no_apic) config_no_smp = 1; value = env_get("no_smp"); if(value) config_no_smp = atoi(value); else config_no_smp = 0; #endif DEBUGEXTRA(("intr_init(0)\n")); intr_init(0); arch_init(); }
int main(int argc,char *argv[]) //int argc; //char *argv[]; { int dummy; char *proto; int opt; int flagremoteinfo; unsigned long timeout; // struct sockaddr_in *v4; sig_pipeignore(); flagremoteinfo = 1; timeout = 30; while ((opt = getopt(argc,argv,"rRt:")) != opteof) switch(opt) { case 'r': flagremoteinfo = 1; break; case 'R': flagremoteinfo = 0; break; case 't': scan_ulong(subgetoptarg,&timeout); break; } argv += subgetoptind; argc -= subgetoptind; if (argc < 1) die(); if (!env_init()) die(); proto = env_get("PROTO"); if (!proto || str_diff(proto,"TCP")) { if (!env_puts("PROTO=TCP")) die(); dummy = sizeof(salocal); if (getsockname(0,(struct sockaddr *) &salocal, (socklen_t *) &dummy) == -1) die(); mappedtov4(&salocal); switch(salocal.sa.sa_family) { case AF_INET: localport = ntohs(salocal.sa4.sin_port); temp[fmt_ulong(temp,localport)] = 0; if (!env_put("TCPLOCALPORT",temp)) die(); temp[ip4_fmt(temp,(char *) &salocal.sa4.sin_addr)] = 0; if (!env_put("TCPLOCALIP",temp)) die(); switch(dns_ptr(&localname,&salocal.sa4.sin_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&localname,"softdnserror")) die(); case 0: if (!stralloc_0(&localname)) die(); case_lowers(localname.s); if (!env_put("TCPLOCALHOST",localname.s)) die(); break; default: if (!env_unset("TCPLOCALHOST")) die(); } break; #ifdef INET6 case AF_INET6: localport = ntohs(salocal.sa6.sin6_port); temp[fmt_ulong(temp,localport)] = 0; if (!env_put("TCPLOCALPORT",temp)) die(); temp[ip6_fmt(temp,(char *) &salocal.sa6.sin6_addr)] = 0; if (!env_put("TCPLOCALIP",temp)) die(); switch(dns_ptr6(&localname,&salocal.sa6.sin6_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&localname,"softdnserror")) die(); case 0: if (!stralloc_0(&localname)) die(); case_lowers(localname.s); if (!env_put("TCPLOCALHOST",localname.s)) die(); break; default: if (!env_unset("TCPLOCALHOST")) die(); } break; #endif default: die(); } dummy = sizeof(saremote); if (getpeername(0,(struct sockaddr *) &saremote, (socklen_t *) &dummy) == -1) die(); mappedtov4(&saremote); switch(saremote.sa.sa_family) { case AF_INET: remoteport = ntohs(saremote.sa4.sin_port); temp[fmt_ulong(temp,remoteport)] = 0; if (!env_put("TCPREMOTEPORT",temp)) die(); temp[ip4_fmt(temp,(char *)&saremote.sa4.sin_addr)] = 0; if (!env_put("TCPREMOTEIP",temp)) die(); switch(dns_ptr(&remotename,&saremote.sa4.sin_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&remotename,"softdnserror")) die(); case 0: if (!stralloc_0(&remotename)) die(); case_lowers(remotename.s); if (!env_put("TCPREMOTEHOST",remotename.s)) die(); break; default: if (!env_unset("TCPREMOTEHOST")) die(); } break; #ifdef INET6 case AF_INET6: remoteport = ntohs(saremote.sa6.sin6_port); temp[fmt_ulong(temp,remoteport)] = 0; if (!env_put("TCPREMOTEPORT",temp)) die(); temp[ip6_fmt(temp,(char *) &saremote.sa6.sin6_addr)] = 0; if (!env_put("TCPREMOTEIP",temp)) die(); switch(dns_ptr6(&remotename,&saremote.sa6.sin6_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&remotename,"softdnserror")) die(); case 0: if (!stralloc_0(&remotename)) die(); case_lowers(remotename.s); if (!env_put("TCPREMOTEHOST",remotename.s)) die(); break; default: if (!env_unset("TCPREMOTEHOST")) die(); } break; #endif default: die(); } if (!env_unset("TCPREMOTEINFO")) die(); if (flagremoteinfo) { char *rinfo; rinfo = remoteinfo_get(&saremote, &salocal,(int) timeout); if (rinfo) if (!env_put("TCPREMOTEINFO",rinfo)) die(); } } sig_pipedefault(); execvp(*argv,argv); die(); return(0); /* never reached */ }
int main() { unsigned int pos; char header[12]; char qtype[2]; char qclass[2]; const char *x; droproot(FATAL); dns_random_init(seed); axfr = env_get("AXFR"); x = env_get("TCPREMOTEIP"); if (x && ip6_scan(x,ip)) ; else byte_zero(ip,16); x = env_get("TCPREMOTEPORT"); if (!x) x = "0"; scan_ulong(x,&port); for (;;) { netread(tcpheader,2); uint16_unpack_big(tcpheader,&len); if (len > 512) strerr_die2x(111,FATAL,"excessively large request"); netread(buf,len); pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated(); if (header[2] & 254) strerr_die2x(111,FATAL,"bogus query"); if (header[4] || (header[5] != 1)) strerr_die2x(111,FATAL,"bogus query"); pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated(); zonelen = dns_domain_length(zone); pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated(); pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated(); if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY)) strerr_die2x(111,FATAL,"bogus query: bad class"); pos = check_edns0(header, buf, len, pos); if (!pos) die_truncated(); qlog(ip,port,header,zone,qtype," "); if (byte_equal(qtype,2,DNS_T_AXFR)) { case_lowerb(zone,zonelen); fdcdb = open_read("data.cdb"); if (fdcdb == -1) die_cdbread(); doaxfr(header); close(fdcdb); } else { if (!response_query(zone,qtype,qclass)) nomem(); response[2] |= 4; case_lowerb(zone,zonelen); response_id(header); response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (!respond(zone,qtype,ip)) die_outside(); print(response,response_len); } } }
int spl_load_image_ext_os(struct spl_image_info *spl_image, struct blk_desc *block_dev, int partition) { int err; __maybe_unused loff_t filelen, actlen; disk_partition_t part_info = {}; __maybe_unused char *file; if (part_get_info(block_dev, partition, &part_info)) { printf("spl: no partition table found\n"); return -1; } ext4fs_set_blk_dev(block_dev, &part_info); err = ext4fs_mount(0); if (!err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("%s: ext4fs mount err - %d\n", __func__, err); #endif return -1; } #if defined(CONFIG_SPL_ENV_SUPPORT) file = env_get("falcon_args_file"); if (file) { err = ext4fs_open(file, &filelen); if (err < 0) { puts("spl: ext4fs_open failed\n"); goto defaults; } err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, 0, filelen, &actlen); if (err < 0) { printf("spl: error reading image %s, err - %d, falling back to default\n", file, err); goto defaults; } file = env_get("falcon_image_file"); if (file) { err = spl_load_image_ext(spl_image, block_dev, partition, file); if (err != 0) { puts("spl: falling back to default\n"); goto defaults; } return 0; } else { puts("spl: falcon_image_file not set in environment, falling back to default\n"); } } else { puts("spl: falcon_args_file not set in environment, falling back to default\n"); } defaults: #endif err = ext4fs_open(CONFIG_SPL_FS_LOAD_ARGS_NAME, &filelen); if (err < 0) puts("spl: ext4fs_open failed\n"); err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, 0, filelen, &actlen); if (err < 0) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("%s: error reading image %s, err - %d\n", __func__, CONFIG_SPL_FS_LOAD_ARGS_NAME, err); #endif return -1; } return spl_load_image_ext(spl_image, block_dev, partition, CONFIG_SPL_FS_LOAD_KERNEL_NAME); }
/* Breaks PATH environment variable into list of paths. */ static void split_path_list(void) { const char *path, *p, *q; int i; path = env_get("PATH"); if(paths != NULL) free_string_array(paths, paths_count); paths_count = 1; p = path; while((p = strchr(p, ':')) != NULL) { paths_count++; p++; } paths = malloc(paths_count*sizeof(paths[0])); if(paths == NULL) { paths_count = 0; return; } i = 0; p = path - 1; do { int j; char *s; p++; #ifndef _WIN32 q = strchr(p, ':'); #else q = strchr(p, ';'); #endif if(q == NULL) { q = p + strlen(p); } s = malloc((q - p + 1)*sizeof(s[0])); if(s == NULL) { free_string_array(paths, i - 1); paths = NULL; paths_count = 0; return; } snprintf(s, q - p + 1, "%s", p); p = q; s = expand_tilde(s); /* No need to check "." path for existence. */ if(strcmp(s, ".") != 0) { if(!path_exists(s)) { free(s); continue; } } paths[i++] = s; for(j = 0; j < i - 1; j++) { if(stroscmp(paths[j], s) == 0) { free(s); i--; break; } } } while(q[0] != '\0'); paths_count = i; }
/** * mac_read_from_eeprom - read the MAC addresses from EEPROM * * This function reads the MAC addresses from EEPROM and sets the * appropriate environment variables for each one read. * * The environment variables are only set if they haven't been set already. * This ensures that any user-saved variables are never overwritten. * * This function must be called after relocation. * * For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0 * format. In a v0 EEPROM, there are only eight MAC addresses and the CRC is * located at a different offset. */ int mac_read_from_eeprom(void) { unsigned int i; u32 crc, crc_offset = offsetof(struct eeprom, crc); u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */ puts("EEPROM: "); if (read_eeprom()) { printf("Read failed.\n"); return 0; } if (!is_valid) { printf("Invalid ID (%02x %02x %02x %02x)\n", e.id[0], e.id[1], e.id[2], e.id[3]); return 0; } #ifdef CONFIG_SYS_I2C_EEPROM_NXID /* * If we've read an NXID v0 EEPROM, then we need to set the CRC offset * to where it is in v0. */ if (e.version == 0) crc_offset = 0x72; #endif crc = crc32(0, (void *)&e, crc_offset); crcp = (void *)&e + crc_offset; if (crc != be32_to_cpu(*crcp)) { printf("CRC mismatch (%08x != %08x)\n", crc, be32_to_cpu(e.crc)); return 0; } #ifdef CONFIG_SYS_I2C_EEPROM_NXID /* * MAC address #9 in v1 occupies the same position as the CRC in v0. * Erase it so that it's not mistaken for a MAC address. We'll * update the CRC later. */ if (e.version == 0) memset(e.mac[8], 0xff, 6); #endif for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) { if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) && memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) { char ethaddr[18]; char enetvar[9]; sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", e.mac[i][0], e.mac[i][1], e.mac[i][2], e.mac[i][3], e.mac[i][4], e.mac[i][5]); sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i); /* Only initialize environment variables that are blank * (i.e. have not yet been set) */ if (!env_get(enetvar)) env_set(enetvar, ethaddr); } } #ifdef CONFIG_SYS_I2C_EEPROM_NXID printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], be32_to_cpu(e.version)); #else printf("%c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]); #endif #ifdef CONFIG_SYS_I2C_EEPROM_NXID /* * Now we need to upconvert the data into v1 format. We do this last so * that at boot time, U-Boot will still say "NXID v0". */ if (e.version == 0) { e.version = cpu_to_be32(NXID_VERSION); update_crc(); } #endif return 0; }
int main(int argc, char **argv) { unsigned int i, done; char *x; progname =*argv; for (i =str_len(*argv); i; --i) if ((*argv)[i -1] == '/') break; *argv +=i; optprogname =progname =*argv; service =argv; services =1; lsb =(str_diff(progname, "sv")); if ((x =env_get("SVDIR"))) varservice =x; if ((x =env_get("SVWAIT"))) scan_ulong(x, &wait); while ((i =getopt(argc, (const char* const*)argv, "w:vV")) != opteof) { switch(i) { case 'w': scan_ulong(optarg, &wait); case 'v': verbose =1; break; case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; argc -=optind; if (!(action =*argv++)) usage(); --argc; if (!lsb) { service =argv; services =argc; } if (!*service) usage(); taia_now(&tnow); tstart =tnow; if ((curdir =open_read(".")) == -1) fatal("unable to open current directory"); act =&control; acts ="s"; if (verbose) cbk =✓ switch (*action) { case 'x': case 'e': acts ="x"; break; case 'X': case 'E': acts ="x"; kll =1; cbk =✓ break; case 'D': acts ="d"; kll =1; cbk =✓ break; case 'T': acts ="tc"; kll =1; cbk =✓ break; case 't': if (!str_diff(action, "try-restart")) { acts ="tc"; cbk =✓ break; } case 'c': if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =✓ break; } case 'u': case 'd': case 'o': case 'p': case 'h': case 'a': case 'i': case 'k': case 'q': case '1': case '2': action[1] =0; acts =action; break; case 's': if (!str_diff(action, "shutdown")) { acts ="x"; cbk =✓ break; } if (!str_diff(action, "start")) { acts ="u"; cbk =✓ break; } if (!str_diff(action, "stop")) { acts ="d"; cbk =✓ break; } if (lsb && str_diff(action, "status")) usage(); act =&status; cbk =0; break; case 'r': if (!str_diff(action, "restart")) { acts ="tcu"; cbk =✓ break; } if (!str_diff(action, "reload")) { acts ="h"; cbk =✓ break; } usage(); case 'f': if (!str_diff(action, "force-reload")) { acts ="tc"; kll =1; cbk =✓ break; } if (!str_diff(action, "force-restart")) { acts ="tcu"; kll =1; cbk =✓ break; } if (!str_diff(action, "force-shutdown")) { acts ="x"; kll =1; cbk =✓ break; } if (!str_diff(action, "force-stop")) { acts ="d"; kll =1; cbk =✓ break; } default: usage(); } servicex =service; for (i =0; i < services; ++i) { if ((**service != '/') && (**service != '.') && **service && ((*service)[str_len(*service) -1] != '/')) { if ((chdir(varservice) == -1) || (chdir(*service) == -1)) { fail("unable to change to service directory"); *service =0; } } else if (chdir(*service) == -1) { fail("unable to change to service directory"); *service =0; } if (*service) if (act && (act(acts) == -1)) *service =0; if (fchdir(curdir) == -1) fatal("unable to change to original directory"); service++; } if (*cbk) for (;;) { taia_sub(&tdiff, &tnow, &tstart); service =servicex; done =1; for (i =0; i < services; ++i, ++service) { if (!*service) continue; if ((**service != '/') && (**service != '.')) { if ((chdir(varservice) == -1) || (chdir(*service) == -1)) { fail("unable to change to service directory"); *service =0; } } else if (chdir(*service) == -1) { fail("unable to change to service directory"); *service =0; } if (*service) { if (cbk(acts) != 0) *service =0; else done =0; } if (*service && taia_approx(&tdiff) > wait) { kll ? outs(KILL) : outs(TIMEOUT); if (svstatus_get() > 0) { svstatus_print(*service); ++rc; } flush("\n"); if (kll) control("k"); *service =0; } if (fchdir(curdir) == -1) fatal("unable to change to original directory"); } if (done) break; usleep(420000); taia_now(&tnow); } return(rc > 99 ? 99 : rc); }
int is_old_config(void) { const char *const myvifmrc = env_get(MYVIFMRC_EV); return (myvifmrc != NULL) && is_conf_file(myvifmrc); }
int board_eth_init(bd_t *bis) { int rv; uint8_t mac_addr[6]; uint32_t mac_hi, mac_lo; /* try reading mac address from efuse */ mac_lo = readl(&cdev->macid0l); mac_hi = readl(&cdev->macid0h); mac_addr[0] = mac_hi & 0xFF; mac_addr[1] = (mac_hi & 0xFF00) >> 8; mac_addr[2] = (mac_hi & 0xFF0000) >> 16; mac_addr[3] = (mac_hi & 0xFF000000) >> 24; mac_addr[4] = mac_lo & 0xFF; mac_addr[5] = (mac_lo & 0xFF00) >> 8; if (!env_get("ethaddr")) { puts("<ethaddr> not set. Validating first E-fuse MAC\n"); if (is_valid_ethaddr(mac_addr)) eth_env_set_enetaddr("ethaddr", mac_addr); } mac_lo = readl(&cdev->macid1l); mac_hi = readl(&cdev->macid1h); mac_addr[0] = mac_hi & 0xFF; mac_addr[1] = (mac_hi & 0xFF00) >> 8; mac_addr[2] = (mac_hi & 0xFF0000) >> 16; mac_addr[3] = (mac_hi & 0xFF000000) >> 24; mac_addr[4] = mac_lo & 0xFF; mac_addr[5] = (mac_lo & 0xFF00) >> 8; if (!env_get("eth1addr")) { if (is_valid_ethaddr(mac_addr)) eth_env_set_enetaddr("eth1addr", mac_addr); } if (board_is_eposevm()) { writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE, &cdev->miisel); cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RMII; cpsw_slaves[0].phy_addr = 16; } else if (board_is_sk()) { writel(RGMII_MODE_ENABLE, &cdev->miisel); cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RGMII; cpsw_slaves[0].phy_addr = 4; cpsw_slaves[1].phy_addr = 5; } else if (board_is_idk()) { writel(RGMII_MODE_ENABLE, &cdev->miisel); cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RGMII; cpsw_slaves[0].phy_addr = 0; } else { writel(RGMII_MODE_ENABLE, &cdev->miisel); cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RGMII; cpsw_slaves[0].phy_addr = 0; } rv = cpsw_register(&cpsw_data); if (rv < 0) printf("Error %d registering CPSW switch\n", rv); return rv; }
void ft_board_setup_ex(void *blob, bd_t *bd) { int lpae; u64 size; char *env; u64 *reserve_start; int unitrd_fixup = 0; env = env_get("mem_lpae"); lpae = env && simple_strtol(env, NULL, 0); env = env_get("uinitrd_fixup"); unitrd_fixup = env && simple_strtol(env, NULL, 0); /* Fix up the initrd */ if (lpae && unitrd_fixup) { int nodeoffset; int err; u64 *prop1, *prop2; u64 initrd_start, initrd_end; nodeoffset = fdt_path_offset(blob, "/chosen"); if (nodeoffset >= 0) { prop1 = (u64 *)fdt_getprop(blob, nodeoffset, "linux,initrd-start", NULL); prop2 = (u64 *)fdt_getprop(blob, nodeoffset, "linux,initrd-end", NULL); if (prop1 && prop2) { initrd_start = __be64_to_cpu(*prop1); initrd_start -= CONFIG_SYS_SDRAM_BASE; initrd_start += CONFIG_SYS_LPAE_SDRAM_BASE; initrd_start = __cpu_to_be64(initrd_start); initrd_end = __be64_to_cpu(*prop2); initrd_end -= CONFIG_SYS_SDRAM_BASE; initrd_end += CONFIG_SYS_LPAE_SDRAM_BASE; initrd_end = __cpu_to_be64(initrd_end); err = fdt_delprop(blob, nodeoffset, "linux,initrd-start"); if (err < 0) puts("error deleting initrd-start\n"); err = fdt_delprop(blob, nodeoffset, "linux,initrd-end"); if (err < 0) puts("error deleting initrd-end\n"); err = fdt_setprop(blob, nodeoffset, "linux,initrd-start", &initrd_start, sizeof(initrd_start)); if (err < 0) puts("error adding initrd-start\n"); err = fdt_setprop(blob, nodeoffset, "linux,initrd-end", &initrd_end, sizeof(initrd_end)); if (err < 0) puts("error adding linux,initrd-end\n"); } } } if (lpae) { /* * the initrd and other reserved memory areas are * embedded in in the DTB itslef. fix up these addresses * to 36 bit format */ reserve_start = (u64 *)((char *)blob + fdt_off_mem_rsvmap(blob)); while (1) { *reserve_start = __cpu_to_be64(*reserve_start); size = __cpu_to_be64(*(reserve_start + 1)); if (size) { *reserve_start -= CONFIG_SYS_SDRAM_BASE; *reserve_start += CONFIG_SYS_LPAE_SDRAM_BASE; *reserve_start = __cpu_to_be64(*reserve_start); } else { break; } reserve_start += 2; } } ddr3_check_ecc_int(KS2_DDR3A_EMIF_CTRL_BASE); }
int main (int argc, char *argv[]) { time_t t = 0; char *x = NULL; struct sigaction sa; iopause_fd *iop = NULL; int i = 0, n = 0, *udp53 = NULL; prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); i = check_option (argc, argv); argc -= i; argv += i; if (mode & DAEMON) { i = fork (); if (i == -1) err (-1, "could not fork a daemon process"); if (i > 0) return 0; } time (&t); memset (buf, 0, sizeof (buf)); strftime (buf, sizeof (buf), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting: %s\n", VERSION, buf); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); initialize (); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); #ifndef __CYGWIN__ if ((x = env_get ("DATALIMIT"))) { struct rlimit r; unsigned long dlimit = atol (x); if (getrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not get resource RLIMIT_DATA"); r.rlim_cur = (dlimit <= r.rlim_max) ? dlimit : r.rlim_max; if (setrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not set resource RLIMIT_DATA"); if (debug_level) warnx ("DATALIMIT set to `%ld' bytes", r.rlim_cur); } #endif if (!(x = env_get ("IP"))) err (-1, "$IP not set"); for (i = 0; (unsigned)i < strlen (x); i++) n = (x[i] == ',') ? n+1 : n; if (!(udp53 = calloc (n+1, sizeof (int)))) err (-1, "could not allocate enough memory for udp53"); if (!(iop = calloc (n+1, sizeof (iopause_fd)))) err (-1, "could not allocate enough memory for iop"); i = n = 0; while (x[i]) { unsigned int l = 0; if (!(l = ip4_scan(x+i, ip))) errx (-1, "could not parse IP address `%s'", x + i); udp53[n] = socket_udp(); if (udp53[n] == -1) errx (-1, "could not open UDP socket"); if (socket_bind4_reuse (udp53[n], ip, server_port) == -1) errx (-1, "could not bind UDP socket"); ndelay_off (udp53[n]); socket_tryreservein (udp53[n], 65536); iop[n].fd = udp53[n]; iop[n].events = IOPAUSE_READ; n++; i += (x[i + l] == ',') ? l + 1 : l; } droproot (); while (1) { struct taia stamp; struct in_addr odst; /* original destination IP */ struct taia deadline; taia_now (&stamp); taia_uint (&deadline, 300); taia_add (&deadline, &deadline, &stamp); iopause (iop, n, &deadline, &stamp); for (i = 0; i < n; i++) { if (!iop[i].revents) continue; len = socket_recv4 (udp53[i], buf, sizeof (buf), ip, &port, &odst); if (len < 0) continue; if (!doit ()) continue; if (response_len > 512) response_tc (); /* may block for buffer space; if it fails, too bad */ len = socket_send4 (udp53[i], response, response_len, ip, port, &odst); if (len < 0) continue; if (debug_level > 1) log_querydone(qnum, response, response_len); } } return 0; }
void load_clean_path_env(void) { (void)replace_string(&real_path, env_get("PATH")); env_set("PATH", clean_path); }
static int init(stralloc *rules) { char host[256]; const char *x; int i; int j; int k; if (!stralloc_copys(rules,"")) return -1; x = env_get("DNSREWRITEFILE"); if (!x) x = "/etc/dnsrewrite"; i = openreadclose(x,&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,"\n")) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == '\n') { if (!stralloc_catb(rules,data.s + i,j - i)) return -1; while (rules->len) { if (rules->s[rules->len - 1] != ' ') if (rules->s[rules->len - 1] != '\t') if (rules->s[rules->len - 1] != '\r') break; --rules->len; } if (!stralloc_0(rules)) return -1; i = j + 1; } return 0; } x = env_get("LOCALDOMAIN"); if (x) { if (!stralloc_copys(&data,x)) return -1; if (!stralloc_append(&data," ")) return -1; if (!stralloc_copys(rules,"?:")) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == ' ') { if (!stralloc_cats(rules,"+.")) return -1; if (!stralloc_catb(rules,data.s + i,j - i)) return -1; i = j + 1; } if (!stralloc_0(rules)) return -1; if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; } i = openreadclose("/etc/resolv.conf",&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,"\n")) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == '\n') { if (byte_equal("search ",7,data.s + i) || byte_equal("search\t",7,data.s + i) || byte_equal("domain ",7,data.s + i) || byte_equal("domain\t",7,data.s + i)) { if (!stralloc_copys(rules,"?:")) return -1; i += 7; while (i < j) { k = byte_chr(data.s + i,j - i,' '); k = byte_chr(data.s + i,k,'\t'); if (!k) { ++i; continue; } if (!stralloc_cats(rules,"+.")) return -1; if (!stralloc_catb(rules,data.s + i,k)) return -1; i += k; } if (!stralloc_0(rules)) return -1; if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; } i = j + 1; } } host[0] = 0; if (gethostname(host,sizeof host) == -1) return -1; host[(sizeof host) - 1] = 0; i = str_chr(host,'.'); if (host[i]) { if (!stralloc_copys(rules,"?:")) return -1; if (!stralloc_cats(rules,host + i)) return -1; if (!stralloc_0(rules)) return -1; } if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; }
int main(int argc, char **argv) { int fdfifo, fdfifowrite; char *x; unsigned long id; VERSIONINFO; x = env_get("WORKDIR"); if (!x) strerr_die2x(111, FATAL, "$WORKDIR not set"); if (chdir(x) == -1) strerr_die4sys(111, FATAL, "unable to chdir to ", x, ": "); x = env_get("GID"); if (!x) strerr_die2x(111, FATAL, "$GID not set"); scan_ulong(x,&id); if (prot_gid((int) id) == -1) strerr_die2sys(111, FATAL, "unable to setgid: "); x = env_get("UID"); if (!x) strerr_die2x(111, FATAL, "$UID not set"); scan_ulong(x,&id); /* undocumented feature */ if(id == 0) if(!env_get("IWANTTORUNASROOTANDKNOWWHATIDO")) strerr_die2x(111, FATAL, "unable to run under uid 0: please change $UID"); if (prot_uid((int) id) == -1) strerr_die2sys(111, FATAL, "unable to setuid: "); buffer_putsflush(buffer_2, ARGV0 "starting\n"); if(fifo_make(FIFONAME, 0620) == -1) strerr_warn4(ARGV0, "unable to create fifo ", FIFONAME, " ", &strerr_sys); fdfifo = open_read(FIFONAME); if(fdfifo == -1) strerr_die4sys(111, FATAL, "unable to open for read ", FIFONAME, " "); coe(fdfifo); ndelay_on(fdfifo); /* DJB says: shouldn't be necessary */ /* we need this to keep the fifo from beeing closed */ fdfifowrite = open_write(FIFONAME); if (fdfifowrite == -1) strerr_die4sys(111, FATAL, "unable to open for write ", FIFONAME, " "); coe(fdfifowrite); /* init a buffer for nonblocking reading */ buffer_init(&wr, waitread, fdfifo, waitreadspace, sizeof waitreadspace); t = dAVLAllocTree(); /* read snapshot of dnsdatatree */ fill_db(); /* SIGALRM can be used to check if dumping the database is needed */ sig_catch(sig_alarm, sigalrm); /* SIGHUP can be used to force dumping the database */ sig_catch(sig_hangup, sighup); /* check if out child is done */ sig_catch(sig_child, sigchld); // XXX SIGINT, SIGTERM, /* do our normal workloop */ doit(); /* we shouldn't get here */ return 1; }
/* 1> open shm 2> init pub 3> update activesys 4> on_app_start 11>init core funtion 12>update core function 13>init function list 5> start local server 6> proccess request */ int main(int argc,char **argv){ char *p; int intMaxShmSize; int intShmKey; msasPubInfo *ltPubInfo; lt_shmHead *lt_MMHead; signal(SIGHUP,resetcatch_hup); signal(SIGCHLD, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); pubconfdir=NULL; pubconfdir= env_get("RUNCONFDIR"); if(!pubconfdir){ pubconfdir="/etc/msa/msas1"; } /*读取最大共享内存数*/ p=bcCnfGetValueS(pubconfdir,"kernel", "maxshmsize"); if(p==NULL){ fprintf(stderr,"Start applicatin error: maxshmsize is NULL!\n"); die(51); } intMaxShmSize=atol(p); /*读取系统shmKey*/ p=bcCnfGetValueS(pubconfdir,"kernel", "shmkey"); if(p==NULL){ fprintf(stderr,"Start applicatin error: shmkey is NULL!\n"); die(52); } intShmKey=atol(p); lt_MMHead=msasopenShmMem(intShmKey,intMaxShmSize); if(lt_MMHead==NULL){ fprintf(stderr,"can open share memory!\n"); die(53); } ltPubInfo=(msasPubInfo *)lt_MMHead->ShmMemPtr; if(ltPubInfo == NULL) { fprintf(stderr,"can open share memory pubinfo!\n"); die(54); } msasInitPubVar(lt_MMHead); /*加入其他执行程序*/ lt_start_simple_server(lt_MMHead,pubconfdir,on_app,on_proc,on_proc_stop); return 0; }
static int tokenize_command(const char *inbuffer, const char **continuebuffer, char *buffer, size_t buflen, cmd_args *args, int arg_count) { int inpos; int outpos; int arg; enum { INITIAL = 0, NEXT_FIELD, SPACE, IN_SPACE, TOKEN, IN_TOKEN, QUOTED_TOKEN, IN_QUOTED_TOKEN, VAR, IN_VAR, COMMAND_SEP, } state; char varname[128]; int varnamepos; inpos = 0; outpos = 0; arg = 0; varnamepos = 0; state = INITIAL; *continuebuffer = NULL; for (;;) { char c = inbuffer[inpos]; // dprintf(SPEW, "c 0x%hhx state %d arg %d inpos %d pos %d\n", c, state, arg, inpos, outpos); switch (state) { case INITIAL: case NEXT_FIELD: if (c == '\0') goto done; if (isspace(c)) state = SPACE; else if (c == ';') state = COMMAND_SEP; else state = TOKEN; break; case SPACE: state = IN_SPACE; break; case IN_SPACE: if (c == '\0') goto done; if (c == ';') { state = COMMAND_SEP; } else if (!isspace(c)) { state = TOKEN; } else { inpos++; // consume the space } break; case TOKEN: // start of a token DEBUG_ASSERT(c != '\0'); if (c == '"') { // start of a quoted token state = QUOTED_TOKEN; } else if (c == '$') { // start of a variable state = VAR; } else { // regular, unquoted token state = IN_TOKEN; args[arg].str = &buffer[outpos]; } break; case IN_TOKEN: if (c == '\0') { arg++; goto done; } if (isspace(c) || c == ';') { arg++; buffer[outpos] = 0; outpos++; /* are we out of tokens? */ if (arg == arg_count) goto done; state = NEXT_FIELD; } else { buffer[outpos] = c; outpos++; inpos++; } break; case QUOTED_TOKEN: // start of a quoted token DEBUG_ASSERT(c == '"'); state = IN_QUOTED_TOKEN; args[arg].str = &buffer[outpos]; inpos++; // consume the quote break; case IN_QUOTED_TOKEN: if (c == '\0') { arg++; goto done; } if (c == '"') { arg++; buffer[outpos] = 0; outpos++; /* are we out of tokens? */ if (arg == arg_count) goto done; state = NEXT_FIELD; } buffer[outpos] = c; outpos++; inpos++; break; case VAR: DEBUG_ASSERT(c == '$'); state = IN_VAR; args[arg].str = &buffer[outpos]; inpos++; // consume the dollar sign // initialize the place to store the variable name varnamepos = 0; break; case IN_VAR: if (c == '\0' || isspace(c) || c == ';') { // hit the end of variable, look it up and stick it inline varname[varnamepos] = 0; #if WITH_LIB_ENV int rc = env_get(varname, &buffer[outpos], buflen - outpos); #else int rc = -1; #endif if (rc < 0) { buffer[outpos++] = '0'; buffer[outpos++] = 0; } else { outpos += strlen(&buffer[outpos]) + 1; } arg++; /* are we out of tokens? */ if (arg == arg_count) goto done; state = NEXT_FIELD; } else { varname[varnamepos] = c; varnamepos++; inpos++; } break; case COMMAND_SEP: // we hit a ;, so terminate the command and pass the remainder of the command back in continuebuffer DEBUG_ASSERT(c == ';'); inpos++; // consume the ';' *continuebuffer = &inbuffer[inpos]; goto done; } } done: buffer[outpos] = 0; return arg; }
static void find_jobs(time_t vtime, cron_db *db, int doWild, int doNonWild) { time_t virtualSecond = vtime * SECONDS_PER_MINUTE; struct tm *tm; int minute, hour, dom, month, dow; user *u; entry *e; #ifndef CRON_LOCALTIME char *orig_tz, *job_tz; #define maketime(tz1, tz2) do { \ char *t = tz1; \ if (t != NULL && *t != '\0') \ setenv("TZ", t, 1); \ else if ((tz2) != NULL) \ setenv("TZ", (tz2), 1); \ else \ unsetenv("TZ"); \ tzset(); \ tm = localtime(&virtualSecond); \ minute = tm->tm_min -FIRST_MINUTE; \ hour = tm->tm_hour -FIRST_HOUR; \ dom = tm->tm_mday -FIRST_DOM; \ month = tm->tm_mon + 1 /* 0..11 -> 1..12 */ -FIRST_MONTH; \ dow = tm->tm_wday -FIRST_DOW; \ } while (/*CONSTCOND*/0) orig_tz = getenv("TZ"); maketime(NULL, orig_tz); #else tm = gmtime(&virtualSecond); #endif Debug(DSCH, ("[%ld] tick(%d,%d,%d,%d,%d) %s %s\n", (long)getpid(), minute, hour, dom, month, dow, doWild?" ":"No wildcard",doNonWild?" ":"Wildcard only")); /* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the * first and fifteenth AND every Sunday; '* * * * Sun' will run *only* * on Sundays; '* * 1,15 * *' will run *only* the 1st and 15th. this * is why we keep 'e->dow_star' and 'e->dom_star'. yes, it's bizarre. * like many bizarre things, it's the standard. */ for (u = db->head; u != NULL; u = u->next) { for (e = u->crontab; e != NULL; e = e->next) { #ifndef CRON_LOCALTIME job_tz = env_get("CRON_TZ", e->envp); maketime(job_tz, orig_tz); #else #define job_tz "N/A" #define orig_tz "N/A" #endif Debug(DSCH|DEXT, ("user [%s:%ld:%ld:...] " "[jobtz=%s, origtz=%s] " "tick(%s), cmd=\"%s\"\n", e->pwd->pw_name, (long)e->pwd->pw_uid, (long)e->pwd->pw_gid, job_tz, orig_tz, tick(e), e->cmd)); if (bit_test(e->minute, minute) && bit_test(e->hour, hour) && bit_test(e->month, month) && ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR)) ? (bit_test(e->dow,dow) && bit_test(e->dom,dom)) : (bit_test(e->dow,dow) || bit_test(e->dom,dom)) ) ) { if ((doNonWild && !(e->flags & (MIN_STAR|HR_STAR))) || (doWild && (e->flags & (MIN_STAR|HR_STAR)))) job_add(e, u, StartTime); } } } #ifndef CRON_LOCALTIME if (orig_tz != NULL) setenv("TZ", orig_tz, 1); else unsetenv("TZ"); #endif }
/* i8042_kbd_init - reset keyboard and init state flags */ static int i8042_start(struct udevice *dev) { struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev); struct i8042_kbd_priv *priv = dev_get_priv(dev); struct input_config *input = &uc_priv->input; int keymap, try; char *penv; int ret; if (!kbd_controller_present() || board_i8042_skip()) { debug("i8042 keyboard controller is not present\n"); return -ENOENT; } /* Init keyboard device (default US layout) */ keymap = KBD_US; penv = env_get("keymap"); if (penv != NULL) { if (strncmp(penv, "de", 3) == 0) keymap = KBD_GER; } for (try = 0; kbd_reset(priv->quirks) != 0; try++) { if (try >= KBD_RESET_TRIES) return -1; } ret = input_add_tables(input, keymap == KBD_GER); if (ret) return ret; i8042_kbd_update_leds(dev, NORMAL); debug("%s: started\n", __func__); return 0; } /** * Set up the i8042 keyboard. This is called by the stdio device handler * * We want to do this init when the keyboard is actually used rather than * at start-up, since keyboard input may not currently be selected. * * Once the keyboard starts there will be a period during which we must * wait for the keyboard to init. We do this only when a key is first * read - see kbd_wait_for_fifo_init(). * * @return 0 if ok, -ve on error */ static int i8042_kbd_probe(struct udevice *dev) { struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev); struct i8042_kbd_priv *priv = dev_get_priv(dev); struct stdio_dev *sdev = &uc_priv->sdev; struct input_config *input = &uc_priv->input; int ret; if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), "intel,duplicate-por")) priv->quirks |= QUIRK_DUP_POR; /* Register the device. i8042_start() will be called soon */ input->dev = dev; input->read_keys = i8042_kbd_check; input_allow_repeats(input, true); strcpy(sdev->name, "i8042-kbd"); ret = input_stdio_register(sdev); if (ret) { debug("%s: input_stdio_register() failed\n", __func__); return ret; } debug("%s: ready\n", __func__); return 0; } static const struct keyboard_ops i8042_kbd_ops = { .start = i8042_start, .update_leds = i8042_kbd_update_leds, }; static const struct udevice_id i8042_kbd_ids[] = { { .compatible = "intel,i8042-keyboard" }, { } };
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) { /* First parameter is mapped to $r5 for kernel boot args */ void (*thekernel) (char *, ulong, ulong); char *commandline = env_get("bootargs"); ulong rd_data_start, rd_data_end; /* * allow the PREP bootm subcommand, it is required for bootm to work */ if (flag & BOOTM_STATE_OS_PREP) return 0; if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1; int ret; char *of_flat_tree = NULL; #if defined(CONFIG_OF_LIBFDT) /* did generic code already find a device tree? */ if (images->ft_len) of_flat_tree = images->ft_addr; #endif thekernel = (void (*)(char *, ulong, ulong))images->ep; /* find ramdisk */ ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_MICROBLAZE, &rd_data_start, &rd_data_end); if (ret) return 1; bootstage_mark(BOOTSTAGE_ID_RUN_OS); if (!of_flat_tree && argc > 1) of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16); /* fixup the initrd now that we know where it should be */ if (images->rd_start && images->rd_end && of_flat_tree) { ret = fdt_initrd(of_flat_tree, images->rd_start, images->rd_end); if (ret) return 1; } #ifdef DEBUG printf("## Transferring control to Linux (at address 0x%08lx) ", (ulong)thekernel); printf("ramdisk 0x%08lx, FDT 0x%08lx...\n", rd_data_start, (ulong) of_flat_tree); #endif #ifdef XILINX_USE_DCACHE flush_cache(0, XILINX_DCACHE_BYTE_SIZE); #endif /* * Linux Kernel Parameters (passing device tree): * r5: pointer to command line * r6: pointer to ramdisk * r7: pointer to the fdt, followed by the board info data */ thekernel(commandline, rd_data_start, (ulong)of_flat_tree); /* does not return */ return 1; }
/** * Abbreviations: fp = frame pointer, ip = instruction pointer * * Frame layout on stack: * fp => compiled lambda that is currently executed * fp + 1 => args * fp + 1 + arg_count => vars * fp + 1 + arg_count + var_count => saved fp and ip indices (atom of type T_INTERPRETER_STATE) * * fp and ip are saved as indices. fp is an stack index and ip is the index into the bytecode * of the previously executed compiled lambda. This allows the stack and previous lambda * to be moved in memory. Important for the stack since it can grow (and be reallocated * while dooing so). The compiled lambda atom might move due to a future garbage collector. */ atom_t* bci_eval(bytecode_interpreter_t interp, atom_t* rl, atom_t *args, env_t *env){ // The variables used by the interpreter to refer to the current context size_t frame_index, arg_count; instruction_t *ip; scope_p frame_scope = NULL; // allocated when the first lambda is built uint8_t scope_escaped = false; // Build the initial stack frame and context variables assert(rl->type == T_RUNTIME_LAMBDA); frame_index = interp->stack->length; stack_push(&interp->stack, rl); arg_count = 0; for(atom_t *atom = args; atom->type == T_PAIR; atom = atom->rest){ stack_push(&interp->stack, atom->first); arg_count++; } if (arg_count != rl->cl->comp_data->arg_count){ warn("Not enough arguments for function! Got %d, required %d", arg_count, rl->cl->comp_data->arg_count); return nil_atom(); } stack_push_n(&interp->stack, nil_atom(), rl->cl->comp_data->var_count); stack_push(&interp->stack, nil_atom()); ip = rl->cl->bytecode.code; inline void check_atom_for_escaped_scope(atom_t *subject){ if (frame_scope == NULL || scope_escaped == true) return; switch(subject->type){ case T_PAIR: check_atom_for_escaped_scope(subject->first); check_atom_for_escaped_scope(subject->rest); break; case T_RUNTIME_LAMBDA: for (scope_p s = subject->scopes; s != NULL; s = s->next){ if (s == frame_scope){ scope_escaped = true; return; } } break; default: // Other atoms don't need to be checked (can't contain scope references) break; } } while(true){ switch(ip->op){ case BC_LOAD_NIL: stack_push(&interp->stack, nil_atom()); break; case BC_LOAD_TRUE: stack_push(&interp->stack, true_atom()); break; case BC_LOAD_FALSE: stack_push(&interp->stack, false_atom()); break; case BC_LOAD_NUM: stack_push(&interp->stack, num_atom_alloc(ip->num)); break; case BC_LOAD_LITERAL: case BC_LOAD_LAMBDA: { scope_t this_scope = (scope_t){ .next = rl->scopes, .type = SCOPE_STACK, .arg_count = arg_count, .frame_index = frame_index}; scope_p target_scope = &this_scope; for(uint16_t scope_offset = ip->offset; scope_offset > 0; scope_offset--) target_scope = target_scope->next; assert(target_scope->type != SCOPE_ENV); atom_t **frame_pointer = NULL; if (target_scope->type == SCOPE_STACK) frame_pointer = interp->stack->atoms + target_scope->frame_index; else frame_pointer = target_scope->atoms; assert(frame_pointer[0]->type == T_RUNTIME_LAMBDA); atom_t *target_cl = frame_pointer[0]->cl; assert(ip->index < target_cl->literal_table.length); if (ip->op == BC_LOAD_LITERAL) { assert(target_cl->literal_table.atoms[ip->index]->type != T_COMPILED_LAMBDA); stack_push(&interp->stack, target_cl->literal_table.atoms[ip->index]); } else { atom_t *compiled_lambda = target_cl->literal_table.atoms[ip->index]; assert(compiled_lambda->type == T_COMPILED_LAMBDA); if (frame_scope == NULL) frame_scope = scope_stack_alloc(rl->scopes, arg_count, frame_index); atom_t *new_rl = runtime_lambda_atom_alloc(compiled_lambda, frame_scope); stack_push(&interp->stack, new_rl); } } break; case BC_LOAD_ARG: case BC_LOAD_LOCAL: case BC_STORE_LOCAL: { scope_t this_scope = (scope_t){ .next = rl->scopes, .type = SCOPE_STACK, .arg_count = arg_count, .frame_index = frame_index}; scope_p target_scope = &this_scope; for(uint16_t scope_offset = ip->offset; scope_offset > 0; scope_offset--) target_scope = target_scope->next; assert(target_scope->type != SCOPE_ENV); atom_t **frame_pointer = NULL; if (target_scope->type == SCOPE_STACK) frame_pointer = interp->stack->atoms + target_scope->frame_index; else frame_pointer = target_scope->atoms; switch(ip->op){ case BC_LOAD_ARG: assert(ip->index < target_scope->arg_count); stack_push(&interp->stack, frame_pointer[ip->index+1]); break; case BC_LOAD_LOCAL: assert(frame_pointer[0]->type == T_RUNTIME_LAMBDA && ip->index < frame_pointer[0]->cl->comp_data->var_count); stack_push(&interp->stack, frame_pointer[target_scope->arg_count + ip->index+1]); break; case BC_STORE_LOCAL: { assert(frame_pointer[0]->type == T_RUNTIME_LAMBDA && ip->index < frame_pointer[0]->cl->comp_data->var_count); atom_t *value = stack_peek(&interp->stack); if (ip->offset > 0) // no need to check if we store the atom in our own stack frame check_atom_for_escaped_scope(value); frame_pointer[target_scope->arg_count + ip->index+1] = value; }break; } } break; case BC_LOAD_ENV: case BC_STORE_ENV: { // First loop though the scope chain to get the definition env scope_p target_scope = rl->scopes; while(target_scope->next != NULL) target_scope = target_scope->next; assert(target_scope->type == SCOPE_ENV); env_t *target_env = target_scope->env; // Pop the key symbol assert(ip->index < rl->cl->literal_table.length); atom_t *key = rl->cl->literal_table.atoms[ip->index]; assert(key->type == T_SYM); if (ip->op == BC_LOAD_ENV) { atom_t *value = env_get(target_env, key->sym); if (value != NULL) { stack_push(&interp->stack, value); } else { warn("BC_LOAD_ENV: no binding for %s in env %p", key->sym, target_env); stack_push(&interp->stack, nil_atom()); } } else { atom_t *value = stack_peek(&interp->stack); check_atom_for_escaped_scope(value); env_set(target_env, key->sym, value); } } break; case BC_DROP: stack_pop(&interp->stack); break; case BC_JUMP: ip += ip->jump_offset; break; case BC_JUMP_IF_FALSE: if (stack_pop(&interp->stack) == false_atom()) ip += ip->jump_offset; break; case BC_CALL: { uint16_t call_arg_count = ip->num; atom_t *func = interp->stack->atoms[interp->stack->length - 1 - call_arg_count]; // length - 1 => last arg, - call_arg_count => func switch (func->type) { case T_RUNTIME_LAMBDA: { // Continue to use the stack atom_t *saved_state = interpreter_state_atom_alloc(frame_index, ip - rl->cl->bytecode.code, arg_count, scope_escaped, frame_scope); arg_count = call_arg_count; // TODO: check if argument count on stack match the required argument count of the compiled lambda frame_index = interp->stack->length - 1 - call_arg_count; // length - 1 => last arg, - call_arg_count => func rl = func; ip = rl->cl->bytecode.code; frame_scope = NULL; scope_escaped = false; stack_push_n(&interp->stack, nil_atom(), rl->cl->comp_data->var_count); stack_push(&interp->stack, saved_state); // Restart the outer while loop because we don't want to increment the instruction pointer (ip). Otherwise we would miss // the first instruction of the new compiled lambda. continue; } break; case T_BUILDIN: { // Build a pair argument list of the args and pop them from the stack while we're at it atom_t *arg_atoms = nil_atom(); for(size_t i = 0; i < call_arg_count; i++) arg_atoms = pair_atom_alloc(stack_pop(&interp->stack), arg_atoms); // Pop the func from the stack atom_t *popped_func = stack_pop(&interp->stack); assert(func == popped_func); // Let the buildin create the result. Pass the env of the bytecode interpreter since this is the best aproximation we have right now. atom_t *result = func->func(arg_atoms, env); stack_push(&interp->stack, result); } break; case T_LAMBDA: { // Create a new env with the unevaled args in it (the args on the stack have already been evaled by the compiled bytecode) env_t *lambda_env = env_alloc(func->env); // Build a pair argument list of the args and pop them from the stack while we're at it atom_t *arg_atoms = nil_atom(); for(size_t i = 0; i < call_arg_count; i++) arg_atoms = pair_atom_alloc(stack_pop(&interp->stack), arg_atoms); // Bind lambda args atom_t *arg_name_pair = func->args, *arg_value_pair = arg_atoms; while(arg_name_pair->type == T_PAIR && arg_value_pair->type == T_PAIR){ env_def(lambda_env, arg_name_pair->first->sym, arg_value_pair->first); arg_name_pair = arg_name_pair->rest; arg_value_pair = arg_value_pair->rest; } // Pop the func from the stack atom_t *popped_func = stack_pop(&interp->stack); assert(func == popped_func); atom_t *result = eval_atom(func->body, lambda_env); stack_push(&interp->stack, result); } break; default: // Not sure what to do with T_CUSTOM in general. For the other atoms: they should never arrive here. assert(0); break; } } break; case BC_RETURN: { atom_t *return_value = stack_pop(&interp->stack); // TODO: Make sure to revert to the start frame_index here. Right now we're done for if a function does // not pop as many values as it pushes (in all brances). atom_t *state = stack_pop(&interp->stack); // Search the return value for an escaped scope if necessary check_atom_for_escaped_scope(return_value); // Capture the scope if it escaped if (scope_escaped){ size_t frame_size = (1 + arg_count + rl->cl->comp_data->var_count) * sizeof(atom_t*); frame_scope->type = SCOPE_HEAP; // The GC will free the frame when it's no longer needed frame_scope->atoms = gc_alloc(frame_size); memcpy(frame_scope->atoms, interp->stack->atoms + frame_index, frame_size); } // Pop the arguments, variables and the compiled lambda stack_pop_n(&interp->stack, arg_count + rl->cl->comp_data->var_count + 1); if (state->type == T_INTERPRETER_STATE) { arg_count = state->interpreter_state.arg_count; frame_index = state->interpreter_state.fp_index; rl = interp->stack->atoms[frame_index]; ip = rl->cl->bytecode.code + state->interpreter_state.ip_index; frame_scope = state->interpreter_state.frame_scope; scope_escaped = state->interpreter_state.scope_escaped; stack_push(&interp->stack, return_value); } else { return return_value; } } break; case BC_ADD: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); assert(a->type == T_NUM && b->type == T_NUM); stack_push(&interp->stack, num_atom_alloc(a->num + b->num)); } break; case BC_SUB: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); assert(a->type == T_NUM && b->type == T_NUM); stack_push(&interp->stack, num_atom_alloc(a->num - b->num)); } break; case BC_MUL: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); assert(a->type == T_NUM && b->type == T_NUM); stack_push(&interp->stack, num_atom_alloc(a->num * b->num)); } break; case BC_DIV: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); assert(a->type == T_NUM && b->type == T_NUM); stack_push(&interp->stack, num_atom_alloc(a->num / b->num)); } break; case BC_MOD: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); assert(a->type == T_NUM && b->type == T_NUM); stack_push(&interp->stack, num_atom_alloc(a->num % b->num)); } break; case BC_EQ: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); atom_t *result = false_atom(); if (a->type == b->type) { switch(a->type){ case T_NUM: if (a->num == b->num) result = true_atom(); break; default: assert(0); break; } } stack_push(&interp->stack, result); } break; case BC_LT: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); atom_t *result = false_atom(); if (a->type == b->type) { switch(a->type){ case T_NUM: if (a->num < b->num) result = true_atom(); break; default: assert(0); break; } } stack_push(&interp->stack, result); } break; case BC_GT: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); atom_t *result = false_atom(); if (a->type == b->type) { switch(a->type){ case T_NUM: if (a->num > b->num) result = true_atom(); break; default: assert(0); break; } } stack_push(&interp->stack, result); } break; case BC_CONS: { atom_t *b = stack_pop(&interp->stack); atom_t *a = stack_pop(&interp->stack); stack_push(&interp->stack, pair_atom_alloc(a, b)); } break; case BC_FIRST: { atom_t *pair = stack_pop(&interp->stack); assert(pair->type == T_PAIR); stack_push(&interp->stack, pair->first); } break; case BC_REST: { atom_t *pair = stack_pop(&interp->stack); assert(pair->type == T_PAIR); stack_push(&interp->stack, pair->rest); } break; default: // Unknown bytecode instruction assert(false); } ip++; assert(ip < rl->cl->bytecode.code + rl->cl->bytecode.length); } return nil_atom(); }