1 #include "dat.h" 2 #include "fns.h" 3 #include "error.h" 4 #include "interp.h" 5 #include "kernel.h" 6 #include "draw.h" 7 #include "version.h" 8 9 int rebootargc = 0; 10 char** rebootargv; 11 static char *imod = "/dis/emuinit.dis"; 12 extern char* hosttype; 13 char* tkfont; /* for libtk/utils.c */ 14 int tkstylus; /* libinterp/tk.c */ 15 extern int mflag; 16 int dflag; 17 int vflag; 18 int vflag; 19 Procs procs; 20 char *eve; 21 int Xsize = 640; 22 int Ysize = 480; 23 int bflag = 1; 24 int sflag; 25 int qflag; 26 int xtblbit; 27 ulong displaychan; 28 char *cputype; 29 30 static void 31 usage(void) 32 { 33 fprint(2, "Usage: emu [options...] [file.dis [args...]]\n" 34 "\t-gXxY\n" 35 "\t-c[0-9]\n" 36 "\t-d file.dis\n" 37 "\t-s\n" 38 "\t-v\n" 39 "\t-p<poolname>=maxsize\n" 40 "\t-f<fontpath>\n" 41 "\t-r<rootpath>\n" 42 "\t-7\n" 43 "\t-B\n" 44 "\t-C<channel string>\n" 45 "\t-S\n"); 46 47 exits("usage"); 48 } 49 50 static void 51 envusage(void) 52 { 53 fprint(2, "emu: bad option in EMU environment variable (%s)\n", getenv("EMU")); 54 usage(); 55 } 56 57 static int 58 isnum(char *p) 59 { 60 if (*p == 0) return 0; 61 while (*p) { 62 if (*p < '0' || *p > '9') return 0; 63 p++; 64 } 65 return 1; 66 } 67 68 static int 69 geom(char *val) 70 { 71 char *p; 72 int x, y; 73 if (val == '\0' || (*val < '0' || *val > '9')) 74 return 0; 75 x = strtoul(val, &p, 0); 76 if(x >= 64) 77 Xsize = x; 78 if (*p++ != 'x' || !isnum(p)) 79 return 0; 80 y = strtoul(p, &p, 0); 81 if(y >= 48) 82 Ysize = y; 83 if (*p != '\0') return 0; 84 return 1; 85 } 86 87 static void 88 poolopt(char *str) 89 { 90 char *var; 91 int n; 92 ulong x; 93 94 var = str; 95 while(*str && *str != '=') 96 str++; 97 if(*str != '=' || str[1] == '\0') 98 usage(); 99 *str++ = '\0'; 100 n = strlen(str); 101 x = atoi(str); 102 switch(str[n - 1]){ 103 case 'k': 104 case 'K': 105 x *= 1024; 106 break; 107 case 'm': 108 case 'M': 109 x *= 1024*1024; 110 break; 111 } 112 if(poolsetsize(var, x) == 0) 113 usage(); 114 } 115 116 static void 117 option(int argc, char *argv[], void (*badusage)(void)) 118 { 119 char *cp; 120 121 ARGBEGIN { 122 default: 123 badusage(); 124 case 'g': /* Window geometry */ 125 if (geom(EARGF(badusage())) == 0) 126 badusage(); 127 break; 128 case 'b': /* jit array bounds checking (obsolete, now on by default) */ 129 break; 130 case 'B': /* suppress jit array bounds checks */ 131 bflag = 0; 132 break; 133 case 'c': /* Compile on the fly */ 134 cp = EARGF(badusage()); 135 if (!isnum(cp)) 136 badusage(); 137 cflag = atoi(cp); 138 if(cflag < 0|| cflag > 9) 139 usage(); 140 break; 141 case 'I': /* (temporary option) run without cons */ 142 dflag++; 143 break; 144 case 'd': /* run as a daemon */ 145 dflag++; 146 imod = EARGF(badusage()); 147 break; 148 case 's': /* No trap handling */ 149 sflag++; 150 break; 151 case 'm': /* gc mark and sweep */ 152 cp = EARGF(badusage()); 153 if (!isnum(cp)) 154 badusage(); 155 mflag = atoi(cp); 156 if(mflag < 0|| mflag > 9) 157 usage(); 158 break; 159 case 'p': /* pool option */ 160 poolopt(EARGF(badusage())); 161 break; 162 case 'f': /* Set font path */ 163 tkfont = EARGF(badusage()); 164 break; 165 case 'r': /* Set inferno root */ 166 strecpy(rootdir, rootdir+sizeof(rootdir), EARGF(badusage())); 167 break; 168 case '7': /* use 7 bit colormap in X */ 169 xtblbit = 1; 170 break; 171 case 'G': /* allow global access to file system (obsolete) */ 172 break; 173 case 'C': /* channel specification for display */ 174 cp = EARGF(badusage()); 175 displaychan = strtochan(cp); 176 if(displaychan == 0){ 177 fprint(2, "emu: invalid channel specifier (-C): %q\n", cp); 178 exits("usage"); 179 } 180 break; 181 case 'S': 182 tkstylus = 1; 183 break; 184 case 'v': 185 vflag = 1; /* print startup messages */ 186 break; 187 } ARGEND 188 } 189 190 static void 191 savestartup(int argc, char *argv[]) 192 { 193 int i; 194 195 rebootargc = argc; 196 rebootargv = malloc((argc+1)*sizeof(char*)); 197 if(rebootargv == nil) 198 panic("can't save startup args"); 199 for(i = 0; i < argc; i++) { 200 rebootargv[i] = strdup(argv[i]); 201 if(rebootargv[i] == nil) 202 panic("can't save startup args"); 203 } 204 rebootargv[i] = nil; 205 } 206 207 void 208 putenvq(char *name, char *val, int conf) 209 { 210 val = smprint("%q", val); 211 ksetenv(name, val, conf); 212 free(val); 213 } 214 215 void 216 putenvqv(char *name, char **v, int n, int conf) 217 { 218 Fmt f; 219 int i; 220 char *val; 221 222 fmtstrinit(&f); 223 for(i=0; i<n; i++) 224 fmtprint(&f, "%s%q", i?" ":"", v[i]); 225 val = fmtstrflush(&f); 226 ksetenv(name, val, conf); 227 free(val); 228 } 229 230 void 231 nofence(void) 232 { 233 } 234 235 void 236 main(int argc, char *argv[]) 237 { 238 char *opt, *p; 239 char *enva[20]; 240 int envc; 241 242 if(coherence == nil) 243 coherence = nofence; 244 quotefmtinstall(); 245 savestartup(argc, argv); 246 /* set default root now, so either $EMU or -r can override it later */ 247 if((p = getenv("INFERNO")) != nil || (p = getenv("ROOT")) != nil) 248 strecpy(rootdir, rootdir+sizeof(rootdir), p); 249 opt = getenv("EMU"); 250 if(opt != nil && *opt != '\0') { 251 enva[0] = "emu"; 252 envc = tokenize(opt, &enva[1], sizeof(enva)-1) + 1; 253 enva[envc] = 0; 254 option(envc, enva, envusage); 255 } 256 option(argc, argv, usage); 257 eve = strdup("inferno"); 258 259 opt = "interp"; 260 if(cflag) 261 opt = "compile"; 262 263 if(vflag) 264 print("Inferno %s main (pid=%d) %s\n", VERSION, getpid(), opt); 265 266 libinit(imod); 267 } 268 269 void 270 emuinit(void *imod) 271 { 272 Osenv *e; 273 char *wdir; 274 275 e = up->env; 276 e->pgrp = newpgrp(); 277 e->fgrp = newfgrp(nil); 278 e->egrp = newegrp(); 279 e->errstr = e->errbuf0; 280 e->syserrstr = e->errbuf1; 281 e->user = strdup(""); 282 283 links(); 284 chandevinit(); 285 286 if(waserror()) 287 panic("setting root and dot"); 288 289 e->pgrp->slash = namec("#/", Atodir, 0, 0); 290 cnameclose(e->pgrp->slash->name); 291 e->pgrp->slash->name = newcname("/"); 292 e->pgrp->dot = cclone(e->pgrp->slash); 293 poperror(); 294 295 strcpy(up->text, "main"); 296 297 if(kopen("#c/cons", OREAD) != 0) 298 fprint(2, "failed to make fd0 from #c/cons: %r\n"); 299 kopen("#c/cons", OWRITE); 300 kopen("#c/cons", OWRITE); 301 302 /* the setid cannot precede the bind of #U */ 303 kbind("#U", "/", MAFTER|MCREATE); 304 setid(eve, 0); 305 kbind("#^", "/dev", MBEFORE); /* snarf */ 306 kbind("#^", "/chan", MBEFORE); 307 kbind("#m", "/dev", MBEFORE); /* pointer */ 308 kbind("#c", "/dev", MBEFORE); 309 kbind("#p", "/prog", MREPL); 310 kbind("#d", "/fd", MREPL); 311 kbind("#I", "/net", MAFTER); /* will fail on Plan 9 */ 312 313 /* BUG: we actually only need to do these on Plan 9 */ 314 kbind("#U/dev", "/dev", MAFTER); 315 kbind("#U/net", "/net", MAFTER); 316 kbind("#U/net.alt", "/net.alt", MAFTER); 317 318 if(cputype != nil) 319 ksetenv("cputype", cputype, 1); 320 putenvqv("emuargs", rebootargv, rebootargc, 1); 321 putenvq("emuroot", rootdir, 1); 322 ksetenv("emuhost", hosttype, 1); 323 wdir = malloc(1024); 324 if(wdir != nil){ 325 if(getwd(wdir, 1024) != nil) 326 putenvq("emuwdir", wdir, 1); 327 free(wdir); 328 } 329 330 kproc("main", disinit, imod, KPDUPFDG|KPDUPPG|KPDUPENVG); 331 332 for(;;) 333 ospause(); 334 } 335 336 void 337 errorf(char *fmt, ...) 338 { 339 va_list arg; 340 char buf[PRINTSIZE]; 341 342 va_start(arg, fmt); 343 vseprint(buf, buf+sizeof(buf), fmt, arg); 344 va_end(arg); 345 error(buf); 346 } 347 348 void 349 error(char *err) 350 { 351 if(err != up->env->errstr && up->env->errstr != nil) 352 kstrcpy(up->env->errstr, err, ERRMAX); 353 // ossetjmp(up->estack[NERR-1]); 354 nexterror(); 355 } 356 357 void 358 exhausted(char *resource) 359 { 360 char buf[64]; 361 int n; 362 363 n = snprint(buf, sizeof(buf), "no free %s\n", resource); 364 iprint(buf); 365 buf[n-1] = 0; 366 error(buf); 367 } 368 369 void 370 nexterror(void) 371 { 372 oslongjmp(nil, up->estack[--up->nerr], 1); 373 } 374 375 /* for dynamic modules - functions not macros */ 376 377 void* 378 waserr(void) 379 { 380 up->nerr++; 381 return up->estack[up->nerr-1]; 382 } 383 384 void 385 poperr(void) 386 { 387 up->nerr--; 388 } 389 390 char* 391 enverror(void) 392 { 393 return up->env->errstr; 394 } 395 396 void 397 panic(char *fmt, ...) 398 { 399 va_list arg; 400 char buf[512]; 401 402 va_start(arg, fmt); 403 vseprint(buf, buf+sizeof(buf), fmt, arg); 404 va_end(arg); 405 fprint(2, "panic: %s\n", buf); 406 if(sflag) 407 abort(); 408 409 cleanexit(0); 410 } 411 412 int 413 iprint(char *fmt, ...) 414 { 415 416 int n; 417 va_list va; 418 char buf[1024]; 419 420 va_start(va, fmt); 421 n = vseprint(buf, buf+sizeof buf, fmt, va) - buf; 422 va_end(va); 423 424 write(1, buf, n); 425 return 1; 426 } 427 428 void 429 _assert(char *fmt) 430 { 431 panic("assert failed: %s", fmt); 432 } 433 434 /* 435 * mainly for libmp 436 */ 437 void 438 sysfatal(char *fmt, ...) 439 { 440 va_list arg; 441 char buf[64]; 442 443 va_start(arg, fmt); 444 vsnprint(buf, sizeof(buf), fmt, arg); 445 va_end(arg); 446 error(buf); 447 } 448 449 void 450 oserror(void) 451 { 452 oserrstr(up->env->errstr, ERRMAX); 453 error(up->env->errstr); 454 } 455