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 if (res
) /* don't print the EOF condition */
73 fprintf(stderr
,"dosmod read only %d of %d bytes.\n",res
,size
);
77 int XWRITE(int fd
,void*buf
,int size
) {
81 res
= write(fd
, buf
, size
);
87 perror("dosmod write");
90 fprintf(stderr
,"dosmod write only %d of %d bytes.\n",res
,size
);
95 void set_timer(struct timeval
*tim
)
101 setitimer(ITIMER_REAL
,&cur
,NULL
);
104 void get_timer(struct timeval
*tim
)
106 struct itimerval cur
;
108 getitimer(ITIMER_REAL
,&cur
);
112 volatile int sig_pend
,sig_fatal
=0,sig_alrm
=0,sig_cb
=0;
114 struct vm86plus_struct VM86
;
116 void sig_handler(int sig
)
118 if (sig_pend
) fprintf(stderr
,"DOSMOD previous signal %d lost\n",sig_pend
);
120 signal(sig
,sig_handler
);
123 void bad_handler(int sig
)
126 fprintf(stderr
,"DOSMOD caught fatal signal %d\n",sig
);
127 fprintf(stderr
,"(Last known VM86 CS:IP was %04x:%04lx)\n",VM86
.regs
.cs
,VM86
.regs
.eip
);
129 sig_pend
=sig
; sig_fatal
++;
130 signal(sig
,bad_handler
);
133 void alarm_handler(int sig
)
136 signal(sig
,alarm_handler
);
139 void cb_handler(int sig
)
142 signal(sig
,cb_handler
);
145 int main(int argc
,char**argv
)
147 int mfd
=open(argv
[0],O_RDWR
);
151 pid_t ppid
=getppid();
153 /* fprintf(stderr,"main is at %08lx, file is %s, fd=%d\n",(unsigned long)&main,argv[0],mfd); */
155 /* Map in our DOS image at the start of the process address space */
157 /* Ulrich Weigand suggested mapping in the DOS image directly from the Wine
160 /* linux currently only allows mapping a process memory if it's being ptraced */
161 /* Linus doesn't like it, so this probably won't work in the future */
162 /* it doesn't even work for me right now */
164 ptrace(PTRACE_ATTACH
,ppid
,0,0);
165 waitpid(ppid
,NULL
,0);
167 img
=mmap(NULL
,0x110000,PROT_EXEC
|PROT_READ
|PROT_WRITE
,MAP_FIXED
|MAP_SHARED
,mfd
,fofs
);
169 ptrace(PTRACE_DETACH
,ppid
,0,0);
172 if (img
==(void*)-1) {
173 fprintf(stderr
,"DOS memory map failed, error=%s\n",strerror(errno
));
174 fprintf(stderr
,"in attempt to map %s, offset %08lX, length 110000, to offset 0\n",argv
[0],fofs
);
177 /* initialize signals and system timer */
178 signal(SIGHUP
,sig_handler
);
179 signal(SIGINT
,sig_handler
);
180 signal(SIGUSR1
,sig_handler
);
181 signal(SIGUSR2
,cb_handler
);
182 signal(SIGALRM
,alarm_handler
);
184 signal(SIGQUIT
,bad_handler
);
185 signal(SIGILL
,bad_handler
);
186 signal(SIGBUS
,bad_handler
);
187 signal(SIGFPE
,bad_handler
);
188 signal(SIGSEGV
,bad_handler
);
189 signal(SIGTERM
,bad_handler
);
191 tim
.tv_sec
=0; tim
.tv_usec
=54925;
194 /* report back to the main program that we're ready */
195 ret
=2; /* dosmod protocol revision */
196 XWRITE(1,&ret
,sizeof(ret
));
197 /* context exchange loop */
199 if (XREAD(0,&func
,sizeof(func
))!=sizeof(func
)) return 1;
202 case DOSMOD_SET_TIMER
:
203 if (XREAD(0,&tim
,sizeof(tim
))!=sizeof(tim
)) return 1;
207 case DOSMOD_GET_TIMER
:
209 if (XWRITE(1,&tim
,sizeof(tim
))!=sizeof(tim
)) return 1;
213 if (XREAD(0,&VM86
,sizeof(VM86
))!=sizeof(VM86
)) return 1;
214 if (sig_pend
||sig_alrm
||sig_cb
) ret
=DOSMOD_SIGNAL
; else
215 ret
=vm86plus(func
,&VM86
);
216 if (XWRITE(1,&ret
,sizeof(ret
))!=sizeof(ret
)) return 1;
217 if (XWRITE(1,&VM86
,sizeof(VM86
))!=sizeof(VM86
)) return 1;
220 ret
=sig_pend
; sig_pend
=0;
223 ret
=SIGALRM
; sig_alrm
--;
225 ret
=SIGUSR2
; sig_cb
--;
228 if (XWRITE(1,&ret
,sizeof(ret
))!=sizeof(ret
)) return 1;
229 if (sig_fatal
) return 1;
237 #else /* !linux-i386 */
238 int main(void) {return 1;}