#include #include "defs.h" #include "prims.h" static int desc_count(void) { struct descriptor_data *d; int rv; rv = 0; for (d=descriptor_list;d;d=d->flink) if (! d->hostnamewait) rv ++; return(rv); } static struct descriptor_data *desc_num_(int n, void (*fail)(void)) { struct descriptor_data *d; int nxerr; nxerr = 1; if (n < 0) { n = -n; nxerr = 0; } for (d=descriptor_list;d;d=d->flink) { if (!d->hostnamewait && !d->usernamewait && (d->descriptor == n)) return(d); } if (nxerr) (*fail)(); return(0); } /* XXX bug in gcc; should be able to call all these functions _fail_, since each one is static to a very restricted scope. But doing that produces assembler errors because then each one is called _fail_ in the resulting assembly file. This kludge depends on the code never calling desc_num more than once per line. */ #define desc_num(n) desc_num_1((n),__LINE__) #define desc_num_1(a,b) desc_num_2(a,b) #define desc_num_2(n,l) \ ({ __label__ _fail_label; \ auto void _fail_##l(void) __attribute__((__noreturn__)); \ auto void _fail_##l(void) { goto _fail_label; } \ if (0) \ { _fail_label: \ ABORT_INTERP("Invalid descriptor number."); \ } \ desc_num_((n),&_fail_##l); \ }) PRIM(concount) { STACKROOM(1); MPUSH(PROG_INTEGER,desc_count()); } PRIM(connections) { struct descriptor_data *d; int n; n = 0; for (d=descriptor_list;d;d=d->flink) { if (! d->hostnamewait) { STACKROOM(1); MPUSH(PROG_INTEGER,d->descriptor); n ++; } } STACKROOM(1); MPUSH(PROG_INTEGER,n); } PRIM(condbref) { struct inst *v; struct descriptor_data *d; dbref p; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); d = desc_num(v->data.number); p = d ? d->connected ? d->player : NOTHING : INVALID; POP(1); MPUSH(PROG_OBJECT,p); } PRIM(conidle) { struct inst *v; struct descriptor_data *d; int idle; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); d = desc_num(v->data.number); idle = d ? curtm()-d->last_time : -1; POP(1); MPUSH(PROG_INTEGER,idle); } PRIM(contime) { struct inst *v; struct descriptor_data *d; int timeon; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); d = desc_num(v->data.number); timeon = d ? curtm()-d->connected_at : -1; POP(1); MPUSH(PROG_INTEGER,timeon); } PRIM(conhost) { struct inst *v; struct descriptor_data *d; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); if (! PWIZARD) ABORT_INTERP("Wizard only."); d = desc_num(v->data.number); POP(1); MPUSH(PROG_STRING,dup_string(d?d->host.text:"")); } PRIM(conuser) { struct inst *v; struct descriptor_data *d; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); if (! PWIZARD) ABORT_INTERP("Wizard only."); d = desc_num(v->data.number); POP(1); MPUSH(PROG_STRING,dup_string(d?d->user.text:"")); } PRIM(conboot) { struct inst *v; struct descriptor_data *d; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); if (! PWIZARD) ABORT_INTERP("Wizard only."); d = desc_num(v->data.number); if (d) { process_output(d); shutdownsock(d); } POP(1); } PRIM(connotify) { struct inst *vdesc; struct inst *vstring; struct descriptor_data *d; NARGS(2); vstring = TOS(0); vdesc = TOS(1); if (vdesc->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer. (1)"); if (vstring->type != PROG_STRING) ABORT_INTERP("Argument not a string. (1)"); if (! PWIZARD) ABORT_INTERP("Wizard only."); d = desc_num(vdesc->data.number); if (d) { queue_string(d,DoNullInd(vstring->data.string)); queue_write(d,"\r\n",2); } POP(2); } PRIM(connectedp) { struct inst *v; struct descriptor_data *d; NARGS(1); v = TOS(0); if (v->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer."); d = v->data.number ? desc_num(-abs(v->data.number)) : 0; POP(1); MPUSH(PROG_INTEGER,!!d); } PRIM(conforce) { struct inst *vdesc; struct inst *vstring; struct descriptor_data *d; NARGS(2); vstring = TOS(0); vdesc = TOS(1); if (vdesc->type != PROG_INTEGER) ABORT_INTERP("Argument not an integer. (1)"); if (vstring->type != PROG_STRING) ABORT_INTERP("Argument not a string. (1)"); if (! PWIZARD) ABORT_INTERP("Wizard only."); d = desc_num(vdesc->data.number); if (d) save_command(d,DoNullInd(vstring->data.string)); POP(2); }