delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-developers/2000/05/22/23:55:35

Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-developers-subscribe AT sourceware DOT cygnus DOT com>
List-Archive: <http://sourceware.cygnus.com/ml/cygwin-developers/>
List-Post: <mailto:cygwin-developers AT sourceware DOT cygnus DOT com>
List-Help: <mailto:cygwin-developers-help AT sourceware DOT cygnus DOT com>, <http://sourceware.cygnus.com/ml/#faqs>
Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com
Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com
Date: Mon, 22 May 2000 23:53:56 -0400
Message-Id: <200005230353.XAA01281@envy.delorie.com>
From: DJ Delorie <dj AT delorie DOT com>
To: cygwin-developers AT sourceware DOT cygnus DOT com
Subject: setup: built-in tar

Here's a preview of something I've been toying with.  My goal is to
get rid of all the .exe's setup carries around; they take up space,
slow down the install, and are cumbersome to work with.  We'd also
need hooks into these processes if/when we add a GUI.

This first step removes tar and gzip, replacing them with zlib and a
built-in tar.  This built-in tar also allows setup to more closely
control where files are going; it can ignore conflicting mounts the
user has set up in favor of what it knows is right, for example.  It
could even do the install without changing the existing mounts at all.
It also ignores a lot of the unneeded info in the tar file, for
example being able to override read-only-ness in a file it needs to
update (well, not *yet*).

