From owner-freebsd-ports Sat Sep 25 14:10:42 1999 Delivered-To: freebsd-ports@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 4D2B914EBA for ; Sat, 25 Sep 1999 14:10:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id OAA21371; Sat, 25 Sep 1999 14:10:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from blaubaer.kn-bremen.de (blaubaer.kn-bremen.de [195.37.179.254]) by hub.freebsd.org (Postfix) with ESMTP id 37D5114E8B for ; Sat, 25 Sep 1999 14:02:31 -0700 (PDT) (envelope-from nox@saturn.kn-bremen.de) Received: from saturn.kn-bremen.de (uucp@localhost) by blaubaer.kn-bremen.de (8.9.1/8.9.1) with UUCP id WAA10135 for FreeBSD-gnats-submit@freebsd.org; Sat, 25 Sep 1999 22:56:52 +0200 Received: (from nox@localhost) by saturn.kn-bremen.de (8.9.3/8.8.5) id WAA56452; Sat, 25 Sep 1999 22:47:57 +0200 (MET DST) Message-Id: <199909252047.WAA56452@saturn.kn-bremen.de> Date: Sat, 25 Sep 1999 22:47:57 +0200 (MET DST) From: Juergen Lock Reply-To: nox@jelal.kn-bremen.de To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: ports/13952: update emulators/wine to 990923 (supersedes ports/13670) Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 13952 >Category: ports >Synopsis: update emulators/wine to 990923 (supersedes ports/13670) >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sat Sep 25 14:10:00 PDT 1999 >Closed-Date: >Last-Modified: >Originator: Juergen Lock >Release: FreeBSD 3.3-STABLE i386 >Organization: me? organized? >Environment: 3.3-STABLE i386, xpm-3.4k >Description: From the ANNOUNCE: This is release 990923 of Wine, a free implementation of Windows on Unix. This is still a developers only release. There are many bugs and unimplemented features. Most applications still do not work correctly. Patches should be submitted to "julliard@lrc.epfl.ch". Please don't forget to include a ChangeLog entry. WHAT'S NEW with Wine-990923: (see ChangeLog for details) - DIB optimizations. - Multimedia and OLE DLLs reorganization. - Many fixes in font mapping. - Clipboard support improvements. - Lots of bug fixes. >How-To-Repeat: n/a >Fix: Changed files: Makefile, files/md5, patches/patch-ad, pkg/PLIST New files: files/README.patch, files/patch-3.3-sys-ldtshare, files/patch-3.3-sys-sigtrap, patches/patch-ba, patches/patch-bd, patches/patch-bf, patches/patch-bg, patches/patch-bi, patches/patch-bj, patches/patch-cb, patches/patch-ce, patches/patch-ch, patches/patch-cj, patches/patch-ck, patches/patch-cl, pkg/MESSAGE Removed files: patches/patch-am, patches/patch-an, patches/patch-aw, patches/patch-ay Index: Makefile =================================================================== RCS file: /home/cvs/cvs/ports/emulators/wine/Makefile,v retrieving revision 1.73 diff -u -u -r1.73 Makefile --- Makefile 1999/08/31 06:43:57 1.73 +++ Makefile 1999/09/25 17:20:57 @@ -1,14 +1,14 @@ # New ports collection makefile for: wine -# Version required: 980517 +# Version required: 990923 # Date created: Sa 9 Nov 1996 00:52:22 MET # Whom: se # # $FreeBSD: ports/emulators/wine/Makefile,v 1.73 1999/08/31 06:43:57 mharo Exp $ # -DATE= 990426 +DATE= 990923 DISTNAME= Wine-${DATE} -PKGNAME= wine-99.04.26 +PKGNAME= wine-99.09.23 CATEGORIES= emulators MASTER_SITES= ${MASTER_SITE_SUNSITE} MASTER_SITE_SUBDIR= ALPHA/wine/development @@ -22,6 +22,8 @@ MAN1= wine.1 ONLY_FOR_ARCHS= i386 +CFLAGS+= -g + pre-configure: @${ECHO} "WINE_INI_GLOBAL \"${PREFIX}/etc/wine.conf\"" \ >> ${WRKSRC}/autoconf.h @@ -34,7 +36,14 @@ -@${MKDIR} ${PREFIX}/etc 2>/dev/null [ -f ${PREFIX}/etc/wine.conf ] \ || ${CP} ${WRKSRC}/wine.ini ${PREFIX}/etc/wine.conf - ${CP} ${WRKSRC}/wine.sym ${PREFIX}/etc - ${CP} ${WRKSRC}/documentation/wine.man ${PREFIX}/man/man1/wine.1 + ${INSTALL_DATA} ${WRKSRC}/wine.sym ${PREFIX}/etc + ${INSTALL_DATA} ${WRKSRC}/documentation/wine.man ${PREFIX}/man/man1/wine.1 + -@${MKDIR} ${PREFIX}/share/wine 2>/dev/null + ${INSTALL_DATA} ${FILESDIR}/README.patch \ + ${FILESDIR}/patch-3.3-sys-ldtshare \ + ${FILESDIR}/patch-3.3-sys-sigtrap \ + ${PREFIX}/share/wine + ${ECHO} + @${SED} s+/usr/local+${PREFIX}+g <${PKGMESSAGE} .include Index: files/md5 =================================================================== RCS file: /home/cvs/cvs/ports/emulators/wine/files/md5,v retrieving revision 1.46 diff -u -u -r1.46 md5 --- md5 1999/05/03 22:36:11 1.46 +++ md5 1999/09/25 01:31:15 @@ -1 +1 @@ -MD5 (Wine-990426.tar.gz) = ddc5561393b7fedb02b933889658eb7f +MD5 (Wine-990923.tar.gz) = 14f7e147463730e21e4b43f99ed14c40 Index: patches/patch-ad =================================================================== RCS file: /home/cvs/cvs/ports/emulators/wine/patches/patch-ad,v retrieving revision 1.5 diff -u -u -r1.5 patch-ad --- patch-ad 1996/08/13 16:35:27 1.5 +++ patch-ad 1999/09/08 22:06:47 @@ -1,40 +1,27 @@ -*** wine.ini.orig Wed Jul 17 22:00:24 1996 ---- wine.ini Mon Aug 12 19:51:38 1996 -*************** -*** 35,39 **** - Temp=e:\ - Path=c:\windows;c:\windows\system;e:\;e:\test;f:\ -! SymbolTableFile=./wine.sym - - [options] ---- 35,39 ---- - Temp=e:\ - Path=c:\windows;c:\windows\system;e:\;e:\test;f:\ -! SymbolTableFile=/usr/local/etc/wine.sym - - [options] -*************** -*** 54,64 **** - - [serialports] -! Com1=/dev/cua0 -! Com2=/dev/cua1 - Com3=/dev/modem,38400 - Com4=/dev/modem - - [parallelports] -! Lpt1=/dev/lp0 - - [spy] ---- 54,64 ---- - - [serialports] -! Com1=/dev/ttyd0 -! Com2=/dev/ttyd1 - Com3=/dev/modem,38400 - Com4=/dev/modem - - [parallelports] -! Lpt1=/dev/lpt0 - - [spy] +Index: wine.ini +@@ -52,7 +52,7 @@ + System=c:\windows\system + Temp=e:\ + Path=c:\windows;c:\windows\system;e:\;e:\test;f:\ +-SymbolTableFile=./wine.sym ++SymbolTableFile=/usr/local/etc/wine.sym + + # + +@@ -105,13 +105,13 @@ + Default = -adobe-times- + + [serialports] +-Com1=/dev/ttyS0 +-Com2=/dev/ttyS1 ++Com1=/dev/ttyd0 ++Com2=/dev/ttyd1 + Com3=/dev/modem,38400 + Com4=/dev/modem + + [parallelports] +-Lpt1=/dev/lp0 ++Lpt1=/dev/lpt0 + + [spooler] + LPT1:=|lpr Index: pkg/PLIST =================================================================== RCS file: /home/cvs/cvs/ports/emulators/wine/pkg/PLIST,v retrieving revision 1.3 diff -u -u -r1.3 PLIST --- PLIST 1998/08/17 09:43:16 1.3 +++ PLIST 1999/09/09 20:58:35 @@ -1,3 +1,6 @@ bin/wine etc/wine.conf etc/wine.sym +share/wine/README.patch +share/wine/patch-3.3-sys-ldtshare +share/wine/patch-3.3-sys-sigtrap --- /dev/null Sat Sep 25 22:11:00 1999 +++ files/README.patch Sat Sep 25 22:08:04 1999 @@ -0,0 +1,40 @@ +Here are two patches for FreeBSD's kernel that are necessary for wine +(well not strictly _necessary_ but without them parts of it won't work.) +They unfortunately didn't make it into the base distribution in time +for the 3.3 release code freeze... + +patch-3.3-sys-ldtshare: +make kernel threads (rfork(), which wine uses) share one LDT instead of +each having its own. this fixes the same problem that wine also had on +linux kernels before 2.2. + +patch-3.3-sys-sigtrap: +stop wine's SIGTRAP handler from being called in the sigreturn syscall, +causing problems for wine's internal debugger. (it would still +correctly show a crash backtrace but all commands that use single- +stepping failed.) + +Apply as follows: + + (cd /usr/src/sys && patch ) = 4.0. +(see the `wine signal handlers lose %fs on FreeBSD' thread on the +wine-devel list for details, can be read at +http://www.integrita.com/cgi-local/lwgate.pl/WINE-DEVEL/archives/1999-09/Subject/article-15.html +at least i ended up there when i searched it today. yes you could also +simply define FS_sig and GS_sig in wine's include/sig_context.h and be +done with it but the resulting wine would only work on 4.0 and +Alexandre (wine maintainer) didn't like that idea...) + +A LDT patch for -current is at http://www.freebsd.org/~luoqi +(not included since i don't know if it still applies), the sigtrap +patch looks like it could also apply to -current but i haven't tried. +(and if not, i guess a similar fix will be committed soon anyway.) --- /dev/null Sat Sep 25 20:08:17 1999 +++ files/patch-3.3-sys-ldtshare Thu Sep 9 19:28:21 1999 @@ -0,0 +1,656 @@ +Index: alpha/alpha/vm_machdep.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/alpha/alpha/vm_machdep.c,v +retrieving revision 1.7.2.2 +diff -u -u -r1.7.2.2 vm_machdep.c +--- vm_machdep.c 1999/08/29 15:56:38 1.7.2.2 ++++ vm_machdep.c 1999/09/04 20:32:00 +@@ -114,11 +114,15 @@ + * ready to run and return to user mode. + */ + void +-cpu_fork(p1, p2) ++cpu_fork(p1, p2, flags) + register struct proc *p1, *p2; ++ int flags; + { + struct user *up = p2->p_addr; + int i; ++ ++ if ((flags & RFPROC) == 0) ++ return; + + p2->p_md.md_tf = p1->p_md.md_tf; + p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED; +Index: i386/i386/genassym.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/i386/genassym.c,v +retrieving revision 1.62.2.2 +diff -u -u -r1.62.2.2 genassym.c +--- genassym.c 1999/08/29 16:05:40 1.62.2.2 ++++ genassym.c 1999/09/04 20:35:59 +@@ -125,7 +125,9 @@ + printf("#define\tPCB_EBX %#x\n", OS(pcb, pcb_ebx)); + printf("#define\tPCB_EIP %#x\n", OS(pcb, pcb_eip)); + printf("#define\tTSS_ESP0 %#x\n", OS(i386tss, tss_esp0)); ++#ifdef USER_LDT + printf("#define\tPCB_USERLDT %#x\n", OS(pcb, pcb_ldt)); ++#endif + printf("#define\tPCB_FS %#x\n", OS(pcb, pcb_fs)); + printf("#define\tPCB_GS %#x\n", OS(pcb, pcb_gs)); + #ifdef VM86 +Index: i386/i386/machdep.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/i386/machdep.c,v +retrieving revision 1.322.2.8 +diff -u -u -r1.322.2.8 machdep.c +--- machdep.c 1999/08/29 16:05:43 1.322.2.8 ++++ machdep.c 1999/09/04 20:36:02 +@@ -817,15 +827,7 @@ + + #ifdef USER_LDT + /* was i386_user_cleanup() in NetBSD */ +- if (pcb->pcb_ldt) { +- if (pcb == curpcb) { +- lldt(_default_ldt); +- currentldt = _default_ldt; +- } +- kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, +- pcb->pcb_ldt_len * sizeof(union descriptor)); +- pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0; +- } ++ user_ldt_free(pcb); + #endif + + bzero((char *)regs, sizeof(struct trapframe)); +Index: i386/i386/sys_machdep.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/i386/sys_machdep.c,v +retrieving revision 1.38.2.1 +diff -u -u -r1.38.2.1 sys_machdep.c +--- sys_machdep.c 1999/08/29 16:05:55 1.38.2.1 ++++ sys_machdep.c 1999/09/04 20:36:09 +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -65,7 +66,6 @@ + + + #ifdef USER_LDT +-void set_user_ldt __P((struct pcb *pcb)); + static int i386_get_ldt __P((struct proc *, char *)); + static int i386_set_ldt __P((struct proc *, char *)); + #endif +@@ -259,13 +259,72 @@ + void + set_user_ldt(struct pcb *pcb) + { +- gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)pcb->pcb_ldt; +- gdt_segs[GUSERLDT_SEL].ssd_limit = (pcb->pcb_ldt_len * sizeof(union descriptor)) - 1; +- ssdtosd(&gdt_segs[GUSERLDT_SEL], &gdt[GUSERLDT_SEL].sd); ++ struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; ++#ifdef SMP ++ gdt[cpuid * NGDT + GUSERLDT_SEL].sd = pcb_ldt->ldt_sd; ++#else ++ gdt[GUSERLDT_SEL].sd = pcb_ldt->ldt_sd; ++#endif + lldt(GSEL(GUSERLDT_SEL, SEL_KPL)); + currentldt = GSEL(GUSERLDT_SEL, SEL_KPL); + } + ++struct pcb_ldt * ++user_ldt_alloc(struct pcb *pcb, int len) ++{ ++ struct pcb_ldt *pcb_ldt, *new_ldt; ++ ++ MALLOC(new_ldt, struct pcb_ldt *, sizeof(struct pcb_ldt), ++ M_SUBPROC, M_WAITOK); ++ if (new_ldt == NULL) ++ return NULL; ++ ++ new_ldt->ldt_len = len = NEW_MAX_LD(len); ++ new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map, ++ len * sizeof(union descriptor)); ++ if (new_ldt->ldt_base == NULL) { ++ FREE(new_ldt, M_SUBPROC); ++ return NULL; ++ } ++ new_ldt->ldt_refcnt = 1; ++ new_ldt->ldt_active = 0; ++ ++ gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base; ++ gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1; ++ ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd); ++ ++ if ((pcb_ldt = pcb->pcb_ldt)) { ++ if (len > pcb_ldt->ldt_len) ++ len = pcb_ldt->ldt_len; ++ bcopy(pcb_ldt->ldt_base, new_ldt->ldt_base, ++ len * sizeof(union descriptor)); ++ } else { ++ bcopy(ldt, new_ldt->ldt_base, sizeof(ldt)); ++ } ++ return new_ldt; ++} ++ ++void ++user_ldt_free(struct pcb *pcb) ++{ ++ struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; ++ ++ if (pcb_ldt == NULL) ++ return; ++ ++ if (pcb == curpcb) { ++ lldt(_default_ldt); ++ currentldt = _default_ldt; ++ } ++ ++ if (--pcb_ldt->ldt_refcnt == 0) { ++ kmem_free(kernel_map, (vm_offset_t)pcb_ldt->ldt_base, ++ pcb_ldt->ldt_len * sizeof(union descriptor)); ++ FREE(pcb_ldt, M_SUBPROC); ++ } ++ pcb->pcb_ldt = NULL; ++} ++ + struct i386_get_ldt_args { + int start; + union descriptor *desc; +@@ -279,6 +338,7 @@ + { + int error = 0; + struct pcb *pcb = &p->p_addr->u_pcb; ++ struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; + int nldt, num; + union descriptor *lp; + int s; +@@ -299,10 +359,10 @@ + + s = splhigh(); + +- if (pcb->pcb_ldt) { +- nldt = pcb->pcb_ldt_len; ++ if (pcb_ldt) { ++ nldt = pcb_ldt->ldt_len; + num = min(uap->num, nldt); +- lp = &((union descriptor *)(pcb->pcb_ldt))[uap->start]; ++ lp = &((union descriptor *)(pcb_ldt->ldt_base))[uap->start]; + } else { + nldt = sizeof(ldt)/sizeof(ldt[0]); + num = min(uap->num, nldt); +@@ -335,6 +395,7 @@ + int error = 0, i, n; + int largest_ld; + struct pcb *pcb = &p->p_addr->u_pcb; ++ struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; + int s; + struct i386_set_ldt_args ua, *uap; + +@@ -348,36 +409,37 @@ + uap->start, uap->num, (void *)uap->desc); + #endif + +- /* verify range of descriptors to modify */ +- if ((uap->start < 0) || (uap->start >= MAX_LD) || (uap->num < 0) || +- (uap->num > MAX_LD)) +- { ++ /* verify range of descriptors to modify */ ++ if ((uap->start < 0) || (uap->start >= MAX_LD) || (uap->num < 0) || ++ (uap->num > MAX_LD)) ++ { ++ return(EINVAL); ++ } ++ largest_ld = uap->start + uap->num - 1; ++ if (largest_ld >= MAX_LD) + return(EINVAL); +- } +- largest_ld = uap->start + uap->num - 1; +- if (largest_ld >= MAX_LD) +- return(EINVAL); +- +- /* allocate user ldt */ +- if (!pcb->pcb_ldt || (largest_ld >= pcb->pcb_ldt_len)) { +- union descriptor *new_ldt = (union descriptor *)kmem_alloc( +- kernel_map, SIZE_FROM_LARGEST_LD(largest_ld)); +- if (new_ldt == NULL) { +- return ENOMEM; +- } +- if (pcb->pcb_ldt) { +- bcopy(pcb->pcb_ldt, new_ldt, pcb->pcb_ldt_len +- * sizeof(union descriptor)); +- kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, +- pcb->pcb_ldt_len * sizeof(union descriptor)); +- } else { +- bcopy(ldt, new_ldt, sizeof(ldt)); +- } +- pcb->pcb_ldt = (caddr_t)new_ldt; +- pcb->pcb_ldt_len = NEW_MAX_LD(largest_ld); +- if (pcb == curpcb) +- set_user_ldt(pcb); +- } ++ ++ /* allocate user ldt */ ++ if (!pcb_ldt || (largest_ld >= pcb_ldt->ldt_len)) { ++ struct pcb_ldt *new_ldt = user_ldt_alloc(pcb, largest_ld); ++ if (new_ldt == NULL) { ++ return ENOMEM; ++ } ++ if (pcb_ldt) { ++ pcb_ldt->ldt_sd = new_ldt->ldt_sd; ++#ifdef SMP ++ /* signal other cpus to reload ldt */ ++#endif ++ kmem_free(kernel_map, (vm_offset_t)pcb_ldt->ldt_base, ++ pcb_ldt->ldt_len * sizeof(union descriptor)); ++ pcb_ldt->ldt_base = new_ldt->ldt_base; ++ pcb_ldt->ldt_len = new_ldt->ldt_len; ++ FREE(new_ldt, M_SUBPROC); ++ } else ++ pcb->pcb_ldt = pcb_ldt = new_ldt; ++ if (pcb == curpcb) ++ set_user_ldt(pcb); ++ } + + /* Check descriptors for access violations */ + for (i = 0, n = uap->start; i < uap->num; i++, n++) { +@@ -388,70 +450,70 @@ + return(error); + + switch (desc.sd.sd_type) { +- case SDT_SYSNULL: /* system null */ +- desc.sd.sd_p = 0; +- break; +- case SDT_SYS286TSS: /* system 286 TSS available */ +- case SDT_SYSLDT: /* system local descriptor table */ +- case SDT_SYS286BSY: /* system 286 TSS busy */ +- case SDT_SYSTASKGT: /* system task gate */ +- case SDT_SYS286IGT: /* system 286 interrupt gate */ +- case SDT_SYS286TGT: /* system 286 trap gate */ +- case SDT_SYSNULL2: /* undefined by Intel */ +- case SDT_SYS386TSS: /* system 386 TSS available */ +- case SDT_SYSNULL3: /* undefined by Intel */ +- case SDT_SYS386BSY: /* system 386 TSS busy */ +- case SDT_SYSNULL4: /* undefined by Intel */ +- case SDT_SYS386IGT: /* system 386 interrupt gate */ +- case SDT_SYS386TGT: /* system 386 trap gate */ +- case SDT_SYS286CGT: /* system 286 call gate */ +- case SDT_SYS386CGT: /* system 386 call gate */ +- /* I can't think of any reason to allow a user proc +- * to create a segment of these types. They are +- * for OS use only. +- */ +- return EACCES; +- +- /* memory segment types */ +- case SDT_MEMEC: /* memory execute only conforming */ +- case SDT_MEMEAC: /* memory execute only accessed conforming */ +- case SDT_MEMERC: /* memory execute read conforming */ +- case SDT_MEMERAC: /* memory execute read accessed conforming */ +- /* Must be "present" if executable and conforming. */ +- if (desc.sd.sd_p == 0) +- return (EACCES); ++ case SDT_SYSNULL: /* system null */ ++ desc.sd.sd_p = 0; + break; +- case SDT_MEMRO: /* memory read only */ +- case SDT_MEMROA: /* memory read only accessed */ +- case SDT_MEMRW: /* memory read write */ +- case SDT_MEMRWA: /* memory read write accessed */ +- case SDT_MEMROD: /* memory read only expand dwn limit */ +- case SDT_MEMRODA: /* memory read only expand dwn lim accessed */ +- case SDT_MEMRWD: /* memory read write expand dwn limit */ +- case SDT_MEMRWDA: /* memory read write expand dwn lim acessed */ +- case SDT_MEME: /* memory execute only */ +- case SDT_MEMEA: /* memory execute only accessed */ +- case SDT_MEMER: /* memory execute read */ +- case SDT_MEMERA: /* memory execute read accessed */ ++ case SDT_SYS286TSS: /* system 286 TSS available */ ++ case SDT_SYSLDT: /* system local descriptor table */ ++ case SDT_SYS286BSY: /* system 286 TSS busy */ ++ case SDT_SYSTASKGT: /* system task gate */ ++ case SDT_SYS286IGT: /* system 286 interrupt gate */ ++ case SDT_SYS286TGT: /* system 286 trap gate */ ++ case SDT_SYSNULL2: /* undefined by Intel */ ++ case SDT_SYS386TSS: /* system 386 TSS available */ ++ case SDT_SYSNULL3: /* undefined by Intel */ ++ case SDT_SYS386BSY: /* system 386 TSS busy */ ++ case SDT_SYSNULL4: /* undefined by Intel */ ++ case SDT_SYS386IGT: /* system 386 interrupt gate */ ++ case SDT_SYS386TGT: /* system 386 trap gate */ ++ case SDT_SYS286CGT: /* system 286 call gate */ ++ case SDT_SYS386CGT: /* system 386 call gate */ ++ /* I can't think of any reason to allow a user proc ++ * to create a segment of these types. They are ++ * for OS use only. ++ */ ++ return EACCES; ++ ++ /* memory segment types */ ++ case SDT_MEMEC: /* memory execute only conforming */ ++ case SDT_MEMEAC: /* memory execute only accessed conforming */ ++ case SDT_MEMERC: /* memory execute read conforming */ ++ case SDT_MEMERAC: /* memory execute read accessed conforming */ ++ /* Must be "present" if executable and conforming. */ ++ if (desc.sd.sd_p == 0) ++ return (EACCES); ++ break; ++ case SDT_MEMRO: /* memory read only */ ++ case SDT_MEMROA: /* memory read only accessed */ ++ case SDT_MEMRW: /* memory read write */ ++ case SDT_MEMRWA: /* memory read write accessed */ ++ case SDT_MEMROD: /* memory read only expand dwn limit */ ++ case SDT_MEMRODA: /* memory read only expand dwn lim accessed */ ++ case SDT_MEMRWD: /* memory read write expand dwn limit */ ++ case SDT_MEMRWDA: /* memory read write expand dwn lim acessed */ ++ case SDT_MEME: /* memory execute only */ ++ case SDT_MEMEA: /* memory execute only accessed */ ++ case SDT_MEMER: /* memory execute read */ ++ case SDT_MEMERA: /* memory execute read accessed */ + break; + default: + return(EINVAL); + /*NOTREACHED*/ + } + +- /* Only user (ring-3) descriptors may be present. */ +- if ((desc.sd.sd_p != 0) && (desc.sd.sd_dpl != SEL_UPL)) +- return (EACCES); ++ /* Only user (ring-3) descriptors may be present. */ ++ if ((desc.sd.sd_p != 0) && (desc.sd.sd_dpl != SEL_UPL)) ++ return (EACCES); + } + + s = splhigh(); + + /* Fill in range */ +- error = copyin(uap->desc, +- &((union descriptor *)(pcb->pcb_ldt))[uap->start], +- uap->num * sizeof(union descriptor)); +- if (!error) +- p->p_retval[0] = uap->start; ++ error = copyin(uap->desc, ++ &((union descriptor *)(pcb_ldt->ldt_base))[uap->start], ++ uap->num * sizeof(union descriptor)); ++ if (!error) ++ p->p_retval[0] = uap->start; + + splx(s); + return(error); +Index: i386/i386/vm_machdep.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/i386/vm_machdep.c,v +retrieving revision 1.115.2.1 +diff -u -u -r1.115.2.1 vm_machdep.c +--- vm_machdep.c 1999/08/29 16:05:58 1.115.2.1 ++++ vm_machdep.c 1999/09/04 20:36:15 +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -68,6 +69,9 @@ + #include + #include + #endif ++#ifdef USER_LDT ++#include ++#endif + + #include + #include +@@ -113,10 +117,29 @@ + * ready to run and return to user mode. + */ + void +-cpu_fork(p1, p2) ++cpu_fork(p1, p2, flags) + register struct proc *p1, *p2; ++ int flags; + { +- struct pcb *pcb2 = &p2->p_addr->u_pcb; ++ struct pcb *pcb2; ++ ++ if ((flags & RFPROC) == 0) { ++#ifdef USER_LDT ++ if ((flags & RFMEM) == 0) { ++ /* unshare user LDT */ ++ struct pcb *pcb1 = &p1->p_addr->u_pcb; ++ struct pcb_ldt *pcb_ldt = pcb1->pcb_ldt; ++ if (pcb_ldt && pcb_ldt->ldt_refcnt > 1) { ++ pcb_ldt = user_ldt_alloc(pcb1,pcb_ldt->ldt_len); ++ user_ldt_free(pcb1); ++ pcb1->pcb_ldt = pcb_ldt; ++ if (pcb1 == curpcb) ++ set_user_ldt(pcb1); ++ } ++ } ++#endif ++ return; ++ } + + #if NNPX > 0 + /* Ensure that p1's pcb is up to date. */ +@@ -126,6 +149,7 @@ + + /* Copy p1's pcb. */ + p2->p_addr->u_pcb = p1->p_addr->u_pcb; ++ pcb2 = &p2->p_addr->u_pcb; + + /* + * Create a new fresh stack for the new process. +@@ -153,7 +177,6 @@ + pcb2->pcb_eip = (int)fork_trampoline; + /* + * pcb2->pcb_ldt: duplicated below, if necessary. +- * pcb2->pcb_ldt_len: cloned above. + * pcb2->pcb_savefpu: cloned above. + * pcb2->pcb_flags: cloned above (always 0 here?). + * pcb2->pcb_onfault: cloned above (always NULL here?). +@@ -172,12 +195,12 @@ + #ifdef USER_LDT + /* Copy the LDT, if necessary. */ + if (pcb2->pcb_ldt != 0) { +- union descriptor *new_ldt; +- size_t len = pcb2->pcb_ldt_len * sizeof(union descriptor); +- +- new_ldt = (union descriptor *)kmem_alloc(kernel_map, len); +- bcopy(pcb2->pcb_ldt, new_ldt, len); +- pcb2->pcb_ldt = (caddr_t)new_ldt; ++ if (flags & RFMEM) { ++ pcb2->pcb_ldt->ldt_refcnt++; ++ } else { ++ pcb2->pcb_ldt = user_ldt_alloc(pcb2, ++ pcb2->pcb_ldt->ldt_len); ++ } + } + #endif + +@@ -235,15 +258,7 @@ + } + #endif + #ifdef USER_LDT +- if (pcb->pcb_ldt != 0) { +- if (pcb == curpcb) { +- lldt(_default_ldt); +- currentldt = _default_ldt; +- } +- kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, +- pcb->pcb_ldt_len * sizeof(union descriptor)); +- pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0; +- } ++ user_ldt_free(pcb); + #endif + cnt.v_swtch++; + cpu_switch(p); +Index: i386/include/pcb.h +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/include/pcb.h,v +retrieving revision 1.26.2.1 +diff -u -u -r1.26.2.1 pcb.h +--- pcb.h 1999/08/29 16:06:43 1.26.2.1 ++++ pcb.h 1999/09/04 20:36:29 +@@ -53,8 +53,11 @@ + int pcb_esp; + int pcb_ebx; + int pcb_eip; +- caddr_t pcb_ldt; /* per process (user) LDT */ +- int pcb_ldt_len; /* number of LDT entries */ ++#ifdef USER_LDT ++ struct pcb_ldt *pcb_ldt; /* per process (user) LDT */ ++#else ++ struct pcb_ldt *pcb_ldt_dontuse; ++#endif + struct save87 pcb_savefpu; /* floating point state for 287/387 */ + u_char pcb_flags; + #define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */ +@@ -71,7 +74,7 @@ + #else + struct pcb_ext *pcb_ext_dontuse; + #endif +- u_long __pcb_spare[1]; /* adjust to avoid core dump size changes */ ++ u_long __pcb_spare[2]; /* adjust to avoid core dump size changes */ + }; + + /* +Index: i386/include/pcb_ext.h +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/include/pcb_ext.h,v +retrieving revision 1.1.2.1 +diff -u -u -r1.1.2.1 pcb_ext.h +--- pcb_ext.h 1999/08/29 16:06:44 1.1.2.1 ++++ pcb_ext.h 1999/09/04 20:36:29 +@@ -43,4 +43,22 @@ + struct vm86_kernel ext_vm86; /* vm86 area */ + }; + ++struct pcb_ldt { ++ caddr_t ldt_base; ++ int ldt_len; ++ int ldt_refcnt; ++ u_long ldt_active; ++ struct segment_descriptor ldt_sd; ++}; ++ ++#ifdef KERNEL ++ ++#ifdef USER_LDT ++void set_user_ldt __P((struct pcb *)); ++struct pcb_ldt *user_ldt_alloc __P((struct pcb *, int)); ++void user_ldt_free __P((struct pcb *)); ++#endif ++ ++#endif ++ + #endif /* _I386_PCB_EXT_H_ */ +Index: kern/kern_fork.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/kern/kern_fork.c,v +retrieving revision 1.54.2.4 +diff -u -u -r1.54.2.4 kern_fork.c +--- kern_fork.c 1999/08/29 16:25:59 1.54.2.4 ++++ kern_fork.c 1999/09/04 20:38:06 +@@ -162,16 +162,7 @@ + */ + if ((flags & RFPROC) == 0) { + +- /* +- * Divorce the memory, if it is shared, essentially +- * this changes shared memory amongst threads, into +- * COW locally. +- */ +- if ((flags & RFMEM) == 0) { +- if (p1->p_vmspace->vm_refcnt > 1) { +- vmspace_unshare(p1); +- } +- } ++ vm_fork(p1, 0, flags); + + /* + * Close all file descriptors. +Index: pc98/i386/machdep.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/pc98/i386/machdep.c,v +retrieving revision 1.105.2.7 +diff -u -u -r1.105.2.7 machdep.c +--- machdep.c 1999/08/29 16:31:03 1.105.2.7 ++++ machdep.c 1999/09/04 20:41:41 +@@ -830,15 +830,7 @@ + + #ifdef USER_LDT + /* was i386_user_cleanup() in NetBSD */ +- if (pcb->pcb_ldt) { +- if (pcb == curpcb) { +- lldt(_default_ldt); +- currentldt = _default_ldt; +- } +- kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, +- pcb->pcb_ldt_len * sizeof(union descriptor)); +- pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0; +- } ++ user_ldt_free(pcb); + #endif + + bzero((char *)regs, sizeof(struct trapframe)); +Index: sys/proc.h +=================================================================== +RCS file: /home/cvs/cvs/src/sys/sys/proc.h,v +retrieving revision 1.66.2.5 +diff -u -u -r1.66.2.5 proc.h +--- proc.h 1999/08/29 16:32:36 1.66.2.5 ++++ proc.h 1999/09/04 20:42:43 +@@ -375,7 +375,7 @@ + + void cpu_exit __P((struct proc *)) __dead2; + void exit1 __P((struct proc *, int)) __dead2; +-void cpu_fork __P((struct proc *, struct proc *)); ++void cpu_fork __P((struct proc *, struct proc *, int)); + int fork1 __P((struct proc *, int)); + int trace_req __P((struct proc *)); + void cpu_wait __P((struct proc *)); +Index: vm/vm_glue.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/vm/vm_glue.c,v +retrieving revision 1.80.2.3 +diff -u -u -r1.80.2.3 vm_glue.c +--- vm_glue.c 1999/08/29 16:33:31 1.80.2.3 ++++ vm_glue.c 1999/09/04 20:43:01 +@@ -208,6 +208,21 @@ + { + register struct user *up; + ++ if ((flags & RFPROC) == 0) { ++ /* ++ * Divorce the memory, if it is shared, essentially ++ * this changes shared memory amongst threads, into ++ * COW locally. ++ */ ++ if ((flags & RFMEM) == 0) { ++ if (p1->p_vmspace->vm_refcnt > 1) { ++ vmspace_unshare(p1); ++ } ++ } ++ cpu_fork(p1, p2, flags); ++ return; ++ } ++ + if (flags & RFMEM) { + p2->p_vmspace = p1->p_vmspace; + p1->p_vmspace->vm_refcnt++; +@@ -259,7 +274,7 @@ + * cpu_fork will copy and update the pcb, set up the kernel stack, + * and make the child ready to run. + */ +- cpu_fork(p1, p2); ++ cpu_fork(p1, p2, flags); + } + + /* --- /dev/null Sat Sep 25 20:08:17 1999 +++ files/patch-3.3-sys-sigtrap Fri Sep 10 16:44:29 1999 @@ -0,0 +1,30 @@ +Index: i386/i386/trap.c +=================================================================== +RCS file: /home/cvs/cvs/src/sys/i386/i386/trap.c,v +retrieving revision 1.133.2.1 +diff -u -u -r1.133.2.1 trap.c +--- trap.c 1999/08/29 16:05:56 1.133.2.1 ++++ trap.c 1999/09/10 14:42:21 +@@ -1041,6 +1084,7 @@ + int error; + int args[8]; + u_int code; ++ int tracedsyscall = ((frame.tf_eflags & PSL_T) && !(frame.tf_eflags & PSL_VM)); + + #ifdef DIAGNOSTIC + if (ISPL(frame.tf_cs) != SEL_UPL) +@@ -1135,10 +1179,12 @@ + break; + } + +- if ((frame.tf_eflags & PSL_T) && !(frame.tf_eflags & PSL_VM)) { ++ if (tracedsyscall) { + /* Traced syscall. */ + frame.tf_eflags &= ~PSL_T; +- trapsignal(p, SIGTRAP, 0); ++ /* tell the signal handler this is a trace trap */ ++ frame.tf_trapno = T_TRCTRAP; ++ trapsignal(p, SIGTRAP, T_TRCTRAP); + } + + userret(p, &frame, sticks); --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-ba Sat Sep 25 19:34:53 1999 @@ -0,0 +1,25 @@ +Index: Make.rules.in +=================================================================== +RCS file: /home/wine/wine/Make.rules.in,v +retrieving revision 1.17 +diff -u -u -r1.17 Make.rules.in +--- Make.rules.in 1999/08/15 12:45:53 1.17 ++++ Make.rules.in 1999/09/24 23:39:10 +@@ -21,7 +21,7 @@ + CC = @CC@ + CPP = @CPP@ + CFLAGS = @CFLAGS@ +-OPTIONS = @OPTIONS@ -D_REENTRANT ++OPTIONS = @OPTIONS@ -D_REENTRANT -D_THREAD_SAFE + X_CFLAGS = @X_CFLAGS@ + X_LIBS = @X_LIBS@ + XLIB = @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@ +@@ -81,7 +81,7 @@ + + # Implicit rules + +-.SUFFIXES: ++#.SUFFIXES: + .SUFFIXES: .rc .res .spec .spec.c .spec.o .glue.c $(SUFFIXES) + + .c.o: --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-bd Sat Sep 25 19:34:53 1999 @@ -0,0 +1,42 @@ +Index: dlls/ntdll/exception.c +=================================================================== +RCS file: /home/wine/wine/dlls/ntdll/exception.c,v +retrieving revision 1.12 +diff -u -u -r1.12 exception.c +--- dlls/ntdll/exception.c 1999/09/22 15:25:45 1.12 ++++ dlls/ntdll/exception.c 1999/09/24 23:39:25 +@@ -31,6 +31,34 @@ + # define GET_IP(context) ((LPVOID)0) + #endif /* __i386__ */ + ++#ifdef __FreeBSD__ ++/* translate BSD's sigcontext sc_trapno for TRAP_sig */ ++int xlatebsdtrapno(int t) ++{ ++ switch (t) ++ { ++ case T_PRIVINFLT: return 6; ++ case T_BPTFLT: return 3; ++ case T_ARITHTRAP: return 16; ++ case T_PROTFLT: return 13; ++ case T_TRCTRAP: return 1; ++ case T_PAGEFLT: return 14; ++ case T_ALIGNFLT: return 17; ++ case T_DIVIDE: return 0; ++ case T_NMI: return 2; ++ case T_OFLOW: return 4; ++ case T_BOUND: return 5; ++ case T_DNA: return 7; ++ case T_FPOPFLT: return 9; ++ case T_TSSFLT: return 10; ++ case T_SEGNPFLT: return 11; ++ case T_STKFLT: return 12; ++ case T_RESERVED: return 15; ++ default: return 18; ++ } ++} ++#endif ++ + /* Default hook for built-in debugger */ + static DWORD default_hook( EXCEPTION_RECORD *rec, CONTEXT *ctx, BOOL first ) + { --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-bf Sat Sep 25 19:34:53 1999 @@ -0,0 +1,16 @@ +Index: include/sig_context.h +=================================================================== +RCS file: /home/wine/wine/include/sig_context.h,v +retrieving revision 1.15 +diff -u -u -r1.15 sig_context.h +--- include/sig_context.h 1999/09/05 16:26:12 1.15 ++++ include/sig_context.h 1999/09/24 23:39:26 +@@ -171,6 +171,8 @@ + #define EFL_sig(context) ((context)->sc_efl) + /* FreeBSD, see i386/i386/traps.c::trap_pfault va->err kludge */ + #define CR2_sig(context) ((context)->sc_err) ++int xlatebsdtrapno(int t); ++#define TRAP_sig(context) ((long)xlatebsdtrapno((context)->sc_trapno)) + #endif + + --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-bg Sat Sep 25 19:34:53 1999 @@ -0,0 +1,48 @@ +Index: loader/signal.c +=================================================================== +RCS file: /home/wine/wine/loader/signal.c,v +retrieving revision 1.16 +diff -u -u -r1.16 signal.c +--- loader/signal.c 1999/08/01 14:54:16 1.16 ++++ loader/signal.c 1999/09/24 23:39:26 +@@ -84,11 +84,7 @@ + } + #endif /* linux && __i386__ */ + +-/* Signal stack */ + +-static char SIGNAL_Stack[16384]; +- +- + /********************************************************************** + * SIGNAL_SetHandler + */ +@@ -98,6 +94,9 @@ + + #if defined(linux) && defined(__i386__) + ++ /* Signal stack */ ++ static char SIGNAL_Stack[16384]; ++ + struct kernel_sigaction sig_act; + sig_act.sa_handler = func; + sig_act.sa_flags = SA_RESTART | SA_NOMASK; +@@ -140,18 +139,6 @@ + */ + BOOL SIGNAL_Init(void) + { +-#ifdef HAVE_WORKING_SIGALTSTACK +- struct sigaltstack ss; +- ss.ss_sp = SIGNAL_Stack; +- ss.ss_size = sizeof(SIGNAL_Stack); +- ss.ss_flags = 0; +- if (sigaltstack(&ss, NULL) < 0) +- { +- perror("sigaltstack"); +- /* fall through on error and try it differently */ +- } +-#endif /* HAVE_SIGALTSTACK */ +- + /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */ + signal (SIGPIPE, SIG_IGN); + /* automatic child reaping to avoid zombies */ --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-bi Sat Sep 25 19:34:53 1999 @@ -0,0 +1,35 @@ +Index: scheduler/sysdeps.c +=================================================================== +RCS file: /home/wine/wine/scheduler/sysdeps.c,v +retrieving revision 1.16 +diff -u -u -r1.16 sysdeps.c +--- scheduler/sysdeps.c 1999/09/05 12:32:06 1.16 ++++ scheduler/sysdeps.c 1999/09/24 23:39:29 +@@ -112,6 +112,9 @@ + */ + void SYSDEPS_SetCurThread( TEB *teb ) + { ++#ifdef HAVE_WORKING_SIGALTSTACK ++ struct sigaltstack ss; ++#endif /* HAVE_SIGALTSTACK */ + #if defined(__i386__) + /* On the i386, the current thread is in the %fs register */ + SET_FS( teb->teb_sel ); +@@ -117,6 +125,17 @@ + /* On non-i386 Solaris, we use the LWP private pointer */ + _lwp_setprivate( teb ); + #endif ++#ifdef HAVE_WORKING_SIGALTSTACK ++ if ((ss.ss_sp = teb->signal_stack)) { ++ ss.ss_size = SIGNAL_STACK_SIZE; ++ ss.ss_flags = 0; ++ if (sigaltstack(&ss, NULL) < 0) ++ { ++ perror("SYSDEPS_SetCurThread sigaltstack"); ++ /* fall through on error and try it differently */ ++ } ++ } ++#endif /* HAVE_SIGALTSTACK */ + + init_done = 1; /* now we can use threading routines */ + } --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-bj Sat Sep 25 19:34:53 1999 @@ -0,0 +1,16 @@ +Index: scheduler/thread.c +=================================================================== +RCS file: /home/wine/wine/scheduler/thread.c,v +retrieving revision 1.44 +diff -u -u -r1.44 thread.c +--- scheduler/thread.c 1999/09/20 18:45:28 1.44 ++++ scheduler/thread.c 1999/09/24 23:39:30 +@@ -194,6 +194,8 @@ + + if (CLIENT_InitThread()) return NULL; + if (!THREAD_InitTEB( &initial_teb, 0, TRUE, NULL )) return NULL; ++ /* call this again so it can set the signal stack (allocated by THREAD_InitTEB) */ ++ SYSDEPS_SetCurThread( &initial_teb ); + return &initial_teb; + } + --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-cb Sat Sep 25 19:34:53 1999 @@ -0,0 +1,36 @@ +Index: controls/button.c +=================================================================== +RCS file: /home/wine/wine/controls/button.c,v +retrieving revision 1.29 +diff -u -u -r1.29 button.c +--- controls/button.c 1999/09/13 16:06:17 1.29 ++++ controls/button.c 1999/09/24 23:39:12 +@@ -150,11 +150,12 @@ + SetCapture( hWnd ); + SetFocus( hWnd ); + SendMessageA( hWnd, BM_SETSTATE, TRUE, 0 ); ++ infoPtr->state |= BUTTON_BTNPRESSED; + break; + + case WM_LBUTTONUP: +- /* FIXME: real windows uses extra flags in the status for this */ +- if (GetCapture() != hWnd) break; ++ if (!(infoPtr->state & BUTTON_BTNPRESSED)) break; ++ infoPtr->state &= BUTTON_NSTATES; + ReleaseCapture(); + if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) break; + SendMessageA( hWnd, BM_SETSTATE, FALSE, 0 ); +@@ -188,6 +189,13 @@ + SendMessageA( hWnd, BM_SETSTATE, PtInRect(&rect, pt), 0 ); + } + break; ++ ++ case WM_CAPTURECHANGED: ++ if (!(infoPtr->state & BUTTON_BTNPRESSED)) break; ++ infoPtr->state &= BUTTON_NSTATES; ++ if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) break; ++ SendMessageA( hWnd, BM_SETSTATE, FALSE, 0 ); ++ break; + + case WM_NCHITTEST: + if(style == BS_GROUPBOX) return HTTRANSPARENT; --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-ce Sat Sep 25 19:34:53 1999 @@ -0,0 +1,19 @@ +Index: include/button.h +=================================================================== +RCS file: /home/wine/wine/include/button.h,v +retrieving revision 1.4 +diff -u -u -r1.4 button.h +--- include/button.h 1999/04/15 15:49:36 1.4 ++++ include/button.h 1999/09/24 23:39:25 +@@ -26,6 +26,11 @@ + #define BUTTON_3STATE 0x02 + #define BUTTON_HIGHLIGHTED 0x04 + #define BUTTON_HASFOCUS 0x08 ++#define BUTTON_NSTATES 0x0F ++ /* undocumented flags */ ++#define BUTTON_BTNPRESSED 0x40 ++#define BUTTON_UNKNOWN2 0x20 ++#define BUTTON_UNKNOWN3 0x10 + + #define BUTTON_STATE(hwnd) ((WIN_FindWndPtr(hwnd))->wExtra[0]) + --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-ch Sat Sep 25 19:34:53 1999 @@ -0,0 +1,325 @@ +Index: objects/brush.c +=================================================================== +RCS file: /home/wine/wine/objects/brush.c,v +retrieving revision 1.16 +diff -u -u -r1.16 brush.c +--- objects/brush.c 1999/05/23 10:25:26 1.16 ++++ objects/brush.c 1999/09/24 23:39:28 +@@ -14,56 +14,103 @@ + + + /*********************************************************************** +- * CreateBrushIndirect16 (GDI.50) ++ * BRUSH_CopyDIB (internal - do the Dib creation) + */ +-HBRUSH16 WINAPI CreateBrushIndirect16( const LOGBRUSH16 * brush ) ++BOOL BRUSH_CopyDIB( LOGBRUSH * logbrush, BITMAPINFO *info, UINT coloruse) ++{ ++ BITMAPINFO *newInfo; ++ INT size; ++ ++ logbrush->lbStyle = BS_DIBPATTERN; ++ logbrush->lbColor = coloruse; ++ logbrush->lbHatch = 0; ++ ++ /* Make a copy of the bitmap */ ++ ++ if (info->bmiHeader.biCompression) ++ size = info->bmiHeader.biSizeImage; ++ else ++ size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, ++ info->bmiHeader.biHeight, ++ info->bmiHeader.biBitCount); ++ size += DIB_BitmapInfoSize( info, coloruse ); ++ ++ if (!(logbrush->lbHatch = (INT)GlobalAlloc16( GMEM_MOVEABLE, size ))) ++ { ++ return FALSE; ++ } ++ newInfo = (BITMAPINFO *) GlobalLock16( (HGLOBAL16)logbrush->lbHatch ); ++ memcpy( newInfo, info, size ); ++ GlobalUnlock16( (HGLOBAL16)logbrush->lbHatch ); ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * BRUSH_CreateBrush (internal; called by brush creation functions) ++ * do the actual gdi object creation ++ */ ++HBRUSH BRUSH_CreateBrush( const LOGBRUSH * brush ) + { + BRUSHOBJ * brushPtr; +- HBRUSH16 hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC ); ++ HBRUSH hbrush; ++ hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC ); + if (!hbrush) return 0; + brushPtr = (BRUSHOBJ *) GDI_HEAP_LOCK( hbrush ); + brushPtr->logbrush.lbStyle = brush->lbStyle; + brushPtr->logbrush.lbColor = brush->lbColor; + brushPtr->logbrush.lbHatch = brush->lbHatch; ++ TRACE("created : %08x style=%x lbHatch=%x\n", hbrush, brush->lbStyle, brush->lbHatch); + GDI_HEAP_UNLOCK( hbrush ); +- TRACE("%04x\n", hbrush); + return hbrush; + } + + + /*********************************************************************** ++ * BRUSH_CreateBitmapBrush (internal; do the bitmap duplication) ++ */ ++HBRUSH BRUSH_CreateBitmapBrush( LOGBRUSH * brush ) ++{ ++ if (brush->lbStyle == BS_PATTERN) ++ { ++ brush->lbHatch = (INT)BITMAP_CopyBitmap( brush->lbHatch ); ++ if (!brush->lbHatch) ++ return 0; ++ } ++ return BRUSH_CreateBrush( brush ); ++} ++ ++/*********************************************************************** + * CreateBrushIndirect32 (GDI32.27) + */ + HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush ) + { +- BRUSHOBJ * brushPtr; +- HBRUSH hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC ); +- if (!hbrush) return 0; +- brushPtr = (BRUSHOBJ *) GDI_HEAP_LOCK( hbrush ); +- brushPtr->logbrush.lbStyle = brush->lbStyle; +- brushPtr->logbrush.lbColor = brush->lbColor; +- brushPtr->logbrush.lbHatch = brush->lbHatch; +- GDI_HEAP_UNLOCK( hbrush ); +- TRACE("%08x\n", hbrush); +- return hbrush; ++ LOGBRUSH logbrush; ++ logbrush.lbStyle = brush->lbStyle; ++ logbrush.lbColor = brush->lbColor; ++ logbrush.lbHatch = brush->lbHatch; ++ return BRUSH_CreateBitmapBrush( &logbrush ); + } + + + /*********************************************************************** +- * CreateHatchBrush16 (GDI.58) ++ * CreateBrushIndirect16 (GDI.50) + */ +-HBRUSH16 WINAPI CreateHatchBrush16( INT16 style, COLORREF color ) ++HBRUSH16 WINAPI CreateBrushIndirect16( const LOGBRUSH16 * brush ) + { +- LOGBRUSH logbrush; +- +- TRACE("%d %06lx\n", style, color ); ++ LOGBRUSH logbrush = { 0, 0, 0 }; ++ logbrush.lbStyle = brush->lbStyle; ++ logbrush.lbColor = brush->lbColor; ++ logbrush.lbHatch = brush->lbHatch; ++ return (HBRUSH16) BRUSH_CreateBitmapBrush( &logbrush ); ++} + +- logbrush.lbStyle = BS_HATCHED; +- logbrush.lbColor = color; +- logbrush.lbHatch = style; + +- if ((style < 0) || (style >= NB_HATCH_STYLES)) return 0; +- return CreateBrushIndirect( &logbrush ); ++/*********************************************************************** ++ * CreateHatchBrush16 (GDI.58) ++ */ ++HBRUSH16 WINAPI CreateHatchBrush16( INT16 style, COLORREF color ) ++{ ++return (HBRUSH16) CreateHatchBrush((INT) style, color); + } + + +@@ -81,7 +128,7 @@ + logbrush.lbHatch = style; + + if ((style < 0) || (style >= NB_HATCH_STYLES)) return 0; +- return CreateBrushIndirect( &logbrush ); ++ return BRUSH_CreateBrush( &logbrush ); + } + + +@@ -90,7 +137,7 @@ + */ + HBRUSH16 WINAPI CreatePatternBrush16( HBITMAP16 hbitmap ) + { +- return (HBRUSH16)CreatePatternBrush( hbitmap ); ++ return (HBRUSH16)CreatePatternBrush( (HBITMAP) hbitmap ); + } + + +@@ -100,53 +147,31 @@ + HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap ) + { + LOGBRUSH logbrush = { BS_PATTERN, 0, 0 }; +- TRACE("%04x\n", hbitmap ); +- +- logbrush.lbHatch = (INT)BITMAP_CopyBitmap( hbitmap ); +- if(!logbrush.lbHatch) +- return 0; +- else +- return CreateBrushIndirect( &logbrush ); ++ TRACE("%04x\n", hbitmap); ++ ++ logbrush.lbHatch = hbitmap ; ++ return BRUSH_CreateBitmapBrush( &logbrush ); + } + + ++ + /*********************************************************************** + * CreateDIBPatternBrush16 (GDI.445) + */ + HBRUSH16 WINAPI CreateDIBPatternBrush16( HGLOBAL16 hbitmap, UINT16 coloruse ) + { + LOGBRUSH logbrush; +- BITMAPINFO *info, *newInfo; +- INT size; ++ BITMAPINFO *info; ++ BOOL ret; + + TRACE("%04x\n", hbitmap ); + +- logbrush.lbStyle = BS_DIBPATTERN; +- logbrush.lbColor = coloruse; +- logbrush.lbHatch = 0; +- +- /* Make a copy of the bitmap */ +- + if (!(info = (BITMAPINFO *)GlobalLock16( hbitmap ))) return 0; +- +- if (info->bmiHeader.biCompression) +- size = info->bmiHeader.biSizeImage; +- else +- size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, +- info->bmiHeader.biHeight, +- info->bmiHeader.biBitCount); +- size += DIB_BitmapInfoSize( info, coloruse ); +- +- if (!(logbrush.lbHatch = (INT16)GlobalAlloc16( GMEM_MOVEABLE, size ))) +- { +- GlobalUnlock16( hbitmap ); +- return 0; +- } +- newInfo = (BITMAPINFO *) GlobalLock16( (HGLOBAL16)logbrush.lbHatch ); +- memcpy( newInfo, info, size ); +- GlobalUnlock16( (HGLOBAL16)logbrush.lbHatch ); ++ ret = BRUSH_CopyDIB( &logbrush, info, coloruse ); + GlobalUnlock16( hbitmap ); +- return CreateBrushIndirect( &logbrush ); ++ ++ if (!ret) return 0; ++ return BRUSH_CreateBrush( &logbrush ); + } + + +@@ -165,42 +190,23 @@ + * + */ + HBRUSH WINAPI CreateDIBPatternBrush( +- HGLOBAL hbitmap, /* Global object containg BITMAPINFO structure */ ++ HGLOBAL hbitmap, /* Global object containing BITMAPINFO structure */ + UINT coloruse /* Specifies color format, if provided */ + ) + { + LOGBRUSH logbrush; +- BITMAPINFO *info, *newInfo; +- INT size; +- ++ BITMAPINFO *info; ++ BOOL ret; ++ + TRACE("%04x\n", hbitmap ); + +- logbrush.lbStyle = BS_DIBPATTERN; +- logbrush.lbColor = coloruse; +- logbrush.lbHatch = 0; +- +- /* Make a copy of the bitmap */ +- + if (!(info = (BITMAPINFO *)GlobalLock( hbitmap ))) return 0; ++ ret = BRUSH_CopyDIB( &logbrush, info, coloruse ); ++ GlobalUnlock( hbitmap ); + +- if (info->bmiHeader.biCompression) +- size = info->bmiHeader.biSizeImage; +- else +- size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, +- info->bmiHeader.biHeight, +- info->bmiHeader.biBitCount); +- size += DIB_BitmapInfoSize( info, coloruse ); ++ if (!ret) return 0; ++ return BRUSH_CreateBrush( &logbrush ); + +- if (!(logbrush.lbHatch = (INT)GlobalAlloc16( GMEM_MOVEABLE, size ))) +- { +- GlobalUnlock16( hbitmap ); +- return 0; +- } +- newInfo = (BITMAPINFO *) GlobalLock16( (HGLOBAL16)logbrush.lbHatch ); +- memcpy( newInfo, info, size ); +- GlobalUnlock16( (HGLOBAL16)logbrush.lbHatch ); +- GlobalUnlock( hbitmap ); +- return CreateBrushIndirect( &logbrush ); + } + + +@@ -223,35 +229,12 @@ + { + BITMAPINFO *info=(BITMAPINFO*)data; + LOGBRUSH logbrush; +- BITMAPINFO *newInfo; +- INT size; + + TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth, + info->bmiHeader.biHeight, info->bmiHeader.biBitCount); +- +- logbrush.lbStyle = BS_DIBPATTERN; +- logbrush.lbColor = coloruse; +- logbrush.lbHatch = 0; + +- /* Make a copy of the bitmap */ +- +- +- if (info->bmiHeader.biCompression) +- size = info->bmiHeader.biSizeImage; +- else +- size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, +- info->bmiHeader.biHeight, +- info->bmiHeader.biBitCount); +- size += DIB_BitmapInfoSize( info, coloruse ); +- +- if (!(logbrush.lbHatch = (INT)GlobalAlloc16( GMEM_MOVEABLE, size ))) +- { +- return 0; +- } +- newInfo = (BITMAPINFO *) GlobalLock16( (HGLOBAL16)logbrush.lbHatch ); +- memcpy( newInfo, info, size ); +- GlobalUnlock16( (HGLOBAL16)logbrush.lbHatch ); +- return CreateBrushIndirect( &logbrush ); ++ if (!BRUSH_CopyDIB( &logbrush, info, coloruse )) return 0; ++ return BRUSH_CreateBrush( &logbrush ); + } + + +@@ -268,7 +251,7 @@ + logbrush.lbColor = color; + logbrush.lbHatch = 0; + +- return CreateBrushIndirect( &logbrush ); ++ return BRUSH_CreateBrush( &logbrush ); + } + + +@@ -285,7 +268,7 @@ + logbrush.lbColor = color; + logbrush.lbHatch = 0; + +- return CreateBrushIndirect( &logbrush ); ++ return BRUSH_CreateBrush( &logbrush ); + } + + --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-cj Sat Sep 25 19:34:53 1999 @@ -0,0 +1,29 @@ +Index: controls/edit.c +=================================================================== +RCS file: /home/wine/wine/controls/edit.c,v +retrieving revision 1.29 +diff -u -u -r1.29 edit.c +--- controls/edit.c 1999/09/10 13:58:34 1.29 ++++ controls/edit.c 1999/09/24 23:39:15 +@@ -3031,14 +3034,14 @@ + if (e == s) + return; + ORDER_INT(s, e); +- hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1)); +- dst = GlobalLock(hdst); ++ hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1)); ++ dst = GlobalLock16(hdst); + lstrcpynA(dst, es->text + s, e - s + 1); +- GlobalUnlock(hdst); +- OpenClipboard(wnd->hwndSelf); +- EmptyClipboard(); +- SetClipboardData(CF_TEXT, hdst); +- CloseClipboard(); ++ GlobalUnlock16(hdst); ++ OpenClipboard16(wnd->hwndSelf); ++ EmptyClipboard16(); ++ SetClipboardData16(CF_TEXT, hdst); ++ CloseClipboard16(); + } + + --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-ck Sat Sep 25 19:34:53 1999 @@ -0,0 +1,192 @@ +Index: windows/clipboard.c +=================================================================== +RCS file: /home/wine/wine/windows/clipboard.c,v +retrieving revision 1.16 +diff -u -u -r1.16 clipboard.c +--- windows/clipboard.c 1999/09/20 15:42:48 1.16 ++++ windows/clipboard.c 1999/09/24 23:39:31 +@@ -171,8 +171,20 @@ + */ + VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime ) + { +- /* idEvent is the HGLOBAL to be deleted */ +- GlobalFree( (HGLOBAL)idEvent ); ++ HANDLE16 hGlobal16 = (HGLOBAL16)idEvent; ++ HANDLE * pGlobalData = (HANDLE *)GlobalLock16( hGlobal16 ); ++ int nElements = GlobalSize16(hGlobal16) / sizeof(HANDLE); ++ int i; ++ ++ /* Free the list of HGLOBAL's */ ++ for (i = 0; i < nElements; i++) ++ { ++ if (pGlobalData[i]) ++ GlobalFree( pGlobalData[i] ); ++ } ++ ++ GlobalUnlock16( hGlobal16 ); ++ GlobalFree16( hGlobal16 ); + } + + /************************************************************************** +@@ -180,6 +192,9 @@ + */ + void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange) + { ++ HANDLE16 hGlobal16 = 0; ++ HANDLE * pGlobalData = 0; ++ + if( (lpFormat->wFormatID >= CF_GDIOBJFIRST && + lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP ) + { +@@ -193,17 +208,22 @@ + if (lpFormat->hData32) + { + DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF ); ++ GlobalUnlock(lpFormat->hData32); ++ ++ /* Release lpFormat->hData32 in the context of the process which created it. ++ * See CLIPBOARD_GlobalFreeProc for more details about this technique. ++ * GlobalFree(lpFormat->hDataSrc32); ++ */ ++ ++ /* hGlobal16 contains an array of HGLOBAL's to be free'd */ ++ hGlobal16 = GlobalAlloc16(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(HANDLE) * 2); ++ pGlobalData = (HANDLE *)GlobalLock16(hGlobal16); ++ pGlobalData[0] = lpFormat->hData32; ++ pGlobalData[1] = lpFormat->hDataSrc32; ++ GlobalUnlock16(hGlobal16); ++ + PostMessageA(hWndClipOwner, WM_TIMER, +- (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc); +- if (lpFormat->hDataSrc32) +- { +- /* Release lpFormat->hData32 in the context of the process which created it. +- * See CLIPBOARD_GlobalFreeProc for more details about this technique. +- * GlobalFree(lpFormat->hDataSrc32); +- */ +- PostMessageA(hWndClipOwner, WM_TIMER, +- (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc); +- } ++ (WPARAM)hGlobal16, (LPARAM)CLIPBOARD_GlobalFreeProc); + + if (lpFormat->hData16) + /* HMETAFILE16 and HMETAFILE32 are apparently the same thing, +@@ -222,22 +242,20 @@ + { + if (lpFormat->hData32) + { ++ /* hGlobal16 contains an array of HGLOBAL's to be free'd */ ++ hGlobal16 = GlobalAlloc16(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(HANDLE) * 2); ++ pGlobalData = (HANDLE *)GlobalLock16(hGlobal16); ++ pGlobalData[0] = lpFormat->hData32; ++ pGlobalData[1] = lpFormat->hDataSrc32; ++ GlobalUnlock16(hGlobal16); ++ + /* Release lpFormat->hData32 in the context of the process which created it. + * See CLIPBOARD_GlobalFreeProc for more details about this technique. + * GlobalFree( lpFormat->hData32 ); + */ + PostMessageA(hWndClipOwner, WM_TIMER, +- (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc); ++ (WPARAM)hGlobal16, (LPARAM)CLIPBOARD_GlobalFreeProc); + } +- if (lpFormat->hDataSrc32) +- { +- /* Release lpFormat->hData32 in the context of the process which created it. +- * See CLIPBOARD_GlobalFreeProc for more details about this technique. +- * GlobalFree(lpFormat->hDataSrc32); +- */ +- PostMessageA(hWndClipOwner, WM_TIMER, +- (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc); +- } + if (lpFormat->hData16) + GlobalFree16(lpFormat->hData16); + } +@@ -431,7 +449,7 @@ + * FIXME: Should be a pair of driver functions that convert between OEM text and Windows. + * + */ +-static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat ) ++static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat, BOOL b16Bit ) + { + LPWINE_CLIPFORMAT lpSource = ClipFormats; + LPWINE_CLIPFORMAT lpTarget; +@@ -486,10 +504,18 @@ + if( !lpstrS ) return NULL; + TRACE("\tconverting from '%s' to '%s', %i chars\n", + lpSource->Name, lpTarget->Name, size); +- +- lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT, size); +- lpstrT = (LPSTR)GlobalLock(lpTarget->hData32); +- ++ ++ if (b16Bit) ++ { ++ lpTarget->hData16 = GlobalAlloc16(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size); ++ lpstrT = (LPSTR)GlobalLock16(lpTarget->hData16); ++ } ++ else ++ { ++ lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size); ++ lpstrT = (LPSTR)GlobalLock(lpTarget->hData32); ++ } ++ + if( lpstrT ) + { + if( lpSource->wFormatID == CF_TEXT ) +@@ -497,10 +523,15 @@ + else + OemToCharBuffA(lpstrS, lpstrT, size); + TRACE("\tgot %s\n", lpstrT); +- GlobalUnlock(lpTarget->hData32); ++ ++ /* Unlock target */ ++ if (b16Bit) ++ GlobalUnlock16(lpTarget->hData16); ++ else ++ GlobalUnlock(lpTarget->hData32); + } + else +- lpTarget->hData32 = 0; ++ lpTarget->hData16 = lpTarget->hData32 = 0; + + /* Unlock source */ + if (lpSource->hData32) +@@ -780,7 +811,7 @@ + + if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT ) + { +- lpRender = CLIPBOARD_RenderText(wFormat); ++ lpRender = CLIPBOARD_RenderText(wFormat, TRUE); + if ( !lpRender ) return 0; + } + else +@@ -790,7 +821,8 @@ + } + + /* Convert between 32 -> 16 bit data, if necessary */ +- if( lpRender->hData32 && !lpRender->hData16 ) ++ if( lpRender->hData32 && !lpRender->hData16 ++ && CLIPBOARD_IsMemoryObject(wFormat) ) + { + int size; + if( lpRender->wFormatID == CF_METAFILEPICT ) +@@ -846,7 +878,7 @@ + + if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT ) + { +- lpRender = CLIPBOARD_RenderText(wFormat); ++ lpRender = CLIPBOARD_RenderText(wFormat, FALSE); + if ( !lpRender ) return 0; + } + else +@@ -856,7 +888,8 @@ + } + + /* Convert between 16 -> 32 bit data, if necessary */ +- if( lpRender->hData16 && !lpRender->hData32 ) ++ if( lpRender->hData16 && !lpRender->hData32 ++ && CLIPBOARD_IsMemoryObject(wFormat) ) + { + int size; + if( lpRender->wFormatID == CF_METAFILEPICT ) --- /dev/null Sat Sep 25 20:06:59 1999 +++ patches/patch-cl Sat Sep 25 19:34:53 1999 @@ -0,0 +1,25 @@ +Index: windows/winproc.c +=================================================================== +RCS file: /home/wine/wine/windows/winproc.c,v +retrieving revision 1.27 +diff -u -u -r1.27 winproc.c +--- windows/winproc.c 1999/08/15 12:45:02 1.27 ++++ windows/winproc.c 1999/09/24 23:39:33 +@@ -2329,8 +2329,16 @@ + { + WINDOWPROC *proc = WINPROC_GetPtr( func ); + +- if (!proc) ++ if (!proc) { ++ extern VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime ); ++ if (msg == WM_TIMER && func == (WNDPROC16)CLIPBOARD_GlobalFreeProc) ++ /* ++ * this is a 32bit timer proc that is not a WINDOWPROC *, ++ * don't call it as 16bit (see windows/clipboard.c) ++ */ ++ return WINPROC_CallWndProc((WNDPROC) func, hwnd, msg, wParam, lParam ); + return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam ); ++ } + + #if testing + func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 ); --- /dev/null Sat Sep 25 20:08:54 1999 +++ pkg/MESSAGE Thu Sep 9 23:27:58 1999 @@ -0,0 +1,4 @@ +In order to use wine you need to build and install a new kernel with +options USER_LDT, SYSVSHM, SYSVSEM, and SYSVMSG. Before you do that +you might want to apply the patches in /usr/local/share/wine to your +kernel sources, see the README.patch there. >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message