elks_sys.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * System calls are mostly pretty easy as the emulator is tightly bound to
  3. * the elks task.
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #include <sys/stat.h>
  11. #include <sys/vm86.h>
  12. #include <sys/times.h>
  13. #include <utime.h>
  14. #include <termios.h>
  15. #include <time.h>
  16. #include <signal.h>
  17. #include <errno.h>
  18. #include <sys/types.h>
  19. #include <sys/resource.h>
  20. #include <sys/wait.h>
  21. #include <sys/ioctl.h>
  22. #include <dirent.h>
  23. #include <sys/time.h>
  24. #include "elks.h"
  25. #include "efile.h"
  26. #ifdef DEBUG
  27. #define dbprintf(x) db_printf x
  28. #else
  29. #define dbprintf(x)
  30. #endif
  31. #define sys_signal elks_signal
  32. extern int elks_signal(int bx,int cx,int dx,int di,int si);
  33. /* Forward refs */
  34. static int elks_termios(int bx,int cx,int dx,int di,int si);
  35. static int elks_enosys(int bx,int cx,int dx,int di,int si);
  36. #define DIRCOUNT 20
  37. DIR * dirtab[DIRCOUNT];
  38. int diropen = 0;
  39. static int elks_opendir(char * dname);
  40. static int elks_readdir(int bx,int cx,int dx,int di,int si);
  41. static int elks_closedir(int bx);
  42. /*
  43. * Compress a host stat into a elks one. Lose upper bits with wild
  44. * abandon. For SYS5.3 this isn't a problem, but machines with 32
  45. * bit inodes (BSD, SYS5 with veritas, newest SCO) you lose the top
  46. * bits which can confuse a few programs which use inode numbers
  47. * (eg gnu tar).
  48. */
  49. static void squash_stat(struct stat *s, int bx)
  50. {
  51. #if 1 /* Can't use elks_stat, shot in the foot by alignment */
  52. ELKS_POKE(short, bx+0, s->st_dev);
  53. ELKS_POKE(short, bx+2, s->st_ino ^ (s->st_ino>>16));
  54. ELKS_POKE(short, bx+4, s->st_mode);
  55. ELKS_POKE(short, bx+6, s->st_nlink);
  56. ELKS_POKE(short, bx+8, s->st_uid);
  57. ELKS_POKE(short, bx+10, s->st_gid);
  58. ELKS_POKE(short, bx+12, s->st_rdev);
  59. ELKS_POKE(long, bx+14, s->st_size);
  60. ELKS_POKE(long, bx+18, s->st_atime);
  61. ELKS_POKE(long, bx+22, s->st_mtime);
  62. ELKS_POKE(long, bx+26, s->st_ctime);
  63. #else
  64. struct elks_stat * ms = ELKS_PTR(struct elks_stat, bx);
  65. ms->est_dev=s->st_dev;
  66. ms->est_inode=(unsigned short)s->st_ino; /* Bits lost */
  67. ms->est_mode=s->st_mode;
  68. ms->est_nlink=s->st_nlink;
  69. ms->est_uid=s->st_uid;
  70. ms->est_gid=s->st_gid;
  71. ms->est_rdev=s->st_rdev;
  72. ms->est_size=s->st_size;
  73. ms->est_atime=s->st_atime;
  74. ms->est_mtime=s->st_mtime;
  75. ms->est_ctime=s->st_ctime;
  76. #endif
  77. }
  78. /*
  79. * Implementation of ELKS syscalls.
  80. */
  81. #define sys_exit elks_exit
  82. static int elks_exit(int bx,int cx,int dx,int di,int si)
  83. {
  84. dbprintf(("exit(%d)\n",bx));
  85. exit(bx);
  86. }
  87. #define sys_vfork elks_fork
  88. #define sys_fork elks_fork
  89. static int elks_fork(int bx,int cx,int dx,int di,int si)
  90. {
  91. dbprintf(("fork()\n"));
  92. /* This is fun 8) - fork the emulator (its easier that way) */
  93. return fork();
  94. }
  95. #define sys_read elks_read
  96. static int elks_read(int bx,int cx,int dx,int di,int si)
  97. {
  98. dbprintf(("read(%d, %d, %d)\n",
  99. bx,cx,dx));
  100. if( bx >= 10000 && bx < 10000+DIRCOUNT)
  101. return elks_readdir(bx, cx, dx, di, si);
  102. if( dx < 0 || dx > 1024 ) dx = 1024;
  103. return read(bx, ELKS_PTR(void, cx), dx);
  104. }
  105. #define sys_write elks_write
  106. static int elks_write(int bx,int cx,int dx,int di,int si)
  107. {
  108. #ifdef TESTING
  109. if( dx > 1024 || dx < 0 )
  110. {
  111. dx = 1024;
  112. dbprintf(("write(%d, %d, >%d)\n",bx,cx,dx));
  113. }
  114. else
  115. #endif
  116. {
  117. dbprintf(("write(%d, %d, %d)\n",bx,cx,dx));
  118. }
  119. return write(bx,ELKS_PTR(void, cx),dx);
  120. }
  121. #define sys_open elks_open
  122. static int elks_open(int bx,int cx,int dx,int di,int si)
  123. {
  124. struct stat s;
  125. /* Assumes _all_ flags are the same */
  126. char *dp=ELKS_PTR(char, bx);
  127. dbprintf(("open(%s, %d, %d)\n",
  128. dp,cx,dx));
  129. /* Nasty hack so /lib/liberror.txt doesn't exist on the host.
  130. */
  131. if (strcmp(dp, "/lib/liberror.txt") == 0 ) {
  132. int fd = open("/tmp/liberror.txt", O_CREAT|O_EXCL|O_RDWR, 0666);
  133. if (fd < 0) return fd;
  134. unlink("/tmp/liberror.txt");
  135. write(fd, efile, sizeof(efile));
  136. lseek(fd, 0L, 0);
  137. return fd;
  138. }
  139. if( cx == O_RDONLY )
  140. {
  141. if(stat(dp,&s)==-1)
  142. return -1;
  143. if( S_ISDIR(s.st_mode) )
  144. return elks_opendir(dp);
  145. }
  146. return open(dp,cx,dx);
  147. }
  148. #define sys_close elks_close
  149. static int elks_close(int bx,int cx,int dx,int di,int si)
  150. {
  151. dbprintf(("close(%d)\n",bx));
  152. if( bx >= 10000 && bx < 10000+DIRCOUNT)
  153. return elks_closedir(bx);
  154. return close(bx);
  155. }
  156. #define sys_wait4 elks_wait4
  157. static int elks_wait4(int bx,int cx,int dx,int di,int si)
  158. {
  159. int status;
  160. unsigned short *tp=ELKS_PTR(unsigned short, cx);
  161. int r;
  162. struct rusage use;
  163. dbprintf(("wait4(%d, %d, %d, %d)\n", bx, cx, dx, di));
  164. r=wait4((int)(short)bx, &status, dx, &use );
  165. *tp=status;
  166. if( di ) memcpy(ELKS_PTR(void, di), &use, sizeof(use));
  167. return r;
  168. }
  169. #define sys_link elks_link
  170. static int elks_link(int bx,int cx,int dx,int di,int si)
  171. {
  172. dbprintf(("link(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx)));
  173. return link(ELKS_PTR(char, bx),ELKS_PTR(char, cx));
  174. }
  175. #define sys_unlink elks_unlink
  176. static int elks_unlink(int bx,int cx,int dx,int di,int si)
  177. {
  178. dbprintf(("unlink(%s)\n",ELKS_PTR(char, bx)));
  179. return unlink(ELKS_PTR(char, bx));
  180. }
  181. #define sys_chdir elks_chdir
  182. static int elks_chdir(int bx,int cx,int dx,int di,int si)
  183. {
  184. dbprintf(("chdir(%s)\n",ELKS_PTR(char, bx)));
  185. return chdir(ELKS_PTR(char, bx));
  186. }
  187. #define sys_fchdir elks_fchdir
  188. static int elks_fchdir(int bx,int cx,int dx,int di,int si)
  189. {
  190. dbprintf(("fchdir(%s)\n",bx));
  191. return fchdir(bx);
  192. }
  193. #define sys_mknod elks_mknod
  194. static int elks_mknod(int bx,int cx,int dx,int di,int si)
  195. {
  196. dbprintf(("mknod(%s,%d,%d)\n", ELKS_PTR(char, bx),cx,dx));
  197. return mknod(ELKS_PTR(char, bx),cx,dx);
  198. }
  199. #define sys_chmod elks_chmod
  200. static int elks_chmod(int bx,int cx,int dx,int di,int si)
  201. {
  202. dbprintf(("chmod(%s,%d)\n", ELKS_PTR(char, bx),cx));
  203. return chmod(ELKS_PTR(char, bx), cx);
  204. }
  205. #define sys_chown elks_chown
  206. static int elks_chown(int bx,int cx,int dx,int di,int si)
  207. {
  208. dbprintf(("chown(%s,%d,%d)\n", ELKS_PTR(char, bx),cx,dx));
  209. return chown(ELKS_PTR(char, bx),cx,dx);
  210. }
  211. #define sys_brk elks_brk
  212. static int elks_brk(int bx,int cx,int dx,int di,int si)
  213. {
  214. dbprintf(("brk(%d)\n",bx));
  215. if(bx>=elks_cpu.regs.esp)
  216. {
  217. errno= 1; /* Really return -1 */
  218. return -1;
  219. }
  220. return 0; /* Can't return bx, 0xBAD1 is an error */
  221. }
  222. #define sys_stat elks_stat
  223. static int elks_stat(int bx,int cx,int dx,int di,int si)
  224. {
  225. struct stat s;
  226. dbprintf(("stat(%s,%d)\n", ELKS_PTR(char, bx), cx));
  227. if(stat(ELKS_PTR(char, bx),&s)==-1)
  228. return -1;
  229. squash_stat(&s,cx);
  230. return 0;
  231. }
  232. #define sys_lstat elks_lstat
  233. static int elks_lstat(int bx,int cx,int dx,int di,int si)
  234. {
  235. struct stat s;
  236. dbprintf(("lstat(%s,%d)\n", ELKS_PTR(char, bx), cx));
  237. if(lstat(ELKS_PTR(char, bx),&s)==-1)
  238. return -1;
  239. squash_stat(&s,cx);
  240. return 0;
  241. }
  242. #define sys_lseek elks_lseek
  243. static int elks_lseek(int bx,int cx,int dx,int di,int si)
  244. {
  245. long l=ELKS_PEEK(long, cx);
  246. dbprintf(("lseek(%d,%ld,%d)\n",bx,l,dx));
  247. l = lseek(bx,l,dx);
  248. if( l < 0 ) return -1;
  249. ELKS_POKE(long, cx, l);
  250. return 0;
  251. }
  252. #define sys_getpid elks_getpid
  253. static int elks_getpid(int bx,int cx,int dx,int di,int si)
  254. {
  255. dbprintf(("getpid/getppid()\n"));
  256. ELKS_POKE(unsigned short, bx, getppid());
  257. return getpid();
  258. }
  259. #define sys_setuid elks_setuid
  260. static int elks_setuid(int bx,int cx,int dx,int di,int si)
  261. {
  262. dbprintf(("setuid(%d)\n",bx));
  263. return setuid(bx);
  264. }
  265. #define sys_getuid elks_getuid
  266. static int elks_getuid(int bx,int cx,int dx,int di,int si)
  267. {
  268. dbprintf(("get[e]uid()\n"));
  269. ELKS_POKE(unsigned short, bx, geteuid());
  270. return getuid();
  271. }
  272. #define sys_alarm elks_alarm
  273. static int elks_alarm(int bx,int cx,int dx,int di,int si)
  274. {
  275. dbprintf(("alarm(%d)\n",bx&0xFFFF));
  276. return alarm(bx&0xFFFF);
  277. }
  278. #define sys_fstat elks_fstat
  279. static int elks_fstat(int bx,int cx,int dx,int di,int si)
  280. {
  281. struct stat s;
  282. int err;
  283. dbprintf(("fstat(%d,%d)\n",bx,cx));
  284. err=fstat(bx,&s);
  285. squash_stat(&s,cx);
  286. return err;
  287. }
  288. #define sys_pause elks_pause
  289. static int elks_pause(int bx,int cx,int dx,int di,int si)
  290. {
  291. dbprintf(("pause()\n"));
  292. return pause();
  293. }
  294. #define sys_utime elks_utime
  295. static int elks_utime(int bx,int cx,int dx,int di,int si)
  296. {
  297. unsigned long *up=ELKS_PTR(long, cx);
  298. struct utimbuf u;
  299. u.actime=*up++;
  300. u.modtime=*up;
  301. return utime(ELKS_PTR(char, bx), &u);
  302. }
  303. #define sys_access elks_access
  304. static int elks_access(int bx,int cx,int dx,int di,int si)
  305. {
  306. dbprintf(("access(%s,%d)\n",ELKS_PTR(char, bx),cx));
  307. return access(ELKS_PTR(char, bx),cx);
  308. }
  309. #define sys_sync elks_sync
  310. static int elks_sync(int bx,int cx,int dx,int di,int si)
  311. {
  312. dbprintf(("sync()\n"));
  313. sync();
  314. return 0;
  315. }
  316. #define sys_kill elks_kill
  317. static int elks_kill(int bx,int cx,int dx,int di,int si)
  318. {
  319. dbprintf(("kill(%d,%d)\n",bx,cx));
  320. return kill(bx,cx);
  321. }
  322. #define sys_pipe elks_pipe
  323. static int elks_pipe(int bx,int cx,int dx,int di,int si)
  324. {
  325. unsigned short *dp=ELKS_PTR(unsigned short, bx);
  326. int p[2];
  327. int err=pipe(p);
  328. if(err==-1)
  329. return err;
  330. *dp++=p[0];
  331. *dp=p[1];
  332. return 0;
  333. }
  334. #define sys_times elks_times
  335. static int elks_times(int bx,int cx,int dx,int di,int si)
  336. {
  337. struct tms t;
  338. long clock_ticks=times(&t);
  339. long *tp=ELKS_PTR(long, bx);
  340. long *clkt=ELKS_PTR(long, cx);
  341. *tp++=t.tms_utime;
  342. *tp++=t.tms_stime;
  343. *tp++=t.tms_cutime;
  344. *tp=t.tms_cstime;
  345. *clkt = clock_ticks;
  346. return 0; /* Should be clock_ticks */
  347. }
  348. #define sys_setgid elks_setgid
  349. static int elks_setgid(int bx,int cx,int dx,int di,int si)
  350. {
  351. return setgid(bx);
  352. }
  353. #define sys_getgid elks_getgid
  354. static int elks_getgid(int bx,int cx,int dx,int di,int si)
  355. {
  356. ELKS_POKE(unsigned short, bx, getegid());
  357. return getgid();
  358. }
  359. /*
  360. * Exec is fun. The Minix user library builds a complete elks stack image.
  361. * Great except that we need to unpack it all again and do a real exec. If
  362. * its another elks image then our kernel side binary loader will load
  363. * elksemu again and we'll take the Unix args and turn them back into a
  364. * elks stack image.
  365. *
  366. * For now we run elksemu ourselves and do token attempts at binary checking.
  367. *
  368. * Of course if the kernel misc module is confiured we could just run the exe.
  369. */
  370. #define sys_execve elks_execve
  371. static int elks_execve(int bx,int cx,int dx,int di,int si)
  372. {
  373. int fd;
  374. int arg_ct,env_ct;
  375. int ct;
  376. char **argp, **envp;
  377. unsigned short *bp;
  378. unsigned char *base;
  379. unsigned short *tmp;
  380. struct elks_exec_hdr mh;
  381. int is_elks = 1;
  382. dbprintf(("exec(%s,%d,%d)\n",ELKS_PTR(char, bx), cx, dx));
  383. base=ELKS_PTR(unsigned char, cx);
  384. bp=ELKS_PTR(unsigned short, cx+2);
  385. tmp=bp;
  386. fd=open(ELKS_PTR(char, bx),O_RDONLY);
  387. if(fd==-1)
  388. { errno = ENOENT; return -1; }
  389. if(read(fd, &mh, sizeof(mh))!=sizeof(mh))
  390. {
  391. close(fd);
  392. errno = ENOEXEC;
  393. return -1;
  394. }
  395. close(fd);
  396. if(mh.hlen!=EXEC_HEADER_SIZE
  397. || (mh.type!=ELKS_COMBID && mh.type!=ELKS_SPLITID))
  398. is_elks = 0;
  399. arg_ct = env_ct = 0;
  400. while(*tmp++)
  401. arg_ct++;
  402. while(*tmp++)
  403. env_ct++;
  404. arg_ct+=2; /* elksemu-path progname arg0...argn */
  405. argp=malloc(sizeof(char *)*(arg_ct+1));
  406. envp=malloc(sizeof(char *)*(env_ct+1));
  407. if(!argp||!envp) { errno = ENOMEM; return -1; }
  408. ct=0;
  409. if( is_elks )
  410. {
  411. argp[0]="/usr/bin/elksemu";
  412. /* argp[1]=ELKS_PTR(char, bx); */
  413. ct=1;
  414. }
  415. while(*bp)
  416. argp[ct++]=ELKS_PTR(char, cx+ *bp++);
  417. argp[ct]=0;
  418. bp++;
  419. ct=0;
  420. while(*bp)
  421. envp[ct++]=ELKS_PTR(char, cx+ *bp++);
  422. envp[ct]=0;
  423. if( is_elks )
  424. {
  425. argp[1]=ELKS_PTR(char, bx);
  426. execve(argp[0],argp,envp);
  427. }
  428. else
  429. execve(ELKS_PTR(char, bx),argp,envp);
  430. if( errno == ENOEXEC || errno == EACCES ) return -1;
  431. perror("elksemu");
  432. exit(1);
  433. }
  434. #define sys_umask elks_umask
  435. static int elks_umask(int bx,int cx,int dx,int di,int si)
  436. {
  437. return umask(bx);
  438. }
  439. #define sys_chroot elks_chroot
  440. static int elks_chroot(int bx,int cx,int dx,int di,int si)
  441. {
  442. dbprintf(("chroot(%s)\n", ELKS_PTR(char, bx)));
  443. return chroot(ELKS_PTR(char, bx));
  444. }
  445. #define sys_fcntl elks_fcntl
  446. static int elks_fcntl(int bx,int cx,int dx,int di,int si)
  447. {
  448. dbprintf(("fcntl(%d,%d,%d)\n", bx,cx,dx));
  449. switch(cx)
  450. {
  451. case ELKS_F_GETFD:
  452. return fcntl(bx,F_GETFD,0);
  453. case ELKS_F_GETFL:
  454. return fcntl(bx,F_GETFL,0);
  455. case ELKS_F_DUPFD:
  456. return fcntl(bx,F_DUPFD,dx);
  457. case ELKS_F_SETFD:
  458. return fcntl(bx,F_SETFD,dx);
  459. case ELKS_F_SETFL:
  460. return fcntl(bx,F_SETFL,dx);
  461. /*
  462. * Fixme: Unpack and process elks file locks
  463. */
  464. case ELKS_F_GETLK:
  465. case ELKS_F_SETLK:
  466. case ELKS_F_SETLKW:
  467. errno = EINVAL;
  468. return -1;
  469. }
  470. errno = EINVAL;
  471. return -1;
  472. }
  473. #define sys_dup elks_dup
  474. static int elks_dup(int bx,int cx,int dx,int di,int si)
  475. {
  476. return dup(bx);
  477. }
  478. #define sys_dup2 elks_dup2
  479. static int elks_dup2(int bx,int cx,int dx,int di,int si)
  480. {
  481. return dup2(bx, cx);
  482. }
  483. #define sys_rename elks_rename
  484. static int elks_rename(int bx,int cx,int dx,int di,int si)
  485. {
  486. dbprintf(("rename(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx)));
  487. return rename(ELKS_PTR(char, bx), ELKS_PTR(char, cx));
  488. }
  489. #define sys_mkdir elks_mkdir
  490. static int elks_mkdir(int bx,int cx,int dx,int di,int si)
  491. {
  492. dbprintf(("mkdir(%s,%d)\n", ELKS_PTR(char, bx),cx));
  493. return mkdir(ELKS_PTR(char, bx),cx);
  494. }
  495. #define sys_rmdir elks_rmdir
  496. static int elks_rmdir(int bx,int cx,int dx,int di,int si)
  497. {
  498. dbprintf(("rmdir(%s)\n", ELKS_PTR(char, bx)));
  499. return rmdir(ELKS_PTR(char, bx));
  500. }
  501. #define sys_gettimeofday elks_gettimeofday
  502. static int elks_gettimeofday(int bx,int cx,int dx,int di,int si)
  503. {
  504. struct timeval tv;
  505. struct timezone tz;
  506. int ax;
  507. dbprintf(("gettimeofday(%d,%d)\n",bx,cx));
  508. ax = gettimeofday(&tv, &tz);
  509. if( ax == 0 && bx )
  510. {
  511. ELKS_POKE(long, bx, tv.tv_sec);
  512. ELKS_POKE(long, bx+4, tv.tv_usec);
  513. }
  514. if( ax == 0 && cx )
  515. {
  516. ELKS_POKE(short, cx, tz.tz_minuteswest);
  517. ELKS_POKE(short, cx+2, tz.tz_dsttime);
  518. }
  519. return ax?-1:0;
  520. }
  521. #define sys_settimeofday elks_settimeofday
  522. static int elks_settimeofday(int bx,int cx,int dx,int di,int si)
  523. {
  524. struct timeval tv, *pv = 0;
  525. struct timezone tz, *pz = 0;
  526. int ax;
  527. dbprintf(("settimeofday(%d,%d)\n",bx,cx));
  528. if( bx )
  529. {
  530. pv = &tv;
  531. tv.tv_sec = ELKS_PEEK(long, bx);
  532. tv.tv_usec = ELKS_PEEK(long, bx+4);
  533. }
  534. if( cx )
  535. {
  536. pz = &tz;
  537. tz.tz_minuteswest = ELKS_PEEK(short, cx);
  538. tz.tz_dsttime = ELKS_PEEK(short, cx+2);
  539. }
  540. ax = settimeofday(pv, pz);
  541. return ax?-1:0;
  542. }
  543. #define sys_nice elks_nice
  544. static int elks_nice(int bx,int cx,int dx,int di,int si)
  545. {
  546. dbprintf(("nice(%d)\n",bx));
  547. return nice(bx);
  548. }
  549. #define sys_symlink elks_symlink
  550. static int elks_symlink(int bx,int cx,int dx,int di,int si)
  551. {
  552. dbprintf(("symlink(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx)));
  553. return symlink(ELKS_PTR(char, bx), ELKS_PTR(char, cx));
  554. }
  555. #define sys_readlink elks_readlink
  556. static int elks_readlink(int bx,int cx,int dx,int di,int si)
  557. {
  558. dbprintf(("readlink(%s,%s,%d)\n",
  559. ELKS_PTR(char, bx),
  560. ELKS_PTR(char, cx),
  561. dx));
  562. return readlink(ELKS_PTR(char, bx), ELKS_PTR(char, cx), dx);
  563. }
  564. #define sys_ioctl elks_ioctl
  565. static int elks_ioctl(int bx,int cx,int dx,int di,int si)
  566. {
  567. dbprintf(("ioctl(%d,0x%04x,0x%04x)\n", bx,cx,dx));
  568. switch((cx>>8)&0xFF)
  569. {
  570. case 'T': return elks_termios(bx,cx,dx,di,si);
  571. default: return elks_enosys(bx,cx,dx,di,si);
  572. }
  573. }
  574. #define sys_reboot elks_reboot
  575. static int elks_reboot(int bx,int cx,int dx,int di,int si)
  576. {
  577. errno = EINVAL;
  578. if( bx != 0xfee1 || cx != 0xdead ) return -1;
  579. switch(dx)
  580. {
  581. /* graceful shutdown, C-A-D off, kill -? 1 */
  582. case 0: return reboot(0xfee1dead, 672274793, 0);
  583. /* Enable C-A-D */
  584. case 0xCAD: return reboot(0xfee1dead, 672274793, 0x89abcdef);
  585. /* Time to die! */
  586. case 0xD1E: return reboot(0xfee1dead, 672274793, 0x1234567);
  587. }
  588. return -1;
  589. }
  590. /****************************************************************************/
  591. static int
  592. elks_opendir(char * dname)
  593. {
  594. DIR * d;
  595. int rv;
  596. for(rv=0; rv<DIRCOUNT; rv++)
  597. if( dirtab[rv] == 0 )
  598. break;
  599. if( rv >= DIRCOUNT ) { errno=ENOMEM; return -1; }
  600. d = opendir(dname);
  601. if( d == 0 ) return -1;
  602. dirtab[rv] = d;
  603. return 10000+rv;
  604. }
  605. #define sys_readdir elks_readdir
  606. static int elks_readdir(int bx,int cx,int dx,int di,int si)
  607. {
  608. struct dirent * ent;
  609. /* Only read _ONE_ _WHOLE_ dirent at a time */
  610. if( dx != 266 && dx != 1 )
  611. {
  612. errno=EINVAL; return -1;
  613. }
  614. errno = 0;
  615. ent = readdir(dirtab[bx-10000]);
  616. if( ent == 0 ) { if( errno ) { return -1; } else return 0; }
  617. memcpy(ELKS_PTR(char, cx+10), ent->d_name, ent->d_reclen+1);
  618. ELKS_POKE(long, cx, ent->d_ino);
  619. ELKS_POKE(short, cx+8, ent->d_reclen);
  620. return dx;
  621. }
  622. static int
  623. elks_closedir(int bx)
  624. {
  625. bx-=10000;
  626. if( dirtab[bx] ) closedir(dirtab[bx]);
  627. dirtab[bx] = 0;
  628. return 0;
  629. }
  630. /****************************************************************************/
  631. static int elks_termios(int bx,int cx,int dx,int di,int si)
  632. {
  633. int rv = 0;
  634. switch(cx&0xFF)
  635. {
  636. case 0x01: rv = ioctl(bx, TCGETS, ELKS_PTR(void, dx)); break;
  637. case 0x02: rv = ioctl(bx, TCSETS, ELKS_PTR(void, dx)); break;
  638. case 0x03: rv = ioctl(bx, TCSETSW, ELKS_PTR(void, dx)); break;
  639. case 0x04: rv = ioctl(bx, TCSETSF, ELKS_PTR(void, dx)); break;
  640. case 0x09: rv = ioctl(bx, TCSBRK, dx); break;
  641. case 0x0A: rv = ioctl(bx, TCXONC, dx); break;
  642. case 0x0B: rv = ioctl(bx, TCFLSH, dx); break;
  643. case 0x11: rv = ioctl(bx, TIOCOUTQ, ELKS_PTR(void, dx)); break;
  644. case 0x1B: rv = ioctl(bx, TIOCINQ, ELKS_PTR(void, dx)); break;
  645. default: rv = -1; errno = EINVAL; break;
  646. }
  647. return rv;
  648. }
  649. /****************************************************************************/
  650. /* */
  651. /****************************************************************************/
  652. #define sys_enosys elks_enosys
  653. static int elks_enosys(int bx,int cx,int dx,int di,int si)
  654. {
  655. fprintf(stderr, "Function number %d called (%d,%d,%d)\n",
  656. (int)(0xFFFF&elks_cpu.regs.eax),
  657. bx, cx, dx);
  658. errno = ENOSYS;
  659. return -1;
  660. }
  661. #include "defn_tab.v"
  662. /* * */
  663. typedef int (*funcp)(int, int, int, int, int);
  664. static funcp jump_tbl[] = {
  665. #include "call_tab.v"
  666. elks_enosys
  667. };
  668. int elks_syscall(void)
  669. {
  670. int r, n;
  671. int bx=elks_cpu.regs.ebx&0xFFFF;
  672. int cx=elks_cpu.regs.ecx&0xFFFF;
  673. int dx=elks_cpu.regs.edx&0xFFFF;
  674. int di=elks_cpu.regs.edi&0xFFFF;
  675. int si=elks_cpu.regs.esi&0xFFFF;
  676. errno=0;
  677. n = (elks_cpu.regs.eax&0xFFFF);
  678. if( n>= 0 && n< sizeof(jump_tbl)/sizeof(funcp) )
  679. r = (*(jump_tbl[n]))(bx, cx, dx, di, si);
  680. else
  681. return -ENOSYS;
  682. if(r>=0)
  683. return r;
  684. else
  685. return -errno;
  686. }