Oh - another bonus.  We don't need to distribute the sources to tar
and gzip with setup.exe any more (GPL'd, you know ;)

My next goal is to remove mount/umount/cygpath, in favor of
LoadLibrary(cygwin1.dll) (or some setup-specific name) and call the
cygwin functions directly.

There are still some debug hacks in the attached patches (I'm still
working on it) but they should be easy to spot.  New files attached at
the end.

? ctar.c
? tar.c
? tar.h
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/Makefile.in,v
retrieving revision 1.14
diff -p -2 -r1.14 Makefile.in
*** Makefile.in	2000/04/29 04:28:59	1.14
--- Makefile.in	2000/05/23 03:44:44
*************** ALL_LDFLAGS:=${filter-out -I%, \
*** 68,74 ****
  PROGS:=setup$(EXEEXT)
  
! OBJS:=error.o memory.o setup.o strarry.o cinstall.o path.o pkg.o xsystem.o
  
! BUNDLED_FILES:=cygwin1.dll.gz $(srcdir)/tar.exe.gz $(srcdir)/gzip.exe.gz \
  	       mount.exe.gz cygpath.exe.gz umount.exe.gz
  .SUFFIXES:
--- 68,74 ----
  PROGS:=setup$(EXEEXT)
  
! OBJS:=error.o memory.o setup.o strarry.o cinstall.o path.o pkg.o tar.o xsystem.o
  
! BUNDLED_FILES:=cygwin1.dll.gz \
  	       mount.exe.gz cygpath.exe.gz umount.exe.gz
  .SUFFIXES:
*************** endif
*** 89,92 ****
--- 89,95 ----
  	@chmod a-x $@
  
+ ctar.exe : ctar.o tar.o $(ALL_DEP_LDLIBS)
+ 	$(CC) -o $@ ctar.o tar.o $(ALL_LDFLAGS) $(ALL_LDLIBS)
+ 
  mingw_getopt.o: $(cygwin_source)/getopt.c
  	$(CC) -c -o $@ $(MINGW_CFLAGS) $^
*************** $(ZLIB): zlib/Makefile
*** 116,120 ****
  %.exe: $(utils_build)/%.exe
  	$(OBJCOPY) --strip-unneeded $? $@
! 	
  $(utils_build)/%.exe: $(utils_build)/Makefile
  	@$(MAKE) -C $(utils_build) $(@F)
--- 119,123 ----
  %.exe: $(utils_build)/%.exe
  	$(OBJCOPY) --strip-unneeded $? $@
! 
  $(utils_build)/%.exe: $(utils_build)/Makefile
  	@$(MAKE) -C $(utils_build) $(@F)
*************** cinstall.rc: $(BUNDLED_FILES)
*** 136,140 ****
  %.o: %.rc
  	$(WINDRES) -o $@ $?
! 	
  %.o: %.c
  ifdef VERBOSE
--- 139,143 ----
  %.o: %.rc
  	$(WINDRES) -o $@ $?
! 
  %.o: %.c
  ifdef VERBOSE
Index: path.c
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/path.c,v
retrieving revision 1.6
diff -p -2 -r1.6 path.c
*** path.c	2000/05/02 02:12:35	1.6
--- path.c	2000/05/23 03:44:44
*************** pathcat (const char *arg1, const char *a
*** 135,153 ****
    char path[_MAX_PATH];
    size_t len;
  
-   assert (!strchr (arg1, '/'));
    strcpy (path, arg1);
- 
-   /* Remove any trailing slash */
-   len = strlen (path);
-   if (path[--len] == '\\')
-     path[len] = '\0';
- 
    strcat (path, "\\");
- 
-   if (*arg2 == '\\')
-     ++arg2;
- 
    strcat (path, arg2);
  
    return xstrdup (path);
--- 135,155 ----
    char path[_MAX_PATH];
    size_t len;
+   char *s, *d;
  
    strcpy (path, arg1);
    strcat (path, "\\");
    strcat (path, arg2);
+ 
+   for (s=path; *s; s++)
+     if (*s == '/')
+       *s = '\\';
+   for (s=d=path; *s; s++)
+     {
+       *d++ = *s;
+       if (*s == '\\')
+ 	while (s[1] == '\\')
+ 	  s++;
+     }
+   *d = 0;
  
    return xstrdup (path);
Index: setup.c
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/setup.c,v
retrieving revision 1.45
diff -p -2 -r1.45 setup.c
*** setup.c	2000/05/20 03:53:33	1.45
--- setup.c	2000/05/23 03:44:48
*************** char *wd = NULL;
*** 57,60 ****
--- 57,62 ----
  static char *tarpgm;
  
+ static char *tar_map[8];
+ 
  static int downloaddir (SA *installme, const char *url);
  
*************** xumount (const char *mountexedir, const 
*** 258,261 ****
--- 260,266 ----
  }
  
+ extern FILE * _tar_vfile;
+ extern int _tar_verbose;
+ 
  static int
  tarx (const char *dir, const char *fn)
*************** tarx (const char *dir, const char *fn)
*** 283,355 ****
      }
  
-   dpath = pathcat (dir, fn);
-   path = dtoupath (dpath);
-   sprintf (buffer, "%s xvfUz \"%s\"", tarpgm, path);
-   xfree (path);
-   xfree (dpath);
- 
    printf ("Installing %s\n", fn);
- 
-   if (_pipe (hpipe, 256, O_TEXT) == -1)
-     return 0;
- 
-   hin = (HANDLE) _get_osfhandle (hpipe[1]);
-   hproc = (HANDLE) xcreate_process (0, NULL, hin, hin, buffer);
-   if (!hproc)
-     {
-       warning ("Unable to extract \"%s\": %s", fn, _strerror (""));
-       return 0;
-     }
  
!   CloseHandle (hproc);
!   _close (hpipe[1]);
!   fp = fdopen (hpipe[0], "rt");
! 
!   filehere = files.index;
!   while (fgets (buffer, sizeof (buffer0), fp))
!     {
!       char *s = strchr (buffer, '\n');
! 
!       if (s)
! 	*s = '\0';
! 
!       if (strchr (buffer, ':') != NULL)
! 	{
! 	  s = buffer;
! 	  fprintf (stderr, "%s\n", s);
! 	}
!       else
! 	{
! 	  if (++files.index >= files.count)
! 	    files.array = realloc (files.array,
! 				   NFILE_SLOP + (files.count += NFILE_LIST));
! 	  s = buffer;
! 	  if (*s != '/')
! 	    *--s = '/';
! #if 0 /* too simplistic */
! 	  e = strchr (s, '\0') - 1;
! 	  if (e > s && *e == '/')
! 	    {
! 	      *e = '\0';
! 	      xumount (wd, s);
! 	    }
! #endif
! 
! 	  s = files.array[files.index] = utodpath (s);
! 	}
! 
!       fprintf (logfp, "%s\n", s);
!     }
!   fclose (fp);
! 
!   while (++filehere <= files.index)
!     if (chmod (files.array[filehere], 0777))
!       warning ("Unable to reset protection on '%s' - %s\n",
! 	       files.array[filehere], _strerror (""));
! 
!   warning ("%s package '%s'\n", write_pkg (pkg, pkgname, pkgversion) ?
! 			      "Updated" : "Refreshed", pkgname);
! 
!   return 1;
  }
  
--- 288,297 ----
      }
  
    printf ("Installing %s\n", fn);
  
