void NNTPListGroup(Connection *conn, char **pptr) { char *group; const char *rec; int recLen; OverInfo *ov; if ((group = parseword(pptr, " \t")) != NULL && strlen(group) < MAXGNAME) SetCurrentGroup(conn, group); if (conn->co_GroupName && (ov = GetOverInfo(conn->co_GroupName)) != NULL) { if ((rec = KPDBReadRecord(KDBActive, conn->co_GroupName, KP_LOCK, &recLen)) != NULL) { conn->co_ListBegNo = strtoll(KPDBGetField(rec, recLen, "NB", NULL, "0"), NULL, 10); conn->co_ListEndNo = strtoll(KPDBGetField(rec, recLen, "NE", NULL, "0"), NULL, 10) + 1; KPDBUnlock(KDBActive, rec); if (conn->co_ListEndNo - conn->co_ListBegNo > ov->ov_Head->oh_MaxArts) conn->co_ListBegNo = conn->co_ListEndNo - ov->ov_Head->oh_MaxArts; MBLogPrintf(conn, &conn->co_TMBuf, "211 Article list follows\r\n"); NNListGroup(conn); } else { MBLogPrintf(conn, &conn->co_TMBuf, "411 No such group %s\r\n", conn->co_GroupName); NNCommand(conn); } PutOverInfo(ov); } else { MBLogPrintf(conn, &conn->co_TMBuf, "481 No group specified\r\n"); NNCommand(conn); } }
main() { int c; while ((c = getch()) != EOF) { if (c == '#') /* directive */ { if (definedirective() == EOF) return; } else if (c == '/') { if (printcomment() == EOF) return; } else if (c == '\"') { if (printquote() == EOF) return; } else if (isspace(c)) putchar(c); else { ungetch(c); if (parseword() == EOF) return; } } }
void NNTPXGTitle(Connection *conn, char **pptr) { const char *wc = NULL; if (pptr) wc = parseword(pptr, " \t"); /* may also be NULL */ MBLogPrintf(conn, &conn->co_TMBuf, "282 list follows\r\n"); NNStartListActiveScan(conn, wc, NULL, COM_GROUPDESC); }
void NNTPListNewsgroups(Connection *conn, char **pptr) { const char *wc = NULL; if (pptr) wc = parseword(pptr, " \t"); /* may also be NULL */ MBLogPrintf(conn, &conn->co_TMBuf, "215 descriptions in form \"group description\"\r\n"); NNStartListActiveScan(conn, wc, NULL, COM_GROUPDESC); }
void NNTPNewgroups(Connection *conn, char **pptr) { const char *yymmdd = NULL; const char *hhmmss = NULL; const char *gmt = NULL; TimeRestrict tr; if (pptr) { yymmdd = parseword(pptr, " \t"); hhmmss = parseword(pptr, " \t"); gmt = parseword(pptr, " \t"); } if (SetTimeRestrict(&tr, yymmdd, hhmmss, gmt) < 0) { MBLogPrintf(conn, &conn->co_TMBuf, "501 yymmdd hhmmss [\"GMT\"] [<distributions>]\r\n"); NNCommand(conn); } else { MBLogPrintf(conn, &conn->co_TMBuf, "231 New newsgroups follow.\r\n"); NNStartListActiveScan(conn, "*", &tr, COM_NEWGROUPS); } }
void NNTPListActive(Connection *conn, char **pptr) { const char *wc = NULL; if (pptr) wc = parseword(pptr, " \t"); /* may also be NULL */ else wc = "*"; MBLogPrintf(conn, &conn->co_TMBuf, "215 Newsgroups in form \"group high low flags\".\r\n"); NNStartListActiveScan(conn, wc, NULL, COM_ACTIVE); }
u_int sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh) { int devtype; u_int romend; devtype = bus_space_read_1(memt, romh, 3); if (devtype == STI_DEVTYPE4) { bus_space_read_raw_region_4(memt, romh, 0x18, (u_int8_t *)&romend, 4); } else { romend = parseword(0x50); } return (round_page(romend)); }
void NNTPList(Connection *conn, char **pptr) { /* * list active [groupwild] * list active.times * list newsgroups [groupwild] * list extensions * list distributions * list distrib.pats * list overview.fmt * list subscriptions * list moderators */ char *ltype = parseword(pptr, " \t"); if (ltype) { int i; for (i = 0; ltype[i]; ++i) ltype[i] = tolower((int)(unsigned char)ltype[i]); } if (ltype == NULL) { NNTPListActive(conn, NULL); } else if (strcmp(ltype, "active") == 0) { NNTPListActive(conn, pptr); } else if (strcmp(ltype, "active.times") == 0) { NNTPListActiveTimes(conn, pptr); } else if (strcmp(ltype, "newsgroups") == 0) { NNTPListNewsgroups(conn, pptr); } else if (strcmp(ltype, "extensions") == 0) { NNTPListExtensions(conn, pptr); } else if (strcmp(ltype, "distributions") == 0) { NNTPListDistributions(conn, pptr); } else if (strcmp(ltype, "distrib.pats") == 0) { NNTPListDistribPats(conn, pptr); } else if (strcmp(ltype, "overview.fmt") == 0) { NNTPListOverviewFmt(conn, pptr); } else if (strcmp(ltype, "subscriptions") == 0) { NNTPListSubscriptions(conn, pptr); } else if (strcmp(ltype, "moderators") == 0) { NNTPListModerators(conn, pptr); } else { NNBadCommandUse(conn); } }
u_int sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh) { int devtype; u_int romend; devtype = bus_space_read_1(memt, romh, 3); if (devtype == STI_DEVTYPE4) { bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND, (uint32_t *)&romend, 1); } else { romend = parseword(STI_DEV1_DD_ROMEND); } DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend))); return round_page(romend); }
int sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg, uint32_t baseaddr, u_int fontindex) { struct sti_rom *rom = scr->scr_rom; bus_space_tag_t memt = rom->memt; bus_space_handle_t romh = rom->romh; struct sti_font *fp = &scr->scr_curfont; uint32_t addr; int size; #ifdef notyet int uc; struct { struct sti_unpmvflags flags; struct sti_unpmvin in; struct sti_unpmvout out; } a; #endif /* * Get the first PROM font in memory */ STI_ENABLE_ROM(rom->rom_softc); rescan: addr = baseaddr; do { if (rom->rom_devtype == STI_DEVTYPE1) { fp->first = parseshort(addr + 0x00); fp->last = parseshort(addr + 0x08); fp->width = bus_space_read_1(memt, romh, addr + 0x13); fp->height = bus_space_read_1(memt, romh, addr + 0x17); fp->type = bus_space_read_1(memt, romh, addr + 0x1b); fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f); fp->next = parseword(addr + 0x20); fp->uheight= bus_space_read_1(memt, romh, addr + 0x33); fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37); } else { /* STI_DEVTYPE4 */ bus_space_read_region_stream_4(memt, romh, addr, (uint32_t *)fp, sizeof(struct sti_font) / 4); } #ifdef STIDEBUG STI_DISABLE_ROM(rom->rom_softc); DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width, fp->height, fp->type, fp->bpc, fp->first, fp->last)); STI_ENABLE_ROM(rom->rom_softc); #endif if (fontindex == 0) { size = sizeof(struct sti_font) + (fp->last - fp->first + 1) * fp->bpc; if (rom->rom_devtype == STI_DEVTYPE1) size *= 4; scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT); if (scr->scr_romfont == NULL) return ENOMEM; bus_space_read_region_stream_4(memt, romh, addr, (uint32_t *)scr->scr_romfont, size / 4); break; } addr = baseaddr + fp->next; fontindex--; } while (fp->next != 0); /* * If our font index was bogus, we did not find the expected font. * In this case, pick the first one and be done with it. */ if (fp->next == 0 && scr->scr_romfont == NULL) { fontindex = 0; goto rescan; } STI_DISABLE_ROM(rom->rom_softc); #ifdef notyet /* * If there is enough room in the off-screen framebuffer memory, * display all the characters there in order to display them * faster with blkmv operations rather than unpmv later on. */ if (size <= cfg->fbheight * (cfg->fbwidth - cfg->width - cfg->owidth)) { memset(&a, 0, sizeof(a)); a.flags.flags = STI_UNPMVF_WAIT; a.in.fg_colour = STI_COLOUR_WHITE; a.in.bg_colour = STI_COLOUR_BLACK; a.in.font_addr = scr->scr_romfont; scr->scr_fontmaxcol = cfg->fbheight / fp->height; scr->scr_fontbase = cfg->width + cfg->owidth; for (uc = fp->first; uc <= fp->last; uc++) { a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) * fp->width + scr->scr_fontbase; a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) * fp->height; a.in.index = uc; (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); if (a.out.errno) { aprint_error_dev(sc->sc_dev, "unpmv %d " "returned %d\n", uc, a.out.errno); return 0; } } free(scr->scr_romfont, M_DEVBUF); scr->scr_romfont = NULL; } #endif return 0; }
int sti_screen_setup(struct sti_screen *scr, int flags) { struct sti_rom *rom = scr->scr_rom; bus_space_tag_t memt = rom->memt; bus_space_handle_t romh = rom->romh; struct sti_dd *dd = &rom->rom_dd; struct sti_cfg *cc = &scr->scr_cfg; struct sti_inqconfout cfg; struct sti_einqconfout ecfg; #ifdef STIDEBUG char buf[256]; #endif int error, i; int geometry_kluge = 0; u_int fontindex = 0; KASSERT(scr != NULL); memset(cc, 0, sizeof(*cc)); cc->ext_cfg = &scr->scr_ecfg; memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg)); if (dd->dd_stimemreq) { scr->scr_ecfg.addr = malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT); if (!scr->scr_ecfg.addr) { aprint_error("cannot allocate %d bytes for STI\n", dd->dd_stimemreq); return ENOMEM; } } sti_region_setup(scr); if ((error = sti_init(scr, 0))) { aprint_error(": cannot initialize (%d)\n", error); goto fail; } memset(&cfg, 0, sizeof(cfg)); memset(&ecfg, 0, sizeof(ecfg)); cfg.ext = &ecfg; if ((error = sti_inqcfg(scr, &cfg))) { aprint_error(": error %d inquiring config\n", error); goto fail; } /* * Older (rev 8.02) boards report wrong offset values, * similar to the displayable area size, at least in m68k mode. * Attempt to detect this and adjust here. */ if (cfg.owidth == cfg.width && cfg.oheight == cfg.height) geometry_kluge = 1; if (geometry_kluge) { scr->scr_cfg.oscr_width = cfg.owidth = cfg.fbwidth - cfg.width; scr->scr_cfg.oscr_height = cfg.oheight = cfg.fbheight - cfg.height; } /* * Save a few fields for sti_describe_screen() later */ scr->fbheight = cfg.fbheight; scr->fbwidth = cfg.fbwidth; scr->oheight = cfg.oheight; scr->owidth = cfg.owidth; memcpy(scr->name, cfg.name, sizeof(scr->name)); if ((error = sti_init(scr, STI_TEXTMODE | flags))) { aprint_error(": cannot initialize (%d)\n", error); goto fail; } #ifdef STIDEBUG snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes); DPRINTF(("conf: bpp=%d planes=%d attr=%s\n" "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp, cfg.planes, buf, ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2], ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2])); #endif scr->scr_bpp = cfg.bppu; /* * Although scr->scr_ecfg.current_monitor is not filled by * sti_init() as expected, we can nevertheless walk the monitor * list, if there is any, and if we find a mode matching our * resolution, pick its font index. */ if (dd->dd_montbl != 0) { STI_ENABLE_ROM(rom->rom_softc); for (i = 0; i < dd->dd_nmon; i++) { u_int offs = dd->dd_montbl + 8 * i; uint32_t m[2]; sti_mon_t mon = (void *)m; if (rom->rom_devtype == STI_DEVTYPE1) { m[0] = parseword(4 * offs); m[1] = parseword(4 * (offs + 4)); } else { bus_space_read_region_stream_4(memt, romh, offs, (uint32_t *)mon, sizeof(*mon) / 4); } if (mon->width == scr->scr_cfg.scr_width && mon->height == scr->scr_cfg.scr_height) { fontindex = mon->font; break; } } STI_DISABLE_ROM(rom->rom_softc); DPRINTF(("font index: %d\n", fontindex)); } if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) { aprint_error(": cannot fetch fonts (%d)\n", error); goto fail; } /* * setup screen descriptions: * figure number of fonts supported; * allocate wscons structures; * calculate dimensions. */ scr->scr_wsd.name = "std"; scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width; scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height; scr->scr_wsd.textops = &sti_emulops; scr->scr_wsd.fontwidth = scr->scr_curfont.width; scr->scr_wsd.fontheight = scr->scr_curfont.height; scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE; scr->scr_scrlist[0] = &scr->scr_wsd; scr->scr_screenlist.nscreens = 1; scr->scr_screenlist.screens = scr->scr_scrlist; return 0; fail: /* XXX free resources */ if (scr->scr_ecfg.addr != NULL) { free(scr->scr_ecfg.addr, M_DEVBUF); scr->scr_ecfg.addr = NULL; } return ENXIO; }
/* * Map all regions. */ void sti_region_setup(struct sti_screen *scr) { struct sti_rom *rom = scr->scr_rom; bus_space_tag_t memt = rom->memt; bus_space_handle_t romh = rom->romh; bus_addr_t *bases = rom->bases; struct sti_dd *dd = &rom->rom_dd; struct sti_cfg *cc = &scr->scr_cfg; bus_space_handle_t bh; struct sti_region regions[STI_REGION_MAX], *r; u_int regno, regcnt; bus_addr_t addr; DPRINTF(("stiregions @ %x:\n", dd->dd_reglst)); /* * Read the region information. */ STI_ENABLE_ROM(rom->rom_softc); if (rom->rom_devtype == STI_DEVTYPE1) { for (regno = 0; regno < STI_REGION_MAX; regno++) *(u_int *)(regions + regno) = parseword(dd->dd_reglst + regno * 0x10); } else { bus_space_read_region_stream_4(memt, romh, dd->dd_reglst, (uint32_t *)regions, sizeof(regions) / 4); } STI_DISABLE_ROM(rom->rom_softc); /* * Count them. */ for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++) if (r->last) break; regcnt++; /* * Map them. */ for (regno = 0, r = regions; regno < regcnt; regno++, r++) { if (r->length == 0) continue; /* * Assume an existing mapping exists. */ addr = bases[regno] + (r->offset << PGSHIFT); DPRINTF(("%08x @ 0x%08x%s%s%s%s", r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "", r->cache ? " cache" : "", r->btlb ? " btlb" : "", r->last ? " last" : "")); /* * Region #0 is always the rom, and it should have been * mapped already. * XXX This expects a 1:1 mapping... */ if (regno == 0 && romh == bases[0]) { cc->regions[0] = addr; DPRINTF(("\n")); continue; } /* XXXNH BUS_SPACE_MAP_CACHEABLE */ if (bus_space_map(memt, addr, r->length << PGSHIFT, r->cache ? BUS_SPACE_MAP_CACHEABLE : 0, &bh)) { DPRINTF((" - already mapped region\n")); } else { /* XXX should use bus_space_vaddr */ addr = (bus_addr_t)bh; if (regno == 1) { DPRINTF((" - fb")); scr->fbaddr = addr; scr->fblen = r->length << PGSHIFT; } DPRINTF(("\n")); } cc->regions[regno] = addr; } #ifdef STIDEBUG /* * Make sure we'll trap accessing unmapped regions */ for (regno = 0; regno < STI_REGION_MAX; regno++) if (cc->regions[regno] == 0) cc->regions[regno] = 0x81234567; #endif }
int sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt, bus_space_handle_t romh, bus_addr_t *bases, u_int codebase) { struct sti_dd *dd; int error, size, i; KASSERT(rom != NULL); STI_ENABLE_ROM(rom->rom_softc); rom->iot = iot; rom->memt = memt; rom->romh = romh; rom->bases = bases; /* * Get ROM header and code function pointers. */ dd = &rom->rom_dd; rom->rom_devtype = bus_space_read_1(memt, romh, 3); if (rom->rom_devtype == STI_DEVTYPE1) { dd->dd_type = bus_space_read_1(memt, romh, 0x03); dd->dd_nmon = bus_space_read_1(memt, romh, 0x07); dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b); dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f); dd->dd_grid[0] = parseword(0x10); dd->dd_grid[1] = parseword(0x20); dd->dd_fntaddr = parseword(0x30) & ~3; dd->dd_maxst = parseword(0x40); dd->dd_romend = parseword(0x50) & ~3; dd->dd_reglst = parseword(0x60) & ~3; dd->dd_maxreent= parseshort(0x70); dd->dd_maxtimo = parseshort(0x78); dd->dd_montbl = parseword(0x80) & ~3; dd->dd_udaddr = parseword(0x90) & ~3; dd->dd_stimemreq=parseword(0xa0); dd->dd_udsize = parseword(0xb0); dd->dd_pwruse = parseshort(0xc0); dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb); dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf); dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3); dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7); dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb); dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf); dd->dd_cfbaddr = parseword(0xe0) & ~3; codebase <<= 2; dd->dd_pacode[0x0] = parseword(codebase + 0x00) & ~3; dd->dd_pacode[0x1] = parseword(codebase + 0x10) & ~3; dd->dd_pacode[0x2] = parseword(codebase + 0x20) & ~3; dd->dd_pacode[0x3] = parseword(codebase + 0x30) & ~3; dd->dd_pacode[0x4] = parseword(codebase + 0x40) & ~3; dd->dd_pacode[0x5] = parseword(codebase + 0x50) & ~3; dd->dd_pacode[0x6] = parseword(codebase + 0x60) & ~3; dd->dd_pacode[0x7] = parseword(codebase + 0x70) & ~3; dd->dd_pacode[0x8] = parseword(codebase + 0x80) & ~3; dd->dd_pacode[0x9] = parseword(codebase + 0x90) & ~3; dd->dd_pacode[0xa] = parseword(codebase + 0xa0) & ~3; dd->dd_pacode[0xb] = parseword(codebase + 0xb0) & ~3; dd->dd_pacode[0xc] = parseword(codebase + 0xc0) & ~3; dd->dd_pacode[0xd] = parseword(codebase + 0xd0) & ~3; dd->dd_pacode[0xe] = parseword(codebase + 0xe0) & ~3; dd->dd_pacode[0xf] = parseword(codebase + 0xf0) & ~3; } else { /* STI_DEVTYPE4 */ bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd, sizeof(*dd) / 4); /* fix pacode... */ bus_space_read_region_stream_4(memt, romh, codebase, (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4); } STI_DISABLE_ROM(rom->rom_softc); DPRINTF(("dd:\n" "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n" "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n" "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n" "code=", dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet, dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst, dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo, dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq, dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr)); DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2], dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5], dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8], dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb], dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe], dd->dd_pacode[0xf])); /* * Figure out how many bytes we need for the STI code. * Note there could be fewer than STI_END pointer entries * populated, especially on older devices. */ for (i = STI_END; !dd->dd_pacode[i]; i--) ; size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN]; if (rom->rom_devtype == STI_DEVTYPE1) size = (size + 3) / 4; if (size == 0) { aprint_error(": no code for the requested platform\n"); return EINVAL; } DPRINTF(("code size %x/%x\n", size, round_page(size))); if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0, UVM_KMF_WIRED))) { aprint_error(": cannot allocate %u bytes for code\n", size); return ENOMEM; } /* * Copy code into memory and make it executable. */ STI_ENABLE_ROM(rom->rom_softc); if (rom->rom_devtype == STI_DEVTYPE1) { uint8_t *p; uint32_t addr, eaddr; p = (uint8_t *)rom->rom_code; for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4; addr < eaddr; addr += 4 ) { *p++ = bus_space_read_4(memt, romh, addr) & 0xff; } } else { /* STI_DEVTYPE4 */ bus_space_read_region_stream_4(memt, romh, dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code, size / 4); } STI_DISABLE_ROM(rom->rom_softc); if ((error = uvm_map_protect(kernel_map, rom->rom_code, rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) { aprint_error(": uvm_map_protect failed (%d)\n", error); uvm_km_free(kernel_map, rom->rom_code, round_page(size), UVM_KMF_WIRED); return error; } /* * Setup code function pointers. */ #define O(i) \ (dd->dd_pacode[(i)] == 0 ? 0 : \ (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \ (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1))) rom->init = (sti_init_t) O(STI_INIT_GRAPH); rom->mgmt = (sti_mgmt_t) O(STI_STATE_MGMT); rom->unpmv = (sti_unpmv_t) O(STI_FONT_UNPMV); rom->blkmv = (sti_blkmv_t) O(STI_BLOCK_MOVE); rom->test = (sti_test_t) O(STI_SELF_TEST); rom->exhdl = (sti_exhdl_t) O(STI_EXCEP_HDLR); rom->inqconf = (sti_inqconf_t)O(STI_INQ_CONF); rom->scment = (sti_scment_t)O(STI_SCM_ENT); rom->dmac = (sti_dmac_t) O(STI_DMA_CTRL); rom->flowc = (sti_flowc_t) O(STI_FLOW_CTRL); rom->utiming = (sti_utiming_t)O(STI_UTIMING); rom->pmgr = (sti_pmgr_t) O(STI_PROC_MGR); rom->util = (sti_util_t) O(STI_UTIL); #undef O /* * Set colormap entry is not implemented until 8.04, so force * a NULL pointer here. */ if (dd->dd_grrev < STI_REVISION(8, 4)) { rom->scment = NULL; } return 0; }
int execute(char *p, bool isdown) // all evaluation happens here, recursively { const int MAXWORDS = 25; // limit, remove char *w[MAXWORDS]; int val = 0; for(bool cont = true; cont;) // for each ; seperated statement { int numargs = MAXWORDS; loopi(MAXWORDS) // collect all argument values { w[i] = (char*) ""; if(i>numargs) continue; char *s = parseword(p); // parse and evaluate exps if(!s) { numargs = i; s = (char*) ""; }; if(*s=='$') s = lookup(s); // substitute variables w[i] = s; }; p += strcspn(p, ";\n\0"); cont = *p++!=0; // more statements if this isn't the end of the string const char *c = w[0]; if(*c=='/') c++; // strip irc-style command prefix if(!*c) continue; // empty statement ident *id = idents->access(c); if(!id) { val = ATOI(c); if(!val && *c!='0') console::out("unknown command: %s", c); } else switch(id->type) { case ID_COMMAND: // game defined commands switch(id->narg) // use very ad-hoc function signature, and just call it { case ARG_1INT: if(isdown) ((void (__cdecl *)(int))id->fun)(ATOI(w[1])); break; case ARG_2INT: if(isdown) ((void (__cdecl *)(int, int))id->fun)(ATOI(w[1]), ATOI(w[2])); break; case ARG_3INT: if(isdown) ((void (__cdecl *)(int, int, int))id->fun)(ATOI(w[1]), ATOI(w[2]), ATOI(w[3])); break; case ARG_4INT: if(isdown) ((void (__cdecl *)(int, int, int, int))id->fun)(ATOI(w[1]), ATOI(w[2]), ATOI(w[3]), ATOI(w[4])); break; case ARG_NONE: if(isdown) ((void (__cdecl *)())id->fun)(); break; case ARG_1STR: if(isdown) ((void (__cdecl *)(char *))id->fun)(w[1]); break; case ARG_2STR: if(isdown) ((void (__cdecl *)(char *, char *))id->fun)(w[1], w[2]); break; case ARG_3STR: if(isdown) ((void (__cdecl *)(char *, char *, char*))id->fun)(w[1], w[2], w[3]); break; case ARG_5STR: if(isdown) ((void (__cdecl *)(char *, char *, char*, char*, char*))id->fun)(w[1], w[2], w[3], w[4], w[5]); break; case ARG_DOWN: ((void (__cdecl *)(bool))id->fun)(isdown); break; case ARG_DWN1: ((void (__cdecl *)(bool, char *))id->fun)(isdown, w[1]); break; case ARG_1EXP: if(isdown) val = ((int (__cdecl *)(int))id->fun)(execute(w[1])); break; case ARG_2EXP: if(isdown) val = ((int (__cdecl *)(int, int))id->fun)(execute(w[1]), execute(w[2])); break; case ARG_1EST: if(isdown) val = ((int (__cdecl *)(char *))id->fun)(w[1]); break; case ARG_2EST: if(isdown) val = ((int (__cdecl *)(char *, char *))id->fun)(w[1], w[2]); break; case ARG_VARI: if(isdown) { string r; // limit, remove r[0] = 0; for(int i = 1; i<numargs; i++) { strcat_s(r, w[i]); // make string-list out of all arguments if(i==numargs-1) break; strcat_s(r, " "); }; ((void (__cdecl *)(char *))id->fun)(r); break; } }; break; case ID_VAR: // game defined variabled if(isdown) { if(!w[1][0]) console::out("%s = %d", c, *id->storage); // var with no value just prints its current value else { if(id->min>id->max) { console::out("variable is read-only"); } else { int i1 = ATOI(w[1]); if(i1<id->min || i1>id->max) { i1 = i1<id->min ? id->min : id->max; // clamp to valid range console::out("valid range for %s is %d..%d", c, id->min, id->max); } *id->storage = i1; }; if(id->fun) ((void (__cdecl *)())id->fun)(); // call trigger function if available }; }; break; case ID_ALIAS: // alias, also used as functions and (global) variables for(int i = 1; i<numargs; i++) { sprintf_sd(t)("arg%d", i); // set any arguments as (global) arg values so functions can access them alias(t, w[i]); }; char *action = newstring(id->action); // create new string here because alias could rebind itself val = execute(action, isdown); gp()->deallocstr(action); break; }; loopj(numargs) gp()->deallocstr(w[j]); }; return val; };
void NNCommand2(Connection *conn) { char *ptr; char *cmd; char *buf; Command *scan; int len; conn->co_Func = NNCommand2; conn->co_State = "waitcmd"; /* * we have to be careful in regards to recursive operation, nor do * we want one descriptor to hog the process. We can't set RFds * because the next command may already be entirely loaded into an * MBuf so setting RFds may not unblock us. Instead, we set WFds * which basically forces a wakeup at some point in the future. */ if (conn->co_FCounter) { FD_SET(conn->co_Desc->d_Fd, &WFds); /* * if the other side closed the connection, select() is * not going to wake up for write(!) so set RFds too. */ if (conn->co_TMBuf.mh_WError) FD_SET(conn->co_Desc->d_Fd, &RFds); return; } ++conn->co_FCounter; /* * if there is still output pending, do not process the next * command. */ if (conn->co_TMBuf.mh_Bytes > 0 && !conn->co_TMBuf.mh_WError) return; /* * get command */ if ((len = MBReadLine(&conn->co_RMBuf, &buf)) == 0) { StatusUpdate(conn, "(idle)"); return; } conn->co_ByteCountType = DRBC_NONE; /* * check EOF */ if (len < 0 || conn->co_TMBuf.mh_WError) { NNTerminate(conn); return; } /* * strip CR LF */ ptr = buf; if (len > 1 && ptr[len-2] == '\r') ptr[len-2] = 0; if (DebugOpt) printf("command: %s\n", ptr); if (strncasecmp(ptr, "authinfo pass ", 14)) { LogCmd(conn, '<', ptr); } else { LogCmd(conn, '<', "authinfo pass **unlogged**"); } if (conn->co_Auth.dr_Flags & DF_USEPROXIED) { struct sockaddr_in sin; char *pt = NULL; if (strncasecmp(ptr, "proxied ", 8) || ! ((pt = strrchr(ptr, ':')))) { MBLogPrintf(conn, &conn->co_TMBuf, "400 %s: Proxy authentication failure.\r\n", conn->co_Auth.dr_VServerDef->vs_HostName ); NNTerminate(conn); } *pt++ = '\0'; ptr += 8; bzero((void *)&sin, sizeof(&sin)); sin.sin_family = AF_INET; sin.sin_port = htons(atoi(pt)); sin.sin_addr.s_addr = inet_addr(ptr); bcopy(&sin, &conn->co_Auth.dr_Addr, sizeof(conn->co_Auth.dr_Addr)); conn->co_Auth.dr_Flags &= ~DF_USEPROXIED; conn->co_Auth.dr_ResultFlags = DR_REQUIRE_DNS; return; } /* * extract command (note: StatusUpdate() will limit the line length) */ StatusUpdate(conn, "%s", ptr); if ((cmd = parseword(&ptr, " \t")) == NULL) { NNCommand(conn); return; } { int i; for (i = 0; cmd[i]; ++i) cmd[i] = tolower((int)(unsigned char)cmd[i]); } /* * Locate and execute command */ for (scan = &Cmds[0]; scan < &Cmds[arysize(Cmds)]; ++scan) { if (strcmp(cmd, scan->cmd_Name) == 0) { if (conn->co_Flags & COF_SERVER) { if (scan->cmd_Flags & CMDF_SERVER) { if ((conn->co_Auth.dr_Flags & DF_FEEDONLY) == 0) break; if ((scan->cmd_Flags & CMDF_NOTFEEDONLY) == 0) break; } } else { if (scan->cmd_Flags & CMDF_READER) break; } } } if (scan < &Cmds[arysize(Cmds)]) { if ((scan->cmd_Flags & CMDF_AUTH) && (conn->co_Auth.dr_Flags & DF_AUTHREQUIRED) ) { MBLogPrintf(conn, &conn->co_TMBuf, "480 Authentication required for command\r\n"); NNCommand(conn); } else { conn->co_ByteCountType = scan->cmd_DRBC_Type; scan->cmd_Func(conn, &ptr); } } else { NNUnknownCommand(conn); } }