4 * Copyright 1998 Ove Kåven
7 #if defined(linux) && defined(__i386__)
9 /* apparently ELF images are usually loaded high anyway */
11 /* if not, force dosmod at high addresses */
26 #include <sys/types.h>
27 #include <sys/ptrace.h>
31 /* FIXME: hack because libc vm86 may be the old syscall version */
35 static __inline__ int vm86plus( int func, struct vm86plus_struct *ptr )
39 __asm__ __volatile__( "pushl %%ebx\n\t"
48 __asm__ __volatile__("int $0x80"
54 if (res >= 0) return res;
59 int XREAD(int fd,void*buf,int size) {
63 res = read(fd, buf, size);
69 perror("dosmod read");
72 fprintf(stderr,"dosmod read only %d of %d bytes.\n",res,size);
76 int XWRITE(int fd,void*buf,int size) {
80 res = write(fd, buf, size);
86 perror("dosmod write");
89 fprintf(stderr,"dosmod write only %d of %d bytes.\n",res,size);
94 void set_timer(struct timeval*tim)
100 setitimer(ITIMER_REAL,&cur,NULL);
103 void get_timer(struct timeval*tim)
105 struct itimerval cur;
107 getitimer(ITIMER_REAL,&cur);
111 volatile int sig_pend,sig_fatal=0,sig_alrm=0;
113 struct vm86plus_struct VM86;
115 void sig_handler(int sig)
117 if (sig_pend) fprintf(stderr,"DOSMOD previous signal %d lost\n",sig_pend);
119 signal(sig,sig_handler);
122 void bad_handler(int sig)
124 fprintf(stderr,"DOSMOD caught fatal signal %d\n",sig);
125 fprintf(stderr,"(Last known VM86 CS:IP was %04x:%04lx)\n",VM86.regs.cs,VM86.regs.eip);
126 sig_pend=sig; sig_fatal++;
127 signal(sig,bad_handler);
130 void alarm_handler(int sig)
133 signal(sig,alarm_handler);
136 int main(int argc,char**argv)
138 int mfd=open(argv[0],O_RDWR);
142 pid_t ppid=getppid();
144 /* fprintf(stderr,"main is at %08lx, file is %s, fd=%d\n",(unsigned long)&main,argv[0],mfd); */
146 /* Map in our DOS image at the start of the process address space */
148 /* Ulrich Weigand suggested mapping in the DOS image directly from the Wine
151 /* linux currently only allows mapping a process memory if it's being ptraced */
152 /* Linus doesn't like it, so this probably won't work in the future */
153 /* it doesn't even work for me right now */
155 ptrace(PTRACE_ATTACH,ppid,0,0);
156 waitpid(ppid,NULL,0);
158 img=mmap(NULL,0x110000,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_FIXED|MAP_SHARED,mfd,fofs);
160 ptrace(PTRACE_DETACH,ppid,0,0);
163 if (img==(void*)-1) {
164 fprintf(stderr,"DOS memory map failed, error=%s\n",strerror(errno));
165 fprintf(stderr,"in attempt to map %s, offset %08lX, length 110000, to offset 0\n",argv[0],fofs);
168 /* initialize signals and system timer */
169 signal(SIGHUP,sig_handler);
170 signal(SIGINT,sig_handler);
171 signal(SIGUSR1,sig_handler);
172 signal(SIGUSR2,sig_handler);
173 signal(SIGALRM,alarm_handler);
175 signal(SIGQUIT,bad_handler);
176 signal(SIGILL,bad_handler);
177 signal(SIGBUS,bad_handler);
178 signal(SIGFPE,bad_handler);
179 signal(SIGSEGV,bad_handler);
180 signal(SIGTERM,bad_handler);
182 tim.tv_sec=0; tim.tv_usec=54925;
185 /* report back to the main program that we're ready */
186 ret=1; /* dosmod protocol revision 1 */
187 XWRITE(1,&ret,sizeof(ret));
188 /* context exchange loop */
190 if (XREAD(0,&func,sizeof(func))!=sizeof(func)) return 1;
193 case DOSMOD_SET_TIMER:
194 if (XREAD(0,&tim,sizeof(tim))!=sizeof(tim)) return 1;
198 case DOSMOD_GET_TIMER:
200 if (XWRITE(1,&tim,sizeof(tim))!=sizeof(tim)) return 1;
204 if (XREAD(0,&VM86,sizeof(VM86))!=sizeof(VM86)) return 1;
205 if (sig_pend||sig_alrm) ret=DOSMOD_SIGNAL; else
206 ret=vm86plus(func,&VM86);
207 if (XWRITE(1,&ret,sizeof(ret))!=sizeof(ret)) return 1;
208 if (XWRITE(1,&VM86,sizeof(VM86))!=sizeof(VM86)) return 1;
211 ret=sig_pend; sig_pend=0;
212 if (!ret) { ret=SIGALRM; sig_alrm--; }
213 if (XWRITE(1,&ret,sizeof(ret))!=sizeof(ret)) return 1;
214 if (sig_fatal) return 1;
222 #else /* !linux-i386 */
223 int main(void) {return 1;}