!   dpath = pathcat (dir, fn);
!   _tar_vfile = logfp;
!   _tar_verbose = 2;
!   return !tar_auto (dpath, tar_map);
  }
  
*************** get_pkg_stuff (int updating)
*** 1421,1424 ****
--- 1363,1380 ----
  }
  
+ static void
+ do_tar_map (int i, char *from, char *root, char *to)
+ {
+   char *t;
+   tar_map[i] = from;
+   i++;
+   tar_map[i] = (char *) xmalloc (strlen(root) + strlen(to) + 3);
+   t = tar_map[i];
+   strcpy (t, root);
+   if (t[strlen(t)-1] == '/' && to[0] == '/')
+     to ++;
+   strcat (t, to);
+ }
+ 
  static char rev[] = "$Revision: 1.44 $ ";
  
*************** those as the basis for your installation
*** 1556,1559 ****
--- 1512,1519 ----
  	}
        xfree (defroot);
+       /* convert to windows format */
+       for (defroot=root; *defroot; defroot++)
+ 	if (*defroot == '/')
+ 	  *defroot == '\\';
  
        Sleep (0);
*************** those as the basis for your installation
*** 1606,1609 ****
--- 1566,1570 ----
  	  _chdrive (toupper (*root) - 'A' + 1);
  
+ #if 0
  	  xumount (wd, "/usr");
  	  xumount (wd, "/var");
*************** those as the basis for your installation
*** 1615,1618 ****
--- 1576,1586 ----
  	  mkmount (wd, "bin", "/usr/bin", 1);
  	  mkmount (wd, "lib", "/usr/lib", 1);
+ #endif
+ 
+ 	  do_tar_map (0, "usr/bin/", root, "/bin/");
+ 	  do_tar_map (2, "usr/lib/", root, "/lib/");
+ 	  do_tar_map (4, "", root, "/");
+ 	  tar_map[6] = tar_map[7] = 0;
+ 
  
  	  mkdirp ("var\\run");

