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 main(int argc, char *argv[]) 232 { 233 char *opt, *p; 234 char *enva[20]; 235 int envc; 236 237 quotefmtinstall(); 238 savestartup(argc, argv); 239 /* set default root now, so either $EMU or -r can override it later */ 240 if((p = getenv("INFERNO")) != nil || (p = getenv("ROOT")) != nil) 241 strecpy(rootdir, rootdir+sizeof(rootdir), p); 242 opt = getenv("EMU"); 243 if(opt != nil && *opt != '\0') { 244 enva[0] = "emu"; 245 envc = tokenize(opt, &enva[1], sizeof(enva)-1) + 1; 246 enva[envc] = 0; 247 option(envc, enva, envusage); 248 } 249 option(argc, argv, usage); 250 eve = strdup("inferno"); 251 252 opt = "interp"; 253 if(cflag) 254 opt = "compile"; 255 256 if(vflag) 257 print("Inferno %s main (pid=%d) %s\n", VERSION, getpid(), opt); 258 259 libinit(imod); 260 } 261 262 void 263 emuinit(void *imod) 264 { 265 Osenv *e; 266 267 e = up->env; 268 e->pgrp = newpgrp(); 269 e->fgrp = newfgrp(nil); 270 e->egrp = newegrp(); 271 e->errstr = e->errbuf0; 272 e->syserrstr = e->errbuf1; 273 e->user = strdup(""); 274 275 links(); 276 chandevinit(); 277 278 if(waserror()) 279 panic("setting root and dot"); 280 281 e->pgrp->slash = namec("#/", Atodir, 0, 0); 282 cnameclose(e->pgrp->slash->name); 283 e->pgrp->slash->name = newcname("/"); 284 e->pgrp->dot = cclone(e->pgrp->slash); 285 poperror(); 286 287 strcpy(up->text, "main"); 288 289 if(kopen("#c/cons", OREAD) != 0) 290 fprint(2, "failed to make fd0 from #c/cons: %r\n"); 291 kopen("#c/cons", OWRITE); 292 kopen("#c/cons", OWRITE); 293 294 /* the setid cannot precede the bind of #U */ 295 kbind("#U", "/", MAFTER|MCREATE); 296 setid(eve, 0); 297 kbind("#^", "/dev", MBEFORE); /* snarf */ 298 kbind("#^", "/chan", MBEFORE); 299 kbind("#m", "/dev", MBEFORE); /* pointer */ 300 kbind("#c", "/dev", MBEFORE); 301 kbind("#p", "/prog", MREPL); 302 kbind("#d", "/fd", MREPL); 303 kbind("#I", "/net", MAFTER); /* will fail on Plan 9 */ 304 305 /* BUG: we actually only need to do these on Plan 9 */ 306 kbind("#U/dev", "/dev", MAFTER); 307 kbind("#U/net", "/net", MAFTER); 308 kbind("#U/net.alt", "/net.alt", MAFTER); 309 310 if(cputype != nil) 311 ksetenv("cputype", cputype, 1); 312 putenvqv("emuargs", rebootargv, rebootargc, 1); 313 putenvq("emuroot", rootdir, 1); 314 ksetenv("emuhost", hosttype, 1); 315 316 kproc("main", disinit, imod, KPDUPFDG|KPDUPPG|KPDUPENVG); 317 318 for(;;) 319 ospause(); 320 } 321 322 void 323 errorf(char *fmt, ...) 324 { 325 va_list arg; 326 char buf[PRINTSIZE]; 327 328 va_start(arg, fmt); 329 vseprint(buf, buf+sizeof(buf), fmt, arg); 330 va_end(arg); 331 error(buf); 332 } 333 334 void 335 error(char *err) 336 { 337 if(err != up->env->errstr && up->env->errstr != nil) 338 kstrcpy(up->env->errstr, err, ERRMAX); 339 // ossetjmp(up->estack[NERR-1]); 340 nexterror(); 341 } 342 343 void 344 exhausted(char *resource) 345 { 346 char buf[64]; 347 int n; 348 349 n = snprint(buf, sizeof(buf), "no free %s\n", resource); 350 iprint(buf); 351 buf[n-1] = 0; 352 error(buf); 353 } 354 355 void 356 nexterror(void) 357 { 358 oslongjmp(nil, up->estack[--up->nerr], 1); 359 } 360 361 /* for dynamic modules - functions not macros */ 362 363 void* 364 waserr(void) 365 { 366 up->nerr++; 367 return up->estack[up->nerr-1]; 368 } 369 370 void 371 poperr(void) 372 { 373 up->nerr--; 374 } 375 376 char* 377 enverror(void) 378 { 379 return up->env->errstr; 380 } 381 382 void 383 panic(char *fmt, ...) 384 { 385 va_list arg; 386 char buf[512]; 387 388 va_start(arg, fmt); 389 vseprint(buf, buf+sizeof(buf), fmt, arg); 390 va_end(arg); 391 fprint(2, "panic: %s\n", buf); 392 if(sflag) 393 abort(); 394 395 cleanexit(0); 396 } 397 398 int 399 iprint(char *fmt, ...) 400 { 401 402 int n; 403 va_list va; 404 char buf[1024]; 405 406 va_start(va, fmt); 407 n = vseprint(buf, buf+sizeof buf, fmt, va) - buf; 408 va_end(va); 409 410 write(1, buf, n); 411 return 1; 412 } 413 414 void 415 _assert(char *fmt) 416 { 417 panic("assert failed: %s", fmt); 418 } 419 420 /* 421 * mainly for libmp 422 */ 423 void 424 sysfatal(char *fmt, ...) 425 { 426 va_list arg; 427 char buf[64]; 428 429 va_start(arg, fmt); 430 vsnprint(buf, sizeof(buf), fmt, arg); 431 va_end(arg); 432 error(buf); 433 } 434 435 void 436 oserror(void) 437 { 438 oserrstr(up->env->errstr, ERRMAX); 439 error(up->env->errstr); 440 } 441