begin 744 new.tar.gz
M'XL(",S^*3D"`VYE=RYT87(`[1MK4]M(,E]-%?]APA:)C0U8YI%=#-QQX"3<
M.I`"<GM;0'EE2;8%MN229!SR^._7W3.CF9%DPV[=[57=6;6UL69Z9KI[^JW&
M2>QHPWGQ'WVL>GUW>YN]8(R]V:5_8<2B=WRL[?HNS%A68VMKV]IY@]-;V_47
MK/[B3W AT F,7"`L1?NW7PXY[$?3.(7_VO/#W[@#">NQ_;CQ/7#C<'A\E(ZMH+"
M,5A97EI>\CXG7A0P/TA8!T8[#U[4#6.OB7,PN+PTLOV`E7'>COI.C3D#8.O:
M&KP\5):7OBXO,3DTLL?L@)7%6X6-[.$P=%BYC`NKC0I;8['_Q0M[$J92:>)R
MW-NOL3LZD['IP!]ZC!:Q0V:Q5Z]8G$3.:$QC#]?6;8VMK#^L5-C!`:M7<`EC
M7_D_S"""5:M-.8[;K:_KKP_I['=^L-\3I^ZS1G;;WC@"-`$`N.E%$6#P*;;[
MWAYS4,KV>X#R!C*U_^607?>B<,224/W8V-BXO;T)5BKI^=YG/V%EJV)B<`?\
MJ]-0+XR`Z?#::#(?$$*\\%>U*C`#9E_?5:NW`$)<\6]IG39<+QH AT  DOT N$W<LF>
M`&J*IP!9:2I.^,A>2YR6)Q_IWF/)P(L\-K5C9@<,)@!K$*C(=A(_Z+/5&&BN
M,7$"I]4;PKWP_0^?NSW^CS:/Y^^.FT5>,D%YAE=@ZHO_V^=/,/]/V/_&;F/7
M$O;_S>ZN9>%TH[&]L/__=?N/8T._FQF<^H$;3N.,J_@"@)M?"'JEV(7\X'H]
M/_#8VZ/CJ_,+5JY_MGYRNY;KN3M;GOW&JK?;%05U=OFQ=7'9.D99H:?=5I.7
MOWYHGY[]W#D^/__YM,567N['CZ.A']P?TDG)X]@#2/0'$R=AROD$]LB[A AT UO
MF\Q\-M?@?W6VMIF"CD+7N_XQ!TB AT L(,..O'=0D@.^J,.VI\':NWJH.@#KZU&
M'AA!&]L&KHD_*H1%T"UC5V=P'T]&!3@@Z+:!*W*Q-[3[A0CL&+LBZPMY2Z!O
M#%SMON]<[Q:2U3!!P3W'?AA<Y^A"T-TMXPKH]*U"#C1V=XPKF`?ZDX&`ZSV,
M[+LPRK$+0+<:/V5!_6`&Z):QZS@"(?Y\;>WL%(!N&[C>38)[NM=2"29WA-A]
M)[<\\&QP AT AV\I6:!T",(N.I.Y,6384)@G9BKPER(M0!\9U.%:W$21I[;0:9I
MH[!NK$:_%^U%2(%Q37RG:)JMF8-IX"&68+0'SEP?HJ,QA*)SKSL?CO[9^7AT
M];ZZ AT RPRP0;V@]<9A@'=MMA;VYEO,_2"?C+((JHQ5GO/[-^=]*[%L10`FP$E
M/^_M:;L%P2R?P0/%N+1B#V.(<,KZPHH,<72 AT 1A;JT-+@4K3Z7][B$6O]+"?Y
MC2TO?89[=R=C&54[9E@>J9A<A>2P`G@$XQ5692(*Q:#L920B,B,^Q?![_,C*
M$)@Y?$1$61&/LD2F@)2$8]J6CAO;R0!O2>*#!^@\4]&[P4D>`XIP#KFD+:J1
MW]EC=,QOJ_%K"@'3 AT P@WY%/_"T=$SL"ZJ+NBZ)1YB!*#"GMYP.#BLX$_J*<;
MV3'PNP:R`8G*:!Q&B0V"P=5Y1O@:CL;^$&XI%&'Q'DH<XT=)/0W"!$\$SU82
MAF*%=1\3+X;@.'D=LU6W0N05(#LOD6!X8AK_BYOJL[^`&]QCEKPQ(4,/H>_"
MR[T_[A#[R_*R1!:FJ1/$Z[ELJ_\E`H18N8_,Z=6(@2EJ^MIU8JY"DG"0`HR$
MH77*H(#:!\P,-//D<)KHAO%D//B5XDN*`$+!S5UZE&M,O=>00=A@=P*7`2?I
M&'Y]*`R1>?6"8_7<-I"-R!OT(>$9#MD7+PKQMC:\#38$(6%=T*[[BM@[,+,Y
MQ!I.V>37B1EUI0D:Q*+U=7%RP+Z!KE*NO5;1R*I<1^O6;2J\@:XZ&6Q)B4T;
M"?FSVFI#.G^D^77[=?9"1]X(5+V<&N.:OI8/0"B0N>,T0D@)3C/:.';LH*>)
M[@:2#QJR&H)DO])$I#)3XU<=MOJ3*_.]`EIJNJC5%$YRRWCJ)\Y`5Z!TJ4F_
M8X.-!Z[LX:V_._M$2HN,I``3DT\OP,A%TWUDN*DDJ?N"O4M?2;EU_6K2B#`9
MRF((*T&'$:0XT?$\%TT!*0!DOA`Z(1M@$]A%'<5W1<6GJD;)4,TB#2G]WKLI
M)$-(7U:!<?*[Y)`#4I%>22HX,^V+8!DJ00"TR\4I#.`/M AT S_OY=Q]B5^&T4V
MB>T+!2]E=*8D11Z<EH#'4P5Y#JL>T+NX-- DOT  AT R8F4TC5'4P"6"U6L=&8VVW0Y
MW.)RR"W?ICZSS6?(VF2F=OE4S^^%>0^EQ&UJ1X$?]/?("6E%E7CL.;X]Y"*X
M*D4MH^N:]Y$"]WOHJG,4(Z\_&8K`SR2BGI^WAW&8H;3!MX$$L1L.P95AKI(!
MV>$@KA]Y#H2[CYGI-X+!89#X_4DXB4U<4GITZ=776WP]W(]+I]?`TT!H#W[`
M"<>/S]D'8D$;8N2]V9&$L`N0+P3A%"*:$'.B>#+&*`3DE&-,(>UOJ\YKX[Z*
M3.7,J\OH]E/WJ;MQ%7XO+XWN@=F=,2\8^[$-;[)DC+&8$9K&H!]N!W_6(!T!
M_SE(U4?W]B>_G%^<,+?&^K$WTT?(<YV!Y]Q3=3!U&!(+.I]V1*/RSDLPK#Y*
MDLB'N`Z#+@6`9L1%#UG_W!,/NE&7O6(8^W>.KJXN3O_VZ:K5.3F]:&'5X]>L
M(YV-(L5VMA)*HRZLF:9,99J3\?QCZ%_)`T6:]%G'8"03[R35#**^!A88C60&
M"X:LYSQK0Y33HCIOV=P/(8!AK8N+\PMR29VS\ZO.V_-/9R?*J,_&EI\(YG[5
M)81ANXIFTF-*%_CF1^V+UM')KYW6/T\OKRZE39_E4,'%O09])&HU0W"S`IQ9
M878,UP'&!3W&(\;2<1+CH$UZ9;!.>3M+,_KB AT BC`<PX0MHERRYRT4/]5YQ)Z
M"(B[]C#N*IDBGP'9?,V^?6/BY>;&6.#DI>,ES17'A$K/8"U7--H AT HW DOT X3:J^
MEB`\2T2Z1FV:E5U+3T6*X5.L#:'.H"U>E47)Z'$^C>GYGSM8,>O`Z&BLIZ%Z
M2D%%-<*1 AT BT><>'8`PVB AT E^=?FCQ,1IZ?W1V`AG_H*G'M$8X27NFD1.]<?7@
M&P/]-,;65/FS*NJE"FS#G;[W^X,3D-0KGR(&L?KPD&TU#+AV.,V!$0"RFJLV
M63>IUN]:9ZV+T^/.+Q>G5ZT:-V*7[X\N6AW4)?9-'^$P/,!D]1H[_]@ZX\IV
M>O9.CF?,X-GYQ8>CMMSG;?OH7>=O1\<_?_K8N6Q].#J[.CV^1-N2RMD@*U>7
MW!P3066T0_3?JY[B)#['PS#VWMN!BVYH,,,/\>H,9)?A:!0&G5ZV)"%E@<.%
M$UX4 AT W^1DZIL@$&27C)X"1`%Q8&1_=C%3U0\6$U":6KL AT J@CHV-UI6,S\P0]
M5$WCS+FX"L6;A7+.3DX"NXLA1,BFD9_0#RWXRWB.,5G5\LK50'R1PV]_FON:
M%T74=?3$&.>^64)"6RSVF'-I$#)@D)753QDN3&L,O_\D(!#W<?J5N1_RRRXN
M6XZB/Y8O0CQ;RL2K<3:@S82=RGUG_.';8K[S&S<E.N_3Q7V7-$/\>]*M,5V&
M>)EBB>MWY5[`W+0NDZL(24<.,$8J]E5E%[G0ERI]$P@\(2>!6->HWN`AVD=@
MS4G37 AT X:"@B6 AT 1]J-/)&X8.G&%?*N:V2D$_X=\QUC.M$F4@!GXA<J3&U+=*$
MD/LT\VRB\#J!$M>/[R'CLAV/=._?1$_>B,RF,I/1(A&&I<D<K*H^IJ.5&&AV
M,;6(`S]&F^*&*D^*6=<;AE/-+H+N89FZ4"^UJK56",V`:151V&O]$-,5T>:@
M($T0[0,(0*9%]((LE\"U+R,ZN*F%N4\?RJ AT 41#A:'EG2\\BX.2N1I#B3,RM#
M&IV$_SM(Z4=QI&(W=<^4LT0;I33YH2]MJ@'AZ(*2W9L&!O90-F.&</.(N^<'
MF('AU5-B3C]5Y:KH[*=B[0)S^1[WW5_7U::6NRYU/<3-U'-FX?2/!"G%N.1)
MDI4/)>,G*Y4%>,RB[-]EX,O<"O>X$99F"PQNC8BO5`K-?H&E AT WV*#1U,_,EV
M3HX2`7_(G,^R9\7[/V7EYNKR#M=E&?SY6BA0(+\GQ>Y>7"8.7M=OL?1`/_E7
M.X['NG4K\D2\C>)I+;/,)E.6.M+$O\'Q-ZIJ<TEHHPJN'V94L,"RI+B<>$//
MR$_4U//2%YX<'$/J AT JE'ZQ=I4V;E)6GJ(?5H@*P[/?O'4?OTI,.CQPZ\?&KE
M-+V@$"=5703ZHD%%5!2>43)0WU-)U\R6%RV4!B`[$4!S^8D4_8+:2]^),7NB
M-4(<X'>E"M?]"D+BLT_MMI9NY-.I4IJ)J<)8>@L9WE[^>GG5^C`O3RE.UY[#
M6VZ,YK#V24G*%R/,+$/H/,\K?@`6UK6OGJ9OS:90Q=E#SB5S)ZR(CKS<SH8_
MKCP!6NC1BD#GA2.*'3]`..WW\MF0WBA*7U,$I_JR%J05C AT 63\7,]QGRB-RR6
MS9H8K6`T"FCSK*C&O,3AK2YSV[G6L'$VS=KP!8-4K3*<A.EL$HJY[]C!FNM0
MD6/4VF+VB AT 0P$C<-J>`ML6;[0DWK;Q[Z<6*V5S AT I(OI7=ZVEF2D41HDW&BLJ
M`F]:W.^"RJ\Z/)*I[X(&Q==HT5>^W70W;[KK-]V;FYONBN*"=FT4)!)Q!_4F
M$UA?T\`:=D?1KVJUPB1V&'HK/FF-VQS2TCNW)9P(N)][5O8SLSWF0+<;U"-]
MD%\Z`Q0OFYI$>`-+=EFE:!W<:>Z`JG5;##K_@*IU:Y19\"O<I(M6*PZCA*TS
MGJU2KP"N0&/6A<D!SG(OREN[D5W^/NVZ;L'/E$<T?7?@5V'TC@/`CW1:U)``
M8U]CR#[O\U8CRLB3T''Z>9-XB8G?8O!.&[RC02&F):V^K'I[TF8;LVK+#:VP
MGXXPAOI'HUPY'*1VJ#':T8Q:ED.2/Y3.#-FAI"8E5\1Z_$\%`LQVG)H.4\LN
MT/,<&<9*MRST,EV3A&EXF0&IIA"X9PV_%^<.DDN1)V*9')()5BDMY9/1IDP8
M_UYBE?VH>"+B<VD-J AT F%Z8V:Z)?2`U=Y87HEC=R^\<WONWZWTAUF;3P)K#AZ
MA8'%*3ZUL$V+6U,N'['\L",6&;[C_[Q5_S_6_S_XK_;_LT9C]XWH_]_=VMG>
MHOY_RUKT__\9S^8:*-D:.X:<-O+[@X1Z/1OU.B1.%Q".O;?!?IP&S AT 9"$20^
M5UBL&T=A/[)'V.-&T64<]I*I'7E-]AA.L+H#J AT L9O4@/Z/MIX&Z&U%GO]Q[3
MS6!B$F"S'/K"Q(M&,=8"\`4[J]YY AT 1?90_9QTL4TL^T[7@`6R(;S<20>`))=
MM1DN>XO87`ILV-L0=J<.RR;S?/Q+(=E7SAKR(+%KC851NE,9DBH@)&+A&!=7
M`/M'-H1,+EUO\N2(5XV>1ATY`ZZ^AW AT Q DOT TDW&"3)>&]S<SJ=;H"D;811?S,]
M`-.V!+Q?]Y&=_!W3&:P8L'WW[J]<+#><<'0HH3?ICRW\7H`Q<Z=S=731>=]1
M#<5J9'D)PI+S8`A8!]3J3#Y AT 9#\B?N3%@0<VHV^)V"BF1>AL0.F:2VX`[?<(
M`U&(!Q_%^?2A AT UMT['Z$$U@\<1POAN`^"`,YUK/]X23BO33 AT Z4LS>X.;F4W'
M(8"CT(0R"(8$EEIT;!\[EGA?'-P&57C3?AV^:ZFP\PAV']MQS&P72ZI`*4]G
M_R AT 9Q=^GY$GD2&.2E10YN5(Z60,K7(W4)FFK$X@/1@^;,#BV?9%'$1C_"P-6
MQCP^YC+&Z+-(AAH?.38:8W(,%R<(ZTV&BK:R`V*:Q'P#RM8JL^A]*B>2Y,S[
M6U(QDVN<ARDAUB(;73CNQ;-X%L_B63R+9_$LGL6S>!;/XED\BV?Q+)[%LWB>
+\?P+@=MKU0!0````
`
end

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019