1 /*
2  * Portable package gateway for the ESP Package Manager (EPM).
3  *
4  * Copyright 1999-2017 by Michael R Sweet
5  * Copyright 1999-2010 by Easy Software Products.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17 
18 /*
19  * Include necessary headers...
20  */
21 
22 #include "epm.h"
23 
24 
25 /*
26  * Local functions...
27  */
28 
29 static void	clean_distfiles(const char *directory, const char *prodname,
30 		                const char *platname, dist_t *dist,
31 				const char *subpackage);
32 static int	write_combined(const char *title, const char *directory,
33 		               const char *prodname, const char *platname,
34 			       dist_t *dist, const char **files,
35 			       time_t deftime, const char *setup,
36 			       const char *types);
37 static int	write_commands(dist_t *dist, FILE *fp, int type,
38 		               const char *subpackage);
39 static FILE	*write_common(dist_t *dist, const char *title,
40 			      int rootsize, int usrsize,
41 		              const char *filename, const char *subpackage);
42 static int	write_confcheck(FILE *fp);
43 static int	write_depends(const char *prodname, dist_t *dist, FILE *fp,
44 		              const char *subpackage);
45 static int	write_distfiles(const char *directory, const char *prodname,
46 		                const char *platname, dist_t *dist,
47 				time_t deftime, const char *subpackage);
48 static int	write_install(dist_t *dist, const char *prodname,
49 			      int rootsize, int usrsize,
50 		              const char *directory,
51 		              const char *subpackage);
52 static int	write_instfiles(tarf_t *tarfile, const char *directory,
53 		                const char *prodname, const char *platname,
54 			        const char **files, const char *destdir,
55 				const char *subpackage);
56 static int	write_patch(dist_t *dist, const char *prodname,
57 			    int rootsize, int usrsize,
58 		            const char *directory,
59 		            const char *subpackage);
60 static int	write_remove(dist_t *dist, const char *prodname,
61 			     int rootsize, int usrsize,
62 		             const char *directory,
63 		             const char *subpackage);
64 static int	write_space_checks(const char *prodname, FILE *fp,
65 		                   const char *sw, const char *ss,
66 				   int rootsize, int usrsize);
67 
68 
69 /*
70  * 'make_portable()' - Make a portable software distribution package.
71  */
72 
73 int					/* O - 1 = success, 0 = fail */
make_portable(const char * prodname,const char * directory,const char * platname,dist_t * dist,struct utsname * platform,const char * setup,const char * types)74 make_portable(const char     *prodname,	/* I - Product short name */
75               const char     *directory,/* I - Directory for distribution files */
76               const char     *platname,	/* I - Platform name */
77               dist_t         *dist,	/* I - Distribution information */
78 	      struct utsname *platform,	/* I - Platform information */
79               const char     *setup,	/* I - Setup GUI image */
80               const char     *types)	/* I - Setup GUI install types */
81 {
82   int		i;			/* Looping var */
83   int		havepatchfiles;		/* 1 if we have patch files, 0 otherwise */
84   time_t	deftime;		/* File creation time */
85   file_t	*file;			/* Software file */
86   static const char	*distfiles[] =	/* Distribution files */
87 		{
88 		  "install",
89 		  "license",
90 		  "readme",
91 		  "remove",
92 		  "ss",
93 		  "sw",
94 		  NULL
95 		};
96   static const char	*patchfiles[] =	/* Patch files */
97 		{
98 		  "patch",
99 		  "license",
100 		  "pss",
101 		  "psw",
102 		  "readme",
103 		  "remove",
104 		  NULL
105 		};
106 
107 
108   REF(platform);
109 
110   if (Verbosity)
111     puts("Creating PORTABLE distribution...");
112 
113  /*
114   * See if we need to make a patch distribution...
115   */
116 
117   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
118     if (isupper((int)file->type))
119       break;
120 
121   havepatchfiles = i > 0;
122 
123   deftime = time(NULL);
124 
125  /*
126   * Build the main package and all of the subpackages...
127   */
128 
129   if (write_distfiles(directory, prodname, platname, dist, deftime, NULL))
130     return (1);
131 
132   for (i = 0; i < dist->num_subpackages; i ++)
133     if (write_distfiles(directory, prodname, platname, dist, deftime,
134                         dist->subpackages[i]))
135       return (1);
136 
137  /*
138   * Create the distribution archives...
139   */
140 
141   if (write_combined("distribution", directory, prodname, platname, dist,
142                      distfiles, deftime, setup, types))
143     return (1);
144 
145   if (havepatchfiles)
146     if (write_combined("patch", directory, prodname, platname, dist,
147                        patchfiles, deftime, setup, types))
148       return (1);
149 
150  /*
151   * Cleanup...
152   */
153 
154   if (!KeepFiles)
155   {
156     clean_distfiles(directory, prodname, platname, dist, NULL);
157 
158     for (i = 0; i < dist->num_subpackages; i ++)
159       clean_distfiles(directory, prodname, platname, dist,
160                       dist->subpackages[i]);
161   }
162 
163  /*
164   * Return!
165   */
166 
167   return (0);
168 }
169 
170 
171 /*
172  * 'clean_distfiles()' - Remove temporary software distribution files...
173  */
174 
175 static void
clean_distfiles(const char * directory,const char * prodname,const char * platname,dist_t * dist,const char * subpackage)176 clean_distfiles(const char *directory,	/* I - Directory */
177 	        const char *prodname,	/* I - Product name */
178                 const char *platname,	/* I - Platform name */
179 	        dist_t     *dist,	/* I - Distribution */
180 	        const char *subpackage)	/* I - Subpackage */
181 {
182   char		prodfull[255],		/* Full name of product */
183 		filename[1024];		/* Name of temporary file */
184 
185 
186  /*
187   * Figure out the full name of the distribution...
188   */
189 
190   if (subpackage)
191     snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
192   else
193     strlcpy(prodfull, prodname, sizeof(prodfull));
194 
195  /*
196   * Remove the distribution files...
197   */
198 
199   if (Verbosity)
200     printf("Removing %s temporary files...\n", prodfull);
201 
202   snprintf(filename, sizeof(filename), "%s/%s.install", directory, prodfull);
203   unlink(filename);
204 
205   snprintf(filename, sizeof(filename), "%s/%s.license", directory, prodfull);
206   unlink(filename);
207 
208   snprintf(filename, sizeof(filename), "%s/%s.patch", directory, prodfull);
209   unlink(filename);
210 
211   snprintf(filename, sizeof(filename), "%s/%s.psw", directory, prodfull);
212   unlink(filename);
213 
214   snprintf(filename, sizeof(filename), "%s/%s.psw", directory, prodfull);
215   unlink(filename);
216 
217   snprintf(filename, sizeof(filename), "%s/%s.readme", directory, prodfull);
218   unlink(filename);
219 
220   snprintf(filename, sizeof(filename), "%s/%s.remove", directory, prodfull);
221   unlink(filename);
222 
223   snprintf(filename, sizeof(filename), "%s/%s.ss", directory, prodfull);
224   unlink(filename);
225 
226   snprintf(filename, sizeof(filename), "%s/%s.sw", directory, prodfull);
227   unlink(filename);
228 }
229 
230 
231 /*
232  * 'write_combined()' - Write all of the distribution files in tar files.
233  */
234 
235 static int				/* O - 0 on success, -1 on failure */
write_combined(const char * title,const char * directory,const char * prodname,const char * platname,dist_t * dist,const char ** files,time_t deftime,const char * setup,const char * types)236 write_combined(const char *title,	/* I - Title */
237                const char *directory,	/* I - Output directory */
238 	       const char *prodname,	/* I - Base product name */
239 	       const char *platname,	/* I - Platform name */
240 	       dist_t     *dist,	/* I - Distribution */
241 	       const char **files,	/* I - Files */
242 	       time_t     deftime,	/* I - Default timestamp */
243 	       const char *setup,	/* I - Setup program */
244 	       const char *types)	/* I - Setup types file */
245 {
246   int		i;			/* Looping var */
247   tarf_t	*tarfile;		/* Distribution tar file */
248   char		tarfilename[1024],	/* Name of tar file */
249 		filename[1024];		/* Name of temporary file */
250 #ifdef __APPLE__
251   FILE		*fp;			/* Plist file... */
252 #endif /* __APPLE__ */
253   struct stat	srcstat;		/* Source file information */
254   const char	*destdir;		/* Destination directory */
255   const char	*setup_img;		/* Setup image name */
256 
257 
258  /*
259   * Figure out the filename...
260   */
261 
262   if (dist->release[0])
263     snprintf(tarfilename, sizeof(tarfilename), "%s/%s-%s-%s", directory,
264              prodname, dist->version, dist->release);
265   else
266     snprintf(tarfilename, sizeof(tarfilename), "%s/%s-%s", directory, prodname,
267              dist->version);
268 
269   if (!strcmp(title, "patch"))
270     strlcat(tarfilename, "-patch", sizeof(tarfilename));
271 
272   if (platname[0])
273   {
274     strlcat(tarfilename, "-", sizeof(tarfilename));
275     strlcat(tarfilename, platname, sizeof(tarfilename));
276   }
277 
278   strlcat(tarfilename, ".tar.gz", sizeof(tarfilename));
279 
280  /*
281   * Open output file...
282   */
283 
284   if ((tarfile = tar_open(tarfilename, 1)) == NULL)
285   {
286     fprintf(stderr, "epm: Unable to create output pipe to gzip -\n     %s\n",
287             strerror(errno));
288     return (-1);
289   }
290 
291   if (Verbosity)
292     printf("Writing %s archive:\n", title);
293 
294 #ifdef __APPLE__
295   if (setup)
296   {
297    /*
298     * Create directories for the setup application...
299     */
300 
301     if (tar_header(tarfile, TAR_DIR, (mode_t)0755, (size_t)0, deftime, "root", "root",
302                    "Install.app", NULL) < 0)
303     {
304       tar_close(tarfile);
305       return (-1);
306     }
307 
308     if (tar_header(tarfile, TAR_DIR, (mode_t)0755, (size_t)0, deftime, "root", "root",
309                    "Install.app/Contents", NULL) < 0)
310     {
311       tar_close(tarfile);
312       return (-1);
313     }
314 
315     if (tar_header(tarfile, TAR_DIR, (mode_t)0755, (size_t)0, deftime, "root", "root",
316                    "Install.app/Contents/MacOS", NULL) < 0)
317     {
318       tar_close(tarfile);
319       return (-1);
320     }
321 
322     if (tar_header(tarfile, TAR_DIR, (mode_t)0755, (size_t)0, deftime, "root", "root",
323                    "Install.app/Contents/Resources", NULL) < 0)
324     {
325       tar_close(tarfile);
326       return (-1);
327     }
328 
329    /*
330     * Then copy the data files...
331     */
332 
333     snprintf(filename, sizeof(filename), "%s/default.icns", DataDir);
334     stat(filename, &srcstat);
335 
336     if (tar_header(tarfile, TAR_NORMAL, srcstat.st_mode & (~0222),
337                    srcstat.st_size, srcstat.st_mtime, "root", "root",
338 		   "Install.app/Contents/Resources/setup.icns", NULL) < 0)
339     {
340       tar_close(tarfile);
341       return (-1);
342     }
343 
344     if (tar_file(tarfile, filename) < 0)
345     {
346       tar_close(tarfile);
347       return (-1);
348     }
349 
350     if (Verbosity)
351       printf("    %7.0fk setup.icns\n", (srcstat.st_size + 1023) / 1024.0);
352 
353     snprintf(filename, sizeof(filename), "%s/%s.setup.plist", directory,
354              prodname);
355     if ((fp = fopen(filename, "w")) == NULL)
356     {
357       fprintf(stderr, "epm: Error writing %s -\n    %s\n", filename,
358               strerror(errno));
359       tar_close(tarfile);
360       return (-1);
361     }
362 
363     fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
364 		"<plist version=\"0.9\">\n"
365 		"    <dict>\n"
366 		"	<key>CFBundleInfoDictionaryVersion</key>\n"
367 		"	<string>6.0</string>\n"
368 		"	<key>CFBundleExecutable</key>\n"
369 		"	<string>setup</string>\n"
370 		"	<key>CFBundleIdentifier</key>\n"
371 		"	<string>org.msweet.epmsetup</string>\n"
372 		"	<key>CFBundleVersion</key>\n"
373 		"	<string>%s</string>\n"
374 		"	<key>CFBundleDevelopmentRegion</key>\n"
375 		"	<string>English</string>\n"
376 		"	<key>NSHumanReadableCopyright</key>\n"
377 		"	<string>Copyright %s</string>\n"
378 		"	<key>CFAppleHelpAnchor</key>\n"
379 		"	<string>help</string>\n"
380 		"	<key>CFBundleName</key>\n"
381 		"	<string>Installer for %s</string>\n"
382 		"	<key>CFBundlePackageType</key>\n"
383 		"	<string>APPL</string>\n"
384 		"	<key>CFBundleSignature</key>\n"
385 		"	<string>FLTK</string>\n"
386 		"	<key>CFBundleIconFile</key>\n"
387 		"	<string>setup.icns</string>\n"
388 		"	<key>CFBundleShortVersionString</key>\n"
389 		"	<string>%s</string>\n"
390 		"	<key>CFBundleGetInfoString</key>\n"
391 		"	<string>%s, Copyright %s</string>\n"
392 		"    </dict>\n"
393 		"</plist>\n",
394             dist->version,
395 	    dist->copyright,
396 	    dist->product,
397 	    dist->version,
398 	    dist->version, dist->copyright);
399     fclose(fp);
400 
401     stat(filename, &srcstat);
402 
403     if (tar_header(tarfile, TAR_NORMAL, srcstat.st_mode & (~0222),
404                    srcstat.st_size, srcstat.st_mtime, "root", "root",
405 		   "Install.app/Contents/Info.plist", NULL) < 0)
406     {
407       tar_close(tarfile);
408       return (-1);
409     }
410 
411     if (tar_file(tarfile, filename) < 0)
412     {
413       tar_close(tarfile);
414       return (-1);
415     }
416 
417     if (!KeepFiles)
418       unlink(filename);
419 
420     if (Verbosity)
421       printf("    %7.0fk Info.plist\n", (srcstat.st_size + 1023) / 1024.0);
422   }
423 
424   destdir = "Install.app/Contents/Resources/";
425 
426 #else /* !__APPLE__ */
427   destdir = "";
428 #endif /* __APPLE__ */
429 
430  /*
431   * Write installer files...
432   */
433 
434   if (write_instfiles(tarfile, directory, prodname, platname, files, destdir,
435                       NULL))
436   {
437     tar_close(tarfile);
438     return (-1);
439   }
440 
441   for (i = 0; i < dist->num_subpackages; i ++)
442     if (write_instfiles(tarfile, directory, prodname, platname, files, destdir,
443                 	dist->subpackages[i]))
444     {
445       tar_close(tarfile);
446       return (-1);
447     }
448 
449  /*
450   * Now the setup files...
451   */
452 
453   if (setup)
454   {
455    /*
456     * Include the ESP Software Installation Wizard (setup)...
457     */
458 
459     if (stat(SetupProgram, &srcstat))
460     {
461       fprintf(stderr, "epm: Unable to stat GUI setup program %s: %s\n", SetupProgram, strerror(errno));
462       tar_close(tarfile);
463       return (-1);
464     }
465 
466 #ifdef __APPLE__
467     if (tar_header(tarfile, TAR_NORMAL, 0555, srcstat.st_size,
468 	           srcstat.st_mtime, "root", "root",
469 		   "Install.app/Contents/MacOS/setup", NULL) < 0)
470 #else
471     if (tar_header(tarfile, TAR_NORMAL, 0555, srcstat.st_size,
472 	           srcstat.st_mtime, "root", "root", "setup", NULL) < 0)
473 #endif /* __APPLE__ */
474     {
475       tar_close(tarfile);
476       return (-1);
477     }
478 
479     if (tar_file(tarfile, SetupProgram) < 0)
480     {
481       tar_close(tarfile);
482       return (-1);
483     }
484 
485     if (Verbosity)
486       printf("    %7.0fk setup\n", (srcstat.st_size + 1023) / 1024.0);
487 
488    /*
489     * And the image file...
490     */
491 
492     stat(setup, &srcstat);
493 
494     if (strlen(setup) > 4 && !strcmp(setup + strlen(setup) - 4, ".gif"))
495       setup_img = "setup.gif";
496     else if (strlen(setup) > 4 && !strcmp(setup + strlen(setup) - 4, ".jpg"))
497       setup_img = "setup.jpg";
498     else if (strlen(setup) > 4 && !strcmp(setup + strlen(setup) - 4, ".png"))
499       setup_img = "setup.png";
500     else
501       setup_img = "setup.xpm";
502 
503     snprintf(filename, sizeof(filename), "%s%s", destdir, setup_img);
504 
505     if (tar_header(tarfile, TAR_NORMAL, 0444, srcstat.st_size,
506 	           srcstat.st_mtime, "root", "root", filename, NULL) < 0)
507     {
508       tar_close(tarfile);
509       return (-1);
510     }
511 
512     if (tar_file(tarfile, setup) < 0)
513     {
514       tar_close(tarfile);
515       return (-1);
516     }
517 
518     if (Verbosity)
519       printf("    %7.0fk %s\n", (srcstat.st_size + 1023) / 1024.0, setup_img);
520 
521    /*
522     * And the types file...
523     */
524 
525     if (types)
526     {
527       stat(types, &srcstat);
528       snprintf(filename, sizeof(filename), "%ssetup.types", destdir);
529 
530       if (tar_header(tarfile, TAR_NORMAL, 0444, srcstat.st_size,
531 		     srcstat.st_mtime, "root", "root", filename, NULL) < 0)
532       {
533         tar_close(tarfile);
534 	return (-1);
535       }
536 
537       if (tar_file(tarfile, types) < 0)
538       {
539         tar_close(tarfile);
540 	return (-1);
541       }
542 
543       if (Verbosity)
544         printf("    %7.0fk setup.types\n", (srcstat.st_size + 1023) / 1024.0);
545     }
546 
547    /*
548     * And finally the uninstall stuff...
549     */
550 
551 #ifdef __APPLE__
552     if (tar_header(tarfile, TAR_DIR, 0755, 0, deftime, "root", "root",
553                    "Uninstall.app", NULL) < 0)
554     {
555       tar_close(tarfile);
556       return (-1);
557     }
558 
559     if (tar_header(tarfile, TAR_DIR, 0755, 0, deftime, "root", "root",
560                    "Uninstall.app/Contents", NULL) < 0)
561     {
562       tar_close(tarfile);
563       return (-1);
564     }
565 
566     if (tar_header(tarfile, TAR_DIR, 0755, 0, deftime, "root", "root",
567                    "Uninstall.app/Contents/MacOS", NULL) < 0)
568     {
569       tar_close(tarfile);
570       return (-1);
571     }
572 
573     if (tar_header(tarfile, TAR_DIR, 0755, 0, deftime, "root", "root",
574                    "Uninstall.app/Contents/Resources", NULL) < 0)
575     {
576       tar_close(tarfile);
577       return (-1);
578     }
579 
580    /*
581     * Then copy the data files...
582     */
583 
584     snprintf(filename, sizeof(filename), "%s/default.icns", DataDir);
585     stat(filename, &srcstat);
586 
587     if (tar_header(tarfile, TAR_NORMAL, srcstat.st_mode & (~0222),
588                    srcstat.st_size, srcstat.st_mtime, "root", "root",
589 		   "Uninstall.app/Contents/Resources/uninst.icns", NULL) < 0)
590     {
591       tar_close(tarfile);
592       return (-1);
593     }
594 
595     if (tar_file(tarfile, filename) < 0)
596     {
597       tar_close(tarfile);
598       return (-1);
599     }
600 
601     if (Verbosity)
602       printf("    %7.0fk uninst.icns\n", (srcstat.st_size + 1023) / 1024.0);
603 
604     snprintf(filename, sizeof(filename), "%s/%s.uninst.plist", directory,
605              prodname);
606     if ((fp = fopen(filename, "w")) == NULL)
607     {
608       fprintf(stderr, "epm: Error writing %s -\n    %s\n", filename,
609               strerror(errno));
610       tar_close(tarfile);
611       return (-1);
612     }
613 
614     fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
615 		"<plist version=\"0.9\">\n"
616 		"    <dict>\n"
617 		"	<key>CFBundleInfoDictionaryVersion</key>\n"
618 		"	<string>6.0</string>\n"
619 		"	<key>CFBundleExecutable</key>\n"
620 		"	<string>uninst</string>\n"
621 		"	<key>CFBundleIdentifier</key>\n"
622 		"	<string>org.msweet.epmuninst</string>\n"
623 		"	<key>CFBundleVersion</key>\n"
624 		"	<string>%s</string>\n"
625 		"	<key>CFBundleDevelopmentRegion</key>\n"
626 		"	<string>English</string>\n"
627 		"	<key>NSHumanReadableCopyright</key>\n"
628 		"	<string>Copyright %s</string>\n"
629 		"	<key>CFAppleHelpAnchor</key>\n"
630 		"	<string>help</string>\n"
631 		"	<key>CFBundleName</key>\n"
632 		"	<string>Uninstaller for %s</string>\n"
633 		"	<key>CFBundlePackageType</key>\n"
634 		"	<string>APPL</string>\n"
635 		"	<key>CFBundleSignature</key>\n"
636 		"	<string>FLTK</string>\n"
637 		"	<key>CFBundleIconFile</key>\n"
638 		"	<string>uninst.icns</string>\n"
639 		"	<key>CFBundleShortVersionString</key>\n"
640 		"	<string>%s</string>\n"
641 		"	<key>CFBundleGetInfoString</key>\n"
642 		"	<string>%s, Copyright %s</string>\n"
643 		"    </dict>\n"
644 		"</plist>\n",
645             dist->version,
646 	    dist->copyright,
647 	    dist->product,
648 	    dist->version,
649 	    dist->version, dist->copyright);
650     fclose(fp);
651 
652     stat(filename, &srcstat);
653 
654     if (tar_header(tarfile, TAR_NORMAL, srcstat.st_mode & (~0222),
655                    srcstat.st_size, srcstat.st_mtime, "root", "root",
656 		   "Uninstall.app/Contents/Info.plist", NULL) < 0)
657     {
658       tar_close(tarfile);
659       return (-1);
660     }
661 
662     if (tar_file(tarfile, filename) < 0)
663     {
664       tar_close(tarfile);
665       return (-1);
666     }
667 
668     if (!KeepFiles)
669       unlink(filename);
670 
671     if (Verbosity)
672       printf("    %7.0fk Info.plist\n", (srcstat.st_size + 1023) / 1024.0);
673 #endif /* __APPLE__ */
674 
675    /*
676     * Include the ESP Software Removal Wizard (uninst)...
677     */
678 
679     if (stat(UninstProgram, &srcstat))
680     {
681       fprintf(stderr, "epm: Unable to stat GUI uninstall program %s: %s\n", UninstProgram, strerror(errno));
682       tar_close(tarfile);
683       return (-1);
684     }
685 
686 #ifdef __APPLE__
687     if (tar_header(tarfile, TAR_NORMAL, 0555, srcstat.st_size,
688 	           srcstat.st_mtime, "root", "root",
689 		   "Uninstall.app/Contents/MacOS/uninst", NULL) < 0)
690 #else
691     if (tar_header(tarfile, TAR_NORMAL, 0555, srcstat.st_size,
692 	           srcstat.st_mtime, "root", "root", "uninst", NULL) < 0)
693 #endif /* __APPLE__ */
694     {
695       tar_close(tarfile);
696       return (-1);
697     }
698 
699     if (tar_file(tarfile, UninstProgram) < 0)
700     {
701       tar_close(tarfile);
702       return (-1);
703     }
704 
705     if (Verbosity)
706       printf("    %7.0fk uninst\n", (srcstat.st_size + 1023) / 1024.0);
707 
708 #ifdef __APPLE__
709    /*
710     * And the image file...
711     */
712 
713     stat(setup, &srcstat);
714 
715     snprintf(filename, sizeof(filename), "Uninstall.app/Contents/Resources/%s",
716              setup_img);
717 
718     if (tar_header(tarfile, TAR_NORMAL, 0444, srcstat.st_size,
719 	           srcstat.st_mtime, "root", "root", filename, NULL) < 0)
720     {
721       tar_close(tarfile);
722       return (-1);
723     }
724 
725     if (tar_file(tarfile, setup) < 0)
726     {
727       tar_close(tarfile);
728       return (-1);
729     }
730 
731     if (Verbosity)
732       printf("    %7.0fk %s\n", (srcstat.st_size + 1023) / 1024.0, setup_img);
733 #endif /* __APPLE__ */
734   }
735 
736   if (Verbosity)
737   {
738     puts("     ------- ----------------------------------------");
739     printf("    %7.0fk %s-%s", tarfile->blocks * 0.5f, prodname, dist->version);
740     if (dist->release[0])
741       printf("-%s", dist->release);
742     if (!strcmp(title, "patch"))
743       fputs("-patch", stdout);
744     if (platname[0])
745       printf("-%s", platname);
746     puts(".tar");
747   }
748 
749   tar_close(tarfile);
750 
751   if (Verbosity)
752   {
753     stat(tarfilename, &srcstat);
754 
755     puts("     ------- ----------------------------------------");
756     printf("    %7.0fk %s\n", (srcstat.st_size + 1023) / 1024.0,
757            tarfilename);
758   }
759 
760 #ifdef __APPLE__
761   {
762     char	dmgfilename[1024];	/* Disk image filename */
763 
764 
765    /*
766     * Make a disk image containing the package files...
767     */
768 
769     if (dist->release[0])
770       snprintf(filename, sizeof(filename), "%s/%s-%s-%s", directory, prodname,
771 	       dist->version, dist->release);
772     else
773       snprintf(filename, sizeof(filename), "%s/%s-%s", directory, prodname,
774 	       dist->version);
775 
776     if (!strcmp(title, "patch"))
777       strlcat(filename, "-patch", sizeof(filename));
778 
779     if (platname[0])
780     {
781       strlcat(filename, "-", sizeof(filename));
782       strlcat(filename, platname, sizeof(filename));
783     }
784 
785     snprintf(dmgfilename, sizeof(dmgfilename), "%s.dmg", filename);
786 
787     mkdir(filename, 0777);
788 
789     if (run_command(filename, "tar xvzf ../%s", strrchr(tarfilename, '/') + 1))
790     {
791       fputs("epm: Unable to create disk image template folder!\n", stderr);
792       return (1);
793     }
794 
795     if (run_command(NULL, "hdiutil create -ov -srcfolder %s %s",
796 		    filename, dmgfilename))
797     {
798       fputs("epm: Unable to create disk image!\n", stderr);
799       return (1);
800     }
801 
802     if (!KeepFiles)
803       unlink_directory(filename);
804 
805     if (Verbosity)
806     {
807       stat(dmgfilename, &srcstat);
808 
809       printf("    %7.0fk %s\n", (srcstat.st_size + 1023) / 1024.0,
810 	     dmgfilename);
811     }
812   }
813 #endif /* __APPLE__ */
814 
815   return (0);
816 }
817 
818 
819 /*
820  * 'write_commands()' - Write commands.
821  */
822 
823 static int				/* O - 0 on success, -1 on failure */
write_commands(dist_t * dist,FILE * fp,int type,const char * subpackage)824 write_commands(dist_t     *dist,	/* I - Distribution */
825                FILE       *fp,		/* I - File pointer */
826                int        type,		/* I - Type of commands to write */
827                const char *subpackage)	/* I - Subsystem */
828 {
829   int			i;		/* Looping var */
830   command_t		*c;		/* Current command */
831   static const char	*commands[] =	/* Command strings */
832 			{
833 			  "pre-install",
834 			  "post-install",
835 			  "pre-patch",
836 			  "post-patch",
837 			  "pre-remove",
838 			  "post-remove"
839 			};
840 
841 
842   for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
843     if (c->type == type && c->subpackage == subpackage)
844       break;
845 
846   if (i)
847   {
848     fprintf(fp, "echo Running %s commands...\n", commands[type]);
849 
850     for (; i > 0; i --, c ++)
851       if (c->type == type && c->subpackage == subpackage)
852         if (fprintf(fp, "%s\n", c->command) < 1)
853         {
854           perror("epm: Error writing command");
855           return (-1);
856         }
857   }
858 
859   return (0);
860 }
861 
862 
863 /*
864  * 'write_common()' - Write the common shell script header.
865  */
866 
867 static FILE *				/* O - File pointer */
write_common(dist_t * dist,const char * title,int rootsize,int usrsize,const char * filename,const char * subpackage)868 write_common(dist_t     *dist,		/* I - Distribution */
869              const char *title,		/* I - "Installation", etc... */
870              int        rootsize,	/* I - Size of root files in kbytes */
871 	     int        usrsize,	/* I - Size of /usr files in kbytes */
872              const char *filename,	/* I - Script to create */
873 	     const char *subpackage)	/* I - Subpackage name */
874 {
875   int	i;				/* Looping var */
876   FILE	*fp;				/* File pointer */
877   char	line[1024],			/* Line buffer */
878 	*start,				/* Start of line */
879 	*ptr;				/* Pointer into line */
880 
881 
882  /*
883   * Remove any existing copy of the file...
884   */
885 
886   unlink(filename);
887 
888  /*
889   * Create the script file...
890   */
891 
892   if ((fp = fopen(filename, "w")) == NULL)
893     return (NULL);
894 
895  /*
896   * Update the permissions on the file...
897   */
898 
899   fchmod(fileno(fp), 0755);
900 
901  /*
902   * Write the standard header...
903   */
904 
905   fputs("#!/bin/sh\n", fp);
906   fprintf(fp, "# %s script for %s version %s.\n", title,
907           dist->product, dist->version);
908   fputs("# Produced using " EPM_VERSION " (https://michaelrsweet.github.io/epm).\n", fp);
909   fprintf(fp, "#%%product %s", dist->product);
910   if (subpackage)
911   {
912     for (i = 0; i < dist->num_descriptions; i ++)
913       if (dist->descriptions[i].subpackage == subpackage)
914 	break;
915 
916     if (i < dist->num_descriptions)
917     {
918       strlcpy(line, dist->descriptions[i].description, sizeof(line));
919       if ((ptr = strchr(line, '\n')) != NULL)
920         *ptr = '\0';
921 
922       fprintf(fp, " - %s", line);
923     }
924   }
925   fputs("\n", fp);
926   fprintf(fp, "#%%vendor %s\n", dist->vendor);
927   fprintf(fp, "#%%copyright %s\n", dist->copyright);
928   fprintf(fp, "#%%version %s %d\n", dist->version, dist->vernumber);
929 
930   for (i = 0; i < dist->num_descriptions; i ++)
931     if (dist->descriptions[i].subpackage == subpackage)
932       break;
933 
934   if (i < dist->num_descriptions)
935   {
936    /*
937     * Just do descriptions for this subpackage...
938     */
939 
940     for (; i < dist->num_descriptions; i ++)
941       if (dist->descriptions[i].subpackage == subpackage)
942       {
943         strlcpy(line, dist->descriptions[i].description, sizeof(line));
944 
945         for (start = line; start; start = ptr)
946 	{
947 	  if ((ptr = strchr(start, '\n')) != NULL)
948             *ptr++ = '\0';
949 
950 	  fprintf(fp, "#%%description %s\n", start);
951 	}
952       }
953   }
954   else
955   {
956    /*
957     * Just do descriptions for the main package...
958     */
959 
960     for (i = 0; i < dist->num_descriptions; i ++)
961       if (dist->descriptions[i].subpackage == NULL)
962       {
963         strlcpy(line, dist->descriptions[i].description, sizeof(line));
964 
965         for (start = line; start; start = ptr)
966 	{
967 	  if ((ptr = strchr(start, '\n')) != NULL)
968             *ptr++ = '\0';
969 
970 	  fprintf(fp, "#%%description %s\n", start);
971 	}
972       }
973   }
974 
975   fprintf(fp, "#%%rootsize %d\n", rootsize);
976   fprintf(fp, "#%%usrsize %d\n", usrsize);
977   fputs("#\n", fp);
978 
979   fputs("PATH=/usr/gnu/bin:/usr/xpg4/bin:/bin:/usr/bin:/usr/ucb:${PATH}\n", fp);
980   fputs("SHELL=/bin/sh\n", fp);
981   fputs("case \"`uname`\" in\n", fp);
982   fputs("\tDarwin*)\n", fp);
983   fputs("\tcase \"`id -un`\" in\n", fp);
984   fputs("\t\troot)\n", fp);
985   fputs("\t\t;;\n", fp);
986   fputs("\t\t*)\n", fp);
987   fprintf(fp, "\t\techo Sorry, you must have administrative priviledges to %s this software.\n",
988           title[0] == 'I' ? "install" : title[0] == 'R' ? "remove" : "patch");
989   fputs("\t\texit 1\n", fp);
990   fputs("\t\t;;\n", fp);
991   fputs("\tesac\n", fp);
992   fputs("\t;;\n", fp);
993   fputs("\t*)\n", fp);
994   fputs("\tcase \"`id`\" in\n", fp);
995   fputs("\t\tuid=0*)\n", fp);
996   fputs("\t\t;;\n", fp);
997   fputs("\t\t*)\n", fp);
998   fprintf(fp, "\t\techo Sorry, you must be root to %s this software.\n",
999           title[0] == 'I' ? "install" : title[0] == 'R' ? "remove" : "patch");
1000   fputs("\t\texit 1\n", fp);
1001   fputs("\t\t;;\n", fp);
1002   fputs("\tesac\n", fp);
1003   fputs("\t;;\n", fp);
1004   fputs("esac\n", fp);
1005 
1006   qprintf(fp, "echo Copyright %s\n", dist->copyright);
1007   fprintf(fp, "# Reset umask for %s...\n",
1008           title[0] == 'I' ? "install" : title[0] == 'R' ? "remove" : "patch");
1009   fputs("umask 002\n", fp);
1010 
1011   write_confcheck(fp);
1012 
1013  /*
1014   * Return the file pointer...
1015   */
1016 
1017   return (fp);
1018 }
1019 
1020 
1021 /*
1022  * 'write_confcheck()' - Write the echo check to find the right echo options.
1023  */
1024 
1025 static int				/* O - -1 on error, 0 on success */
write_confcheck(FILE * fp)1026 write_confcheck(FILE *fp)		/* I - Script file */
1027 {
1028  /*
1029   * This is a simplified version of the autoconf test for echo; basically
1030   * we ignore the Stardent Vistra SVR4 case, since 1) we've never heard of
1031   * this OS, and 2) it doesn't provide the same functionality, specifically
1032   * the omission of a newline when prompting the user for some text.
1033   */
1034 
1035   fputs("# Determine correct echo options...\n", fp);
1036   fputs("if (echo \"testing\\c\"; echo 1,2,3) | grep c >/dev/null; then\n", fp);
1037   fputs("	ac_n=-n\n", fp);
1038   fputs("	ac_c=\n", fp);
1039   fputs("else\n", fp);
1040   fputs("	ac_n=\n", fp);
1041   fputs("	ac_c='\\c'\n", fp);
1042   fputs("fi\n", fp);
1043 
1044  /*
1045   * This is a check for the correct options to use with the "tar"
1046   * command.
1047   */
1048 
1049   fputs("# Determine correct extract options for the tar command...\n", fp);
1050   fputs("if test `uname` = Darwin; then\n", fp);
1051   fputs("	ac_tar=\"tar -xpPf\"\n", fp);
1052   fputs("elif test \"`tar --help 2>&1 | grep GNU`\" = \"\"; then\n", fp);
1053   fputs("	ac_tar=\"tar -xpf\"\n", fp);
1054   fputs("else\n", fp);
1055   fputs("	ac_tar=\"tar -xpPf\"\n", fp);
1056   fputs("fi\n", fp);
1057 
1058   return (0);
1059 }
1060 
1061 
1062 /*
1063  * 'write_depends()' - Write dependencies.
1064  */
1065 
1066 static int				/* O - 0 on success, - 1 on failure */
write_depends(const char * prodname,dist_t * dist,FILE * fp,const char * subpackage)1067 write_depends(const char *prodname,	/* I - Product name */
1068               dist_t     *dist,		/* I - Distribution */
1069               FILE       *fp,		/* I - File pointer */
1070 	      const char *subpackage)	/* I - Subpackage */
1071 {
1072   int			i;		/* Looping var */
1073   depend_t		*d;		/* Current dependency */
1074   const char		*product;	/* Product/file to depend on */
1075   static const char	*depends[] =	/* Dependency strings */
1076 			{
1077 			  "requires",
1078 			  "incompat",
1079 			  "replaces",
1080 			  "provides"
1081 			};
1082 
1083 
1084   for (i = 0, d = dist->depends; i < dist->num_depends; i ++, d ++)
1085     if (d->subpackage == subpackage)
1086     {
1087       if (!strcmp(d->product, "_self"))
1088         product = prodname;
1089       else
1090         product = d->product;
1091 
1092       fprintf(fp, "#%%%s %s %d %d\n", depends[(int)d->type], product,
1093               d->vernumber[0], d->vernumber[1]);
1094 
1095       switch (d->type)
1096       {
1097 	case DEPEND_REQUIRES :
1098             if (product[0] == '/')
1099             {
1100              /*
1101               * Require a file...
1102               */
1103 
1104               qprintf(fp, "if test ! -r %s -a ! -h %s; then\n",
1105                       product, product);
1106               qprintf(fp, "	echo Sorry, you must first install \\'%s\\'!\n",
1107 	              product);
1108               fputs("	exit 1\n", fp);
1109               fputs("fi\n", fp);
1110             }
1111             else
1112             {
1113              /*
1114               * Require a product...
1115               */
1116 
1117               fprintf(fp, "if test ! -x %s/%s.remove; then\n",
1118                       SoftwareDir, product);
1119               fprintf(fp, "	if test -x %s.install; then\n",
1120                       product);
1121               fprintf(fp, "		echo Installing required %s software...\n",
1122                       product);
1123               fprintf(fp, "		./%s.install now\n", product);
1124               fputs("	else\n", fp);
1125               fprintf(fp, "		echo Sorry, you must first install \\'%s\\'!\n",
1126 	              product);
1127               fputs("		exit 1\n", fp);
1128               fputs("	fi\n", fp);
1129               fputs("fi\n", fp);
1130 
1131               if (d->vernumber[0] > 0 || d->vernumber[1] < INT_MAX)
1132 	      {
1133 	       /*
1134 		* Do version number checking...
1135 		*/
1136 
1137         	fprintf(fp, "installed=`grep \'^#%%version\' "
1138 	                    "%s/%s.remove | awk \'{print $3}\'`\n",
1139                 	SoftwareDir, product);
1140 
1141         	fputs("if test x$installed = x; then\n", fp);
1142 		fputs("	installed=0\n", fp);
1143 		fputs("fi\n", fp);
1144 
1145 		fprintf(fp, "if test $installed -lt %d -o $installed -gt %d; then\n",
1146 	        	d->vernumber[0], d->vernumber[1]);
1147         	fprintf(fp, "	if test -x %s.install; then\n",
1148                 	product);
1149         	fprintf(fp, "		echo Installing required %s software...\n",
1150                 	product);
1151         	fprintf(fp, "		./%s.install now\n", product);
1152         	fputs("	else\n", fp);
1153         	fprintf(fp, "		echo Sorry, you must first install \\'%s\\' version %s to %s!\n",
1154 	        	product, d->version[0], d->version[1]);
1155         	fputs("		exit 1\n", fp);
1156         	fputs("	fi\n", fp);
1157         	fputs("fi\n", fp);
1158 	      }
1159             }
1160 	    break;
1161 
1162 	case DEPEND_INCOMPAT :
1163             if (product[0] == '/')
1164             {
1165              /*
1166               * Incompatible with a file...
1167               */
1168 
1169               qprintf(fp, "if test -r %s -o -h %s; then\n",
1170                       product, product);
1171               qprintf(fp, "	echo Sorry, this software is incompatible with \\'%s\\'!\n",
1172 	              product);
1173               fputs("	echo Please remove it first.\n", fp);
1174               fputs("	exit 1\n", fp);
1175               fputs("fi\n", fp);
1176             }
1177             else
1178             {
1179              /*
1180               * Incompatible with a product...
1181               */
1182 
1183               fprintf(fp, "if test -x %s/%s.remove; then\n",
1184                       SoftwareDir, product);
1185 
1186               if (d->vernumber[0] > 0 || d->vernumber[1] < INT_MAX)
1187 	      {
1188 	       /*
1189 		* Do version number checking...
1190 		*/
1191 
1192         	fprintf(fp, "	installed=`grep \'^#%%version\' "
1193 	                    "%s/%s.remove | awk \'{print $3}\'`\n",
1194 			SoftwareDir, product);
1195 
1196         	fputs("	if test x$installed = x; then\n", fp);
1197 		fputs("		installed=0\n", fp);
1198 		fputs("	fi\n", fp);
1199 
1200 		fprintf(fp, "	if test $installed -ge %d -a $installed -le %d; then\n",
1201 	        	d->vernumber[0], d->vernumber[1]);
1202         	fprintf(fp, "		echo Sorry, this software is incompatible with \\'%s\\' version %s to %s!\n",
1203 	        	product, d->version[0], d->version[1]);
1204         	fprintf(fp, "		echo Please remove it first by running \\'%s/%s.remove\\'.\n",
1205 	        	SoftwareDir, product);
1206         	fputs("		exit 1\n", fp);
1207         	fputs("	fi\n", fp);
1208 	      }
1209 	      else
1210 	      {
1211         	fprintf(fp, "	echo Sorry, this software is incompatible with \\'%s\\'!\n",
1212 	        	product);
1213         	fprintf(fp, "	echo Please remove it first by running \\'%s/%s.remove\\'.\n",
1214 	        	SoftwareDir, product);
1215         	fputs("	exit 1\n", fp);
1216 	      }
1217 
1218               fputs("fi\n", fp);
1219             }
1220 	    break;
1221 
1222 	case DEPEND_REPLACES :
1223             fprintf(fp, "if test -x %s/%s.remove; then\n", SoftwareDir,
1224 	            product);
1225 
1226             if (d->vernumber[0] > 0 || d->vernumber[1] < INT_MAX)
1227 	    {
1228 	     /*
1229 	      * Do version number checking...
1230 	      */
1231 
1232               fprintf(fp, "	installed=`grep \'^#%%version\' "
1233 	                  "%s/%s.remove | awk \'{print $3}\'`\n",
1234                       SoftwareDir, product);
1235 
1236               fputs("	if test x$installed = x; then\n", fp);
1237 	      fputs("		installed=0\n", fp);
1238 	      fputs("	fi\n", fp);
1239 
1240 	      fprintf(fp, "	if test $installed -ge %d -a $installed -le %d; then\n",
1241 	              d->vernumber[0], d->vernumber[1]);
1242               fprintf(fp, "		echo Automatically replacing \\'%s\\'...\n",
1243 	              product);
1244               fprintf(fp, "		%s/%s.remove now\n",
1245 	              SoftwareDir, product);
1246               fputs("	fi\n", fp);
1247 	    }
1248 	    else
1249 	    {
1250               fprintf(fp, "	echo Automatically replacing \\'%s\\'...\n",
1251 	              product);
1252               fprintf(fp, "	%s/%s.remove now\n",
1253 	              SoftwareDir, product);
1254             }
1255 
1256             fputs("fi\n", fp);
1257 	    break;
1258       }
1259     }
1260 
1261   return (0);
1262 }
1263 
1264 
1265 /*
1266  * 'write_distfiles()' - Write a software distribution...
1267  */
1268 
1269 static int				/* O - -1 on error, 0 on success */
write_distfiles(const char * directory,const char * prodname,const char * platname,dist_t * dist,time_t deftime,const char * subpackage)1270 write_distfiles(const char *directory,	/* I - Directory */
1271 	        const char *prodname,	/* I - Product name */
1272                 const char *platname,	/* I - Platform name */
1273 	        dist_t     *dist,	/* I - Distribution */
1274 		time_t     deftime,	/* I - Default file time */
1275 	        const char *subpackage)	/* I - Subpackage */
1276 {
1277   int		i;			/* Looping var */
1278   int		havepatchfiles;		/* 1 if we have patch files, 0 otherwise */
1279   tarf_t	*tarfile;		/* Distribution tar file */
1280   char		prodfull[255],		/* Full name of product */
1281 		swname[255],		/* Name of distribution tar file */
1282 		pswname[255],		/* Name of patch tar file */
1283 		filename[1024];		/* Name of temporary file */
1284   struct stat	srcstat;		/* Source file information */
1285   file_t	*file;			/* Software file */
1286   int		rootsize,		/* Size of files in root partition */
1287 		usrsize;		/* Size of files in /usr partition */
1288   int		prootsize,		/* Size of patch files in root partition */
1289 		pusrsize;		/* Size of patch files in /usr partition */
1290 
1291 
1292  /*
1293   * Figure out the full name of the distribution...
1294   */
1295 
1296   if (subpackage)
1297     snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
1298   else
1299     strlcpy(prodfull, prodname, sizeof(prodfull));
1300 
1301  /*
1302   * See if we need to make a patch distribution...
1303   */
1304 
1305   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1306     if (isupper((int)file->type) && file->subpackage == subpackage)
1307       break;
1308 
1309   havepatchfiles = i > 0;
1310 
1311  /*
1312   * Copy the license and readme files...
1313   */
1314 
1315   if (Verbosity)
1316     printf("Copying %s license and readme files...\n", prodfull);
1317 
1318   if (dist->license[0])
1319   {
1320     snprintf(filename, sizeof(filename), "%s/%s.license", directory, prodfull);
1321     if (copy_file(filename, dist->license, 0444, getuid(), getgid()))
1322       return (1);
1323   }
1324 
1325   if (dist->readme[0])
1326   {
1327     snprintf(filename, sizeof(filename), "%s/%s.readme", directory, prodfull);
1328     if (copy_file(filename, dist->readme, 0444, getuid(), getgid()))
1329       return (1);
1330   }
1331 
1332  /*
1333   * Create the non-shared software distribution file...
1334   */
1335 
1336   if (Verbosity)
1337     puts("Creating non-shared software distribution file...");
1338 
1339   snprintf(swname, sizeof(swname), "%s.sw", prodfull);
1340   snprintf(filename, sizeof(filename), "%s/%s", directory, swname);
1341 
1342   unlink(filename);
1343   if ((tarfile = tar_open(filename, CompressFiles)) == NULL)
1344   {
1345     fprintf(stderr, "epm: Unable to create file \"%s\" -\n     %s\n",
1346             filename, strerror(errno));
1347     return (1);
1348   }
1349 
1350   for (i = dist->num_files, file = dist->files, rootsize = 0, prootsize = 0;
1351        i > 0;
1352        i --, file ++)
1353     if (strncmp(file->dst, "/usr", 4) != 0 && file->subpackage == subpackage)
1354       switch (tolower(file->type))
1355       {
1356 	case 'f' : /* Regular file */
1357 	case 'c' : /* Config file */
1358 	case 'i' : /* Init script */
1359             if (stat(file->src, &srcstat))
1360 	    {
1361 	      fprintf(stderr, "epm: Cannot stat \"%s\": %s\n", file->src, strerror(errno));
1362 	      tar_close(tarfile);
1363 	      return (1);
1364 	    }
1365 
1366             rootsize += (srcstat.st_size + 1023) / 1024;
1367 
1368             if (isupper(file->type & 255))
1369               prootsize += (srcstat.st_size + 1023) / 1024;
1370 
1371            /*
1372 	    * Configuration files are extracted to the config file name with
1373 	    * .N appended; add a bit of script magic to check if the config
1374 	    * file already exists, and if not we copy the .N to the config
1375 	    * file location...
1376 	    */
1377 
1378 	    if (tolower(file->type) == 'c')
1379 	      snprintf(filename, sizeof(filename), "%s.N", file->dst);
1380 	    else if (tolower(file->type) == 'i')
1381 	      snprintf(filename, sizeof(filename), "%s/init.d/%s", SoftwareDir,
1382 	               file->dst);
1383 	    else
1384               strlcpy(filename, file->dst, sizeof(filename));
1385 
1386             if (Verbosity > 1)
1387 	      printf("%s -> %s...\n", file->src, filename);
1388 
1389 	    if (tar_header(tarfile, TAR_NORMAL, file->mode, srcstat.st_size,
1390 	                   srcstat.st_mtime, file->user, file->group,
1391 			   filename, NULL) < 0)
1392 	    {
1393 	      tar_close(tarfile);
1394 	      return (1);
1395 	    }
1396 
1397 	    if (tar_file(tarfile, file->src) < 0)
1398 	    {
1399 	      tar_close(tarfile);
1400 	      return (1);
1401 	    }
1402 	    break;
1403 
1404 	case 'd' : /* Create directory */
1405             if (Verbosity > 1)
1406 	      printf("Directory %s...\n", file->dst);
1407 
1408             rootsize ++;
1409 
1410             if (isupper(file->type & 255))
1411               prootsize ++;
1412 	    break;
1413 
1414 	case 'l' : /* Link file */
1415             if (Verbosity > 1)
1416 	      printf("%s -> %s...\n", file->src, file->dst);
1417 
1418 	    if (tar_header(tarfile, TAR_SYMLINK, file->mode, 0, deftime,
1419 	                   file->user, file->group, file->dst, file->src) < 0)
1420 	    {
1421 	      tar_close(tarfile);
1422 	      return (1);
1423 	    }
1424 
1425             rootsize ++;
1426 
1427             if (isupper(file->type & 255))
1428               prootsize ++;
1429 	    break;
1430       }
1431 
1432   tar_close(tarfile);
1433 
1434  /*
1435   * Create the shared software distribution file...
1436   */
1437 
1438   if (Verbosity)
1439     puts("Creating shared software distribution file...");
1440 
1441   snprintf(swname, sizeof(swname), "%s.ss", prodfull);
1442   snprintf(filename, sizeof(filename), "%s/%s", directory, swname);
1443 
1444   unlink(filename);
1445   if ((tarfile = tar_open(filename, CompressFiles)) == NULL)
1446   {
1447     fprintf(stderr, "epm: Unable to create file \"%s\" -\n     %s\n",
1448             filename, strerror(errno));
1449     return (1);
1450   }
1451 
1452   for (i = dist->num_files, file = dist->files, usrsize = 0, pusrsize = 0;
1453        i > 0;
1454        i --, file ++)
1455     if (strncmp(file->dst, "/usr", 4) == 0 && file->subpackage == subpackage)
1456       switch (tolower(file->type))
1457       {
1458 	case 'f' : /* Regular file */
1459 	case 'c' : /* Config file */
1460 	case 'i' : /* Init script */
1461             if (stat(file->src, &srcstat))
1462 	    {
1463 	      fprintf(stderr, "epm: Cannot stat \"%s\": %s\n", file->src, strerror(errno));
1464 	      tar_close(tarfile);
1465 	      return (1);
1466 	    }
1467 
1468             usrsize += (srcstat.st_size + 1023) / 1024;
1469 
1470             if (isupper(file->type & 255))
1471               pusrsize += (srcstat.st_size + 1023) / 1024;
1472 
1473            /*
1474 	    * Configuration files are extracted to the config file name with
1475 	    * .N appended; add a bit of script magic to check if the config
1476 	    * file already exists, and if not we copy the .N to the config
1477 	    * file location...
1478 	    */
1479 
1480 	    if (tolower(file->type) == 'c')
1481 	      snprintf(filename, sizeof(filename), "%s.N", file->dst);
1482 	    else if (tolower(file->type) == 'i')
1483 	      snprintf(filename, sizeof(filename), "%s/init.d/%s", SoftwareDir,
1484 	               file->dst);
1485 	    else
1486               strlcpy(filename, file->dst, sizeof(filename));
1487 
1488             if (Verbosity > 1)
1489 	      printf("%s -> %s...\n", file->src, filename);
1490 
1491 	    if (tar_header(tarfile, TAR_NORMAL, file->mode, srcstat.st_size,
1492 	                   srcstat.st_mtime, file->user, file->group,
1493 			   filename, NULL) < 0)
1494 	    {
1495 	      tar_close(tarfile);
1496 	      return (1);
1497 	    }
1498 
1499 	    if (tar_file(tarfile, file->src) < 0)
1500 	    {
1501 	      tar_close(tarfile);
1502 	      return (1);
1503 	    }
1504 	    break;
1505 
1506 	case 'd' : /* Create directory */
1507             if (Verbosity > 1)
1508 	      printf("%s...\n", file->dst);
1509 
1510 	    usrsize ++;
1511 
1512             if (isupper(file->type & 255))
1513               pusrsize ++;
1514 	    break;
1515 
1516 	case 'l' : /* Link file */
1517             if (Verbosity > 1)
1518 	      printf("%s -> %s...\n", file->src, file->dst);
1519 
1520 	    if (tar_header(tarfile, TAR_SYMLINK, file->mode, 0, deftime,
1521 	                   file->user, file->group, file->dst, file->src) < 0)
1522 	    {
1523 	      tar_close(tarfile);
1524 	      return (1);
1525 	    }
1526 
1527 	    usrsize ++;
1528 
1529             if (isupper(file->type & 255))
1530               pusrsize ++;
1531 	    break;
1532       }
1533 
1534   tar_close(tarfile);
1535 
1536  /*
1537   * Create the patch distribution files...
1538   */
1539 
1540   if (havepatchfiles)
1541   {
1542     if (Verbosity)
1543       puts("Creating non-shared software patch file...");
1544 
1545     snprintf(pswname, sizeof(pswname), "%s.psw", prodfull);
1546     snprintf(filename, sizeof(filename), "%s/%s", directory, pswname);
1547 
1548     unlink(filename);
1549     if ((tarfile = tar_open(filename, CompressFiles)) == NULL)
1550     {
1551       fprintf(stderr, "epm: Unable to create file \"%s\" -\n     %s\n",
1552               filename, strerror(errno));
1553       return (1);
1554     }
1555 
1556     for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1557       if (strncmp(file->dst, "/usr", 4) != 0 && file->subpackage == subpackage)
1558 	switch (file->type)
1559 	{
1560 	  case 'C' : /* Config file */
1561 	  case 'F' : /* Regular file */
1562           case 'I' : /* Init script */
1563               if (stat(file->src, &srcstat))
1564 	      {
1565 		fprintf(stderr, "epm: Cannot stat \"%s\": %s\n", file->src, strerror(errno));
1566 		tar_close(tarfile);
1567 		return (1);
1568 	      }
1569 
1570              /*
1571 	      * Configuration files are extracted to the config file name with
1572 	      * .N appended; add a bit of script magic to check if the config
1573 	      * file already exists, and if not we copy the .N to the config
1574 	      * file location...
1575 	      */
1576 
1577 	      if (file->type == 'C')
1578 		snprintf(filename, sizeof(filename), "%s.N", file->dst);
1579 	      else if (file->type == 'I')
1580 		snprintf(filename, sizeof(filename), "%s/init.d/%s", SoftwareDir,
1581 		         file->dst);
1582 	      else
1583         	strlcpy(filename, file->dst, sizeof(filename));
1584 
1585               if (Verbosity > 1)
1586 		printf("%s -> %s...\n", file->src, filename);
1587 
1588 	      if (tar_header(tarfile, TAR_NORMAL, file->mode, srcstat.st_size,
1589 	                     srcstat.st_mtime, file->user, file->group,
1590 			     filename, NULL) < 0)
1591 	      {
1592 		tar_close(tarfile);
1593 		return (1);
1594 	      }
1595 
1596 	      if (tar_file(tarfile, file->src) < 0)
1597 	      {
1598 		tar_close(tarfile);
1599 		return (1);
1600 	      }
1601 	      break;
1602 
1603 	  case 'd' : /* Create directory */
1604               if (Verbosity > 1)
1605 		printf("%s...\n", file->dst);
1606 	      break;
1607 
1608 	  case 'L' : /* Link file */
1609               if (Verbosity > 1)
1610 		printf("%s -> %s...\n", file->src, file->dst);
1611 
1612 	      if (tar_header(tarfile, TAR_SYMLINK, file->mode, 0, deftime,
1613 	                     file->user, file->group, file->dst, file->src) < 0)
1614 	      {
1615 		tar_close(tarfile);
1616 		return (1);
1617 	      }
1618 	      break;
1619 	}
1620 
1621     tar_close(tarfile);
1622 
1623     if (Verbosity)
1624       puts("Creating shared software patch file...");
1625 
1626     snprintf(pswname, sizeof(pswname), "%s.pss", prodfull);
1627     snprintf(filename, sizeof(filename), "%s/%s", directory, pswname);
1628 
1629     unlink(filename);
1630     if ((tarfile = tar_open(filename, CompressFiles)) == NULL)
1631     {
1632       fprintf(stderr, "epm: Unable to create file \"%s\" -\n     %s\n",
1633               filename, strerror(errno));
1634       return (1);
1635     }
1636 
1637     for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1638       if (strncmp(file->dst, "/usr", 4) == 0 && file->subpackage == subpackage)
1639 	switch (file->type)
1640 	{
1641 	  case 'C' : /* Config file */
1642 	  case 'F' : /* Regular file */
1643           case 'I' : /* Init script */
1644               if (stat(file->src, &srcstat))
1645 	      {
1646 		fprintf(stderr, "epm: Cannot stat \"%s\": %s\n", file->src, strerror(errno));
1647 		tar_close(tarfile);
1648 		return (1);
1649 	      }
1650 
1651              /*
1652 	      * Configuration files are extracted to the config file name with
1653 	      * .N appended; add a bit of script magic to check if the config
1654 	      * file already exists, and if not we copy the .N to the config
1655 	      * file location...
1656 	      */
1657 
1658 	      if (file->type == 'C')
1659 		snprintf(filename, sizeof(filename), "%s.N", file->dst);
1660 	      else if (file->type == 'I')
1661 		snprintf(filename, sizeof(filename), "%s/init.d/%s",
1662 		         SoftwareDir, file->dst);
1663 	      else
1664         	strlcpy(filename, file->dst, sizeof(filename));
1665 
1666               if (Verbosity > 1)
1667 		printf("%s -> %s...\n", file->src, filename);
1668 
1669 	      if (tar_header(tarfile, TAR_NORMAL, file->mode, srcstat.st_size,
1670 	                     srcstat.st_mtime, file->user, file->group,
1671 			     filename, NULL) < 0)
1672 	      {
1673 		tar_close(tarfile);
1674 		return (1);
1675 	      }
1676 
1677 	      if (tar_file(tarfile, file->src) < 0)
1678 	      {
1679 		tar_close(tarfile);
1680 		return (1);
1681 	      }
1682 	      break;
1683 
1684 	  case 'd' : /* Create directory */
1685               if (Verbosity > 1)
1686 		printf("%s...\n", file->dst);
1687 	      break;
1688 
1689 	  case 'L' : /* Link file */
1690               if (Verbosity > 1)
1691 		printf("%s -> %s...\n", file->src, file->dst);
1692 
1693 	      if (tar_header(tarfile, TAR_SYMLINK, file->mode, 0, deftime,
1694 	                     file->user, file->group, file->dst, file->src) < 0)
1695 	      {
1696 		tar_close(tarfile);
1697 		return (1);
1698 	      }
1699 	      break;
1700 	}
1701 
1702     tar_close(tarfile);
1703   }
1704 
1705  /*
1706   * Create the scripts...
1707   */
1708 
1709   if (write_install(dist, prodname, rootsize, usrsize, directory, subpackage))
1710     return (1);
1711 
1712   if (havepatchfiles)
1713     if (write_patch(dist, prodname, prootsize, pusrsize, directory, subpackage))
1714       return (1);
1715 
1716   if (write_remove(dist, prodname, rootsize, usrsize, directory, subpackage))
1717     return (1);
1718 
1719  /*
1720   * Return...
1721   */
1722 
1723   return (0);
1724 }
1725 
1726 
1727 /*
1728  * 'write_install()' - Write the installation script.
1729  */
1730 
1731 static int				/* O - -1 on error, 0 on success */
write_install(dist_t * dist,const char * prodname,int rootsize,int usrsize,const char * directory,const char * subpackage)1732 write_install(dist_t     *dist,		/* I - Software distribution */
1733               const char *prodname,	/* I - Product name */
1734               int        rootsize,	/* I - Size of root files in kbytes */
1735 	      int        usrsize,	/* I - Size of /usr files in kbytes */
1736 	      const char *directory,	/* I - Directory */
1737 	      const char *subpackage)	/* I - Subpackage */
1738 {
1739   int		i;			/* Looping var */
1740   int		col;			/* Column in the output */
1741   FILE		*scriptfile;		/* Install script */
1742   char		prodfull[255];		/* Full product name */
1743   char		filename[1024];		/* Name of temporary file */
1744   file_t	*file;			/* Software file */
1745   const char	*runlevels;		/* Run levels */
1746   int		number;			/* Start/stop number */
1747 
1748 
1749   if (Verbosity)
1750     puts("Writing installation script...");
1751 
1752   if (subpackage)
1753     snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
1754   else
1755     strlcpy(prodfull, prodname, sizeof(prodfull));
1756 
1757   snprintf(filename, sizeof(filename), "%s/%s.install", directory, prodfull);
1758 
1759   if ((scriptfile = write_common(dist, "Installation", rootsize, usrsize,
1760                                  filename, subpackage)) == NULL)
1761   {
1762     fprintf(stderr, "epm: Unable to create installation script \"%s\" -\n"
1763                     "     %s\n", filename, strerror(errno));
1764     return (-1);
1765   }
1766 
1767   fputs("if test \"$*\" = \"now\"; then\n", scriptfile);
1768   fputs("	echo Software license silently accepted via command-line option.\n", scriptfile);
1769   fputs("else\n", scriptfile);
1770   fputs("	echo \"\"\n", scriptfile);
1771   qprintf(scriptfile, "	echo This installation script will install the %s\n",
1772           dist->product);
1773   qprintf(scriptfile, "	echo software version %s on your system.\n",
1774           dist->version);
1775   fputs("	echo \"\"\n", scriptfile);
1776   fputs("	while true ; do\n", scriptfile);
1777   fputs("		echo $ac_n \"Do you wish to continue? $ac_c\"\n", scriptfile);
1778   fputs("		read yesno\n", scriptfile);
1779   fputs("		case \"$yesno\" in\n", scriptfile);
1780   fputs("			y | yes | Y | Yes | YES)\n", scriptfile);
1781   fputs("			break\n", scriptfile);
1782   fputs("			;;\n", scriptfile);
1783   fputs("			n | no | N | No | NO)\n", scriptfile);
1784   fputs("			exit 1\n", scriptfile);
1785   fputs("			;;\n", scriptfile);
1786   fputs("			*)\n", scriptfile);
1787   fputs("			echo Please enter yes or no.\n", scriptfile);
1788   fputs("			;;\n", scriptfile);
1789   fputs("		esac\n", scriptfile);
1790   fputs("	done\n", scriptfile);
1791 
1792   if (dist->license[0])
1793   {
1794     fprintf(scriptfile, "	more %s.license\n", prodfull);
1795     fputs("	echo \"\"\n", scriptfile);
1796     fputs("	while true ; do\n", scriptfile);
1797     fputs("		echo $ac_n \"Do you agree with the terms of this license? $ac_c\"\n", scriptfile);
1798     fputs("		read yesno\n", scriptfile);
1799     fputs("		case \"$yesno\" in\n", scriptfile);
1800     fputs("			y | yes | Y | Yes | YES)\n", scriptfile);
1801     fputs("			break\n", scriptfile);
1802     fputs("			;;\n", scriptfile);
1803     fputs("			n | no | N | No | NO)\n", scriptfile);
1804     fputs("			exit 1\n", scriptfile);
1805     fputs("			;;\n", scriptfile);
1806     fputs("			*)\n", scriptfile);
1807     fputs("			echo Please enter yes or no.\n", scriptfile);
1808     fputs("			;;\n", scriptfile);
1809     fputs("		esac\n", scriptfile);
1810     fputs("	done\n", scriptfile);
1811   }
1812 
1813   fputs("fi\n", scriptfile);
1814   fprintf(scriptfile, "if test -x %s/%s.remove; then\n", SoftwareDir, prodfull);
1815   fprintf(scriptfile, "	echo Removing old versions of %s software...\n",
1816           prodfull);
1817   fprintf(scriptfile, "	%s/%s.remove now\n", SoftwareDir, prodfull);
1818   fputs("fi\n", scriptfile);
1819 
1820   write_space_checks(prodfull, scriptfile, rootsize ? "sw" : NULL,
1821                      usrsize ? "ss" : NULL, rootsize, usrsize);
1822   write_depends(prodname, dist, scriptfile, subpackage);
1823   write_commands(dist, scriptfile, COMMAND_PRE_INSTALL, subpackage);
1824 
1825   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1826     if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
1827         strncmp(file->dst, "/usr", 4) != 0 && file->subpackage == subpackage)
1828       break;
1829 
1830   if (i)
1831   {
1832     fputs("echo Backing up old versions of non-shared files to be installed...\n", scriptfile);
1833 
1834     col = fputs("for file in", scriptfile);
1835     for (; i > 0; i --, file ++)
1836       if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
1837           strncmp(file->dst, "/usr", 4) != 0 && file->subpackage == subpackage)
1838       {
1839         if (col > 80)
1840 	  col = qprintf(scriptfile, " \\\n%s", file->dst) - 2;
1841 	else
1842           col += qprintf(scriptfile, " %s", file->dst);
1843       }
1844 
1845     fputs("; do\n", scriptfile);
1846     fputs("	if test -d \"$file\" -o -f \"$file\" -o -h \"$file\"; then\n", scriptfile);
1847     fputs("		mv -f \"$file\" \"$file.O\"\n", scriptfile);
1848     fputs("	fi\n", scriptfile);
1849     fputs("done\n", scriptfile);
1850   }
1851 
1852   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1853     if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
1854         strncmp(file->dst, "/usr", 4) == 0 && file->subpackage == subpackage)
1855       break;
1856 
1857   if (i)
1858   {
1859     fputs("if test -w /usr ; then\n", scriptfile);
1860     fputs("	echo Backing up old versions of shared files to be installed...\n", scriptfile);
1861 
1862     col = fputs("	for file in", scriptfile);
1863     for (; i > 0; i --, file ++)
1864       if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
1865           strncmp(file->dst, "/usr", 4) == 0 && file->subpackage == subpackage)
1866       {
1867         if (col > 80)
1868 	  col = qprintf(scriptfile, " \\\n%s", file->dst) - 2;
1869 	else
1870           col += qprintf(scriptfile, " %s", file->dst);
1871       }
1872 
1873     fputs("; do\n", scriptfile);
1874     fputs("		if test -d \"$file\" -o -f \"$file\" -o -h \"$file\"; then\n", scriptfile);
1875     fputs("			mv -f \"$file\" \"$file.O\"\n", scriptfile);
1876     fputs("		fi\n", scriptfile);
1877     fputs("	done\n", scriptfile);
1878     fputs("fi\n", scriptfile);
1879   }
1880 
1881   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1882     if (tolower(file->type) == 'd' && file->subpackage == subpackage)
1883       break;
1884 
1885   if (i)
1886   {
1887     fputs("echo Creating installation directories...\n", scriptfile);
1888 
1889     for (; i > 0; i --, file ++)
1890       if (tolower(file->type) == 'd' && file->subpackage == subpackage)
1891       {
1892 	qprintf(scriptfile, "if test ! -d %s -a ! -f %s -a ! -h %s; then\n",
1893         	file->dst, file->dst, file->dst);
1894 	qprintf(scriptfile, "	mkdir -p %s\n", file->dst);
1895 	fputs("else\n", scriptfile);
1896 	qprintf(scriptfile, "	if test -f %s; then\n", file->dst);
1897 	qprintf(scriptfile, "		echo Error: %s already exists as a regular file!\n",
1898 	        file->dst);
1899 	fputs("		exit 1\n", scriptfile);
1900 	fputs("	fi\n", scriptfile);
1901 	fputs("fi\n", scriptfile);
1902 	qprintf(scriptfile, "chown %s %s\n", file->user, file->dst);
1903 	qprintf(scriptfile, "chgrp %s %s\n", file->group, file->dst);
1904 	qprintf(scriptfile, "chmod %o %s\n", file->mode, file->dst);
1905       }
1906   }
1907 
1908   fputs("echo Installing software...\n", scriptfile);
1909 
1910   if (rootsize)
1911   {
1912     if (CompressFiles)
1913       fprintf(scriptfile, "gzip -dc %s.sw | $ac_tar -\n", prodfull);
1914     else
1915       fprintf(scriptfile, "$ac_tar %s.sw\n", prodfull);
1916   }
1917 
1918   if (usrsize)
1919   {
1920     fputs("if echo Write Test >/usr/.writetest 2>/dev/null; then\n", scriptfile);
1921     if (CompressFiles)
1922       fprintf(scriptfile, "	gzip -dc %s.ss | $ac_tar -\n", prodfull);
1923     else
1924       fprintf(scriptfile, "	$ac_tar %s.ss\n", prodfull);
1925     fputs("fi\n", scriptfile);
1926   }
1927 
1928   fprintf(scriptfile, "if test -d %s; then\n", SoftwareDir);
1929   fprintf(scriptfile, "	rm -f %s/%s.remove\n", SoftwareDir, prodfull);
1930   fputs("else\n", scriptfile);
1931   fprintf(scriptfile, "	mkdir -p %s\n", SoftwareDir);
1932   fputs("fi\n", scriptfile);
1933   fprintf(scriptfile, "cp %s.remove %s\n", prodfull, SoftwareDir);
1934   fprintf(scriptfile, "chmod 544 %s/%s.remove\n", SoftwareDir, prodfull);
1935 
1936   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1937     if (tolower(file->type) == 'c' && file->subpackage == subpackage)
1938       break;
1939 
1940   if (i)
1941   {
1942     fputs("echo Checking configuration files...\n", scriptfile);
1943 
1944     col = fputs("for file in", scriptfile);
1945     for (; i > 0; i --, file ++)
1946       if (tolower(file->type) == 'c' && file->subpackage == subpackage)
1947       {
1948         if (col > 80)
1949 	  col = qprintf(scriptfile, " \\\n%s", file->dst) - 2;
1950 	else
1951           col += qprintf(scriptfile, " %s", file->dst);
1952       }
1953 
1954     fputs("; do\n", scriptfile);
1955     fputs("	if test ! -f \"$file\"; then\n", scriptfile);
1956     fputs("		cp \"$file.N\" \"$file\"\n", scriptfile);
1957     fputs("	fi\n", scriptfile);
1958     fputs("done\n", scriptfile);
1959   }
1960 
1961   fputs("echo Updating file permissions...\n", scriptfile);
1962 
1963   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1964     if (strncmp(file->dst, "/usr", 4) != 0 &&
1965         strcmp(file->user, "root") != 0 && file->subpackage == subpackage)
1966       switch (tolower(file->type))
1967       {
1968 	case 'c' :
1969 	    qprintf(scriptfile, "chown %s %s.N\n", file->user, file->dst);
1970 	    qprintf(scriptfile, "chgrp %s %s.N\n", file->group, file->dst);
1971 	case 'f' :
1972 	    qprintf(scriptfile, "chown %s %s\n", file->user, file->dst);
1973 	    qprintf(scriptfile, "chgrp %s %s\n", file->group, file->dst);
1974 	    break;
1975       }
1976 
1977   fputs("if test -f /usr/.writetest; then\n", scriptfile);
1978   fputs("	rm -f /usr/.writetest\n", scriptfile);
1979   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1980     if (strncmp(file->dst, "/usr", 4) == 0 &&
1981         strcmp(file->user, "root") != 0 && file->subpackage == subpackage)
1982       switch (tolower(file->type))
1983       {
1984 	case 'c' :
1985 	    qprintf(scriptfile, "	chown %s %s.N\n", file->user, file->dst);
1986 	    qprintf(scriptfile, "	chgrp %s %s.N\n", file->group, file->dst);
1987 	case 'f' :
1988 	    qprintf(scriptfile, "	chown %s %s\n", file->user, file->dst);
1989 	    qprintf(scriptfile, "	chgrp %s %s\n", file->group, file->dst);
1990 	    break;
1991       }
1992   fputs("fi\n", scriptfile);
1993 
1994   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
1995     if (tolower(file->type) == 'i' && file->subpackage == subpackage)
1996       break;
1997 
1998   if (i)
1999   {
2000     fputs("echo Setting up init scripts...\n", scriptfile);
2001 
2002    /*
2003     * Find where the frigging init scripts go...
2004     */
2005 
2006     fputs("rcdir=\"\"\n", scriptfile);
2007     fputs("for dir in /sbin/rc.d /sbin /etc/rc.d /etc ; do\n", scriptfile);
2008     fputs("	if test -d $dir/rc2.d -o -h $dir/rc2.d -o "
2009           "-d $dir/rc3.d -o -h $dir/rc3.d; then\n", scriptfile);
2010     fputs("		rcdir=\"$dir\"\n", scriptfile);
2011     fputs("	fi\n", scriptfile);
2012     fputs("done\n", scriptfile);
2013     fputs("if test \"$rcdir\" = \"\" ; then\n", scriptfile);
2014     fputs("	if test -d /usr/local/etc/rc.d; then\n", scriptfile);
2015     fputs("		for file in", scriptfile);
2016     for (; i > 0; i --, file ++)
2017       if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2018         qprintf(scriptfile, " %s", file->dst);
2019     fputs("; do\n", scriptfile);
2020     fputs("			rm -f /usr/local/etc/rc.d/$file.sh\n", scriptfile);
2021     qprintf(scriptfile, "			ln -s %s/init.d/$file "
2022                         "/usr/local/etc/rc.d/$file.sh\n",
2023             SoftwareDir);
2024     fputs("		done\n", scriptfile);
2025     fputs("	else\n", scriptfile);
2026     fputs("		echo Unable to determine location of startup scripts!\n", scriptfile);
2027     fputs("	fi\n", scriptfile);
2028     fputs("else\n", scriptfile);
2029     for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2030       if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2031       {
2032 	fputs("	if test -d $rcdir/init.d; then\n", scriptfile);
2033 	qprintf(scriptfile, "		/bin/rm -f $rcdir/init.d/%s\n", file->dst);
2034 	qprintf(scriptfile, "		/bin/ln -s %s/init.d/%s "
2035                     "$rcdir/init.d/%s\n", SoftwareDir, file->dst, file->dst);
2036 	fputs("	else\n", scriptfile);
2037 	fputs("		if test -d /etc/init.d; then\n", scriptfile);
2038 	qprintf(scriptfile, "			/bin/rm -f /etc/init.d/%s\n", file->dst);
2039 	qprintf(scriptfile, "			/bin/ln -s %s/init.d/%s "
2040                     "/etc/init.d/%s\n", SoftwareDir, file->dst, file->dst);
2041 	fputs("		fi\n", scriptfile);
2042 	fputs("	fi\n", scriptfile);
2043 
2044 	for (runlevels = get_runlevels(dist->files + i, "0235");
2045              isdigit(*runlevels & 255);
2046 	     runlevels ++)
2047 	{
2048 	  if (*runlevels == '0')
2049             number = get_stop(file, 0);
2050 	  else
2051 	    number = get_start(file, 99);
2052 
2053           fprintf(scriptfile, "	if test -d $rcdir/rc%c.d; then\n", *runlevels);
2054 	  qprintf(scriptfile, "		/bin/rm -f $rcdir/rc%c.d/%c%02d%s\n",
2055 	          *runlevels, *runlevels == '0' ? 'K' : 'S', number, file->dst);
2056 	  qprintf(scriptfile, "		/bin/ln -s %s/init.d/%s "
2057                               "$rcdir/rc%c.d/%c%02d%s\n",
2058                   SoftwareDir, file->dst, *runlevels,
2059 		  *runlevels == '0' ? 'K' : 'S', number, file->dst);
2060 	  fputs("	fi\n", scriptfile);
2061         }
2062 
2063 #ifdef __sgi
2064         fputs("	if test -x /etc/chkconfig; then\n", scriptfile);
2065         qprintf(scriptfile, "		/etc/chkconfig -f %s on\n", file->dst);
2066         fputs("	fi\n", scriptfile);
2067 #endif /* __sgi */
2068 
2069       }
2070 
2071     fputs("fi\n", scriptfile);
2072   }
2073 
2074   write_commands(dist, scriptfile, COMMAND_POST_INSTALL, subpackage);
2075 
2076   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2077     if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2078       qprintf(scriptfile, "%s/init.d/%s start\n", SoftwareDir, file->dst);
2079 
2080   fputs("echo Installation is complete.\n", scriptfile);
2081 
2082   fclose(scriptfile);
2083 
2084   return (0);
2085 }
2086 
2087 
2088 /*
2089  * 'write_instfiles()' - Write the installer files to the tar file...
2090  */
2091 
2092 static int				/* O - 0 = success, -1 on failure */
write_instfiles(tarf_t * tarfile,const char * directory,const char * prodname,const char * platname,const char ** files,const char * destdir,const char * subpackage)2093 write_instfiles(tarf_t     *tarfile,	/* I - Distribution tar file */
2094                 const char *directory,	/* I - Output directory */
2095                 const char *prodname,	/* I - Base product name */
2096 	        const char *platname,	/* I - Platform name */
2097 	        const char **files,	/* I - Files */
2098 		const char *destdir,	/* I - Destination directory in tar file */
2099 	        const char *subpackage)	/* I - Subpackage */
2100 {
2101   int		i;			/* Looping var */
2102   char		srcname[1024],		/* Name of source file in distribution */
2103 		dstname[1024],		/* Name of destination file in distribution */
2104 		prodfull[255];		/* Full name of product */
2105   struct stat	srcstat;		/* Source file information */
2106 
2107 
2108   if (subpackage)
2109     snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
2110   else
2111     strlcpy(prodfull, prodname, sizeof(prodfull));
2112 
2113   for (i = 0; files[i] != NULL; i ++)
2114   {
2115     snprintf(srcname, sizeof(srcname), "%s/%s.%s", directory, prodfull, files[i]);
2116     snprintf(dstname, sizeof(dstname), "%s%s.%s", destdir, prodfull, files[i]);
2117 
2118     if (stat(srcname, &srcstat))
2119     {
2120       if (!i)
2121         break;
2122       else
2123         continue;
2124     }
2125 
2126     if (srcstat.st_size == 0)
2127       continue;
2128 
2129     if (tar_header(tarfile, TAR_NORMAL, srcstat.st_mode & 07555,
2130                    srcstat.st_size, srcstat.st_mtime, "root", "root",
2131 		   dstname, NULL) < 0)
2132     {
2133       return (-1);
2134     }
2135 
2136     if (tar_file(tarfile, srcname) < 0)
2137       return (-1);
2138 
2139     if (Verbosity)
2140       printf("    %7.0fk %s.%s\n", (srcstat.st_size + 1023) / 1024.0,
2141 	     prodfull, files[i]);
2142   }
2143 
2144   return (0);
2145 }
2146 
2147 
2148 /*
2149  * 'write_patch()' - Write the patch script.
2150  */
2151 
2152 static int				/* O - -1 on error, 0 on success */
write_patch(dist_t * dist,const char * prodname,int rootsize,int usrsize,const char * directory,const char * subpackage)2153 write_patch(dist_t     *dist,		/* I - Software distribution */
2154             const char *prodname,	/* I - Product name */
2155             int        rootsize,	/* I - Size of root files in kbytes */
2156 	    int        usrsize,		/* I - Size of /usr files in kbytes */
2157 	    const char *directory,	/* I - Directory */
2158 	    const char *subpackage)	/* I - Subpackage */
2159 {
2160   int		i;			/* Looping var */
2161   FILE		*scriptfile;		/* Patch script */
2162   char		filename[1024];		/* Name of temporary file */
2163   char		prodfull[255];		/* Full product name */
2164   file_t	*file;			/* Software file */
2165   const char	*runlevels;		/* Run levels */
2166   int		number;			/* Start/stop number */
2167 
2168 
2169   if (Verbosity)
2170     puts("Writing patch script...");
2171 
2172   if (subpackage)
2173     snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
2174   else
2175     strlcpy(prodfull, prodname, sizeof(prodfull));
2176 
2177   snprintf(filename, sizeof(filename), "%s/%s.patch", directory, prodfull);
2178 
2179   if ((scriptfile = write_common(dist, "Patch", rootsize, usrsize,
2180                                  filename, subpackage)) == NULL)
2181   {
2182     fprintf(stderr, "epm: Unable to create patch script \"%s\" -\n"
2183                     "     %s\n", filename, strerror(errno));
2184     return (-1);
2185   }
2186 
2187   fputs("if test \"$*\" = \"now\"; then\n", scriptfile);
2188   fputs("	echo Software license silently accepted via command-line option.\n", scriptfile);
2189   fputs("else\n", scriptfile);
2190   fputs("	echo \"\"\n", scriptfile);
2191   qprintf(scriptfile, "	echo This installation script will patch the %s\n",
2192           dist->product);
2193   qprintf(scriptfile, "	echo software to version %s on your system.\n", dist->version);
2194   fputs("	echo \"\"\n", scriptfile);
2195   fputs("	while true ; do\n", scriptfile);
2196   fputs("		echo $ac_n \"Do you wish to continue? $ac_c\"\n", scriptfile);
2197   fputs("		read yesno\n", scriptfile);
2198   fputs("		case \"$yesno\" in\n", scriptfile);
2199   fputs("			y | yes | Y | Yes | YES)\n", scriptfile);
2200   fputs("			break\n", scriptfile);
2201   fputs("			;;\n", scriptfile);
2202   fputs("			n | no | N | No | NO)\n", scriptfile);
2203   fputs("			exit 1\n", scriptfile);
2204   fputs("			;;\n", scriptfile);
2205   fputs("			*)\n", scriptfile);
2206   fputs("			echo Please enter yes or no.\n", scriptfile);
2207   fputs("			;;\n", scriptfile);
2208   fputs("		esac\n", scriptfile);
2209   fputs("	done\n", scriptfile);
2210 
2211   if (dist->license[0])
2212   {
2213     fprintf(scriptfile, "	more %s.license\n", prodfull);
2214     fputs("	echo \"\"\n", scriptfile);
2215     fputs("	while true ; do\n", scriptfile);
2216     fputs("		echo $ac_n \"Do you agree with the terms of this license? $ac_c\"\n", scriptfile);
2217     fputs("		read yesno\n", scriptfile);
2218     fputs("		case \"$yesno\" in\n", scriptfile);
2219     fputs("			y | yes | Y | Yes | YES)\n", scriptfile);
2220     fputs("			break\n", scriptfile);
2221     fputs("			;;\n", scriptfile);
2222     fputs("			n | no | N | No | NO)\n", scriptfile);
2223     fputs("			exit 1\n", scriptfile);
2224     fputs("			;;\n", scriptfile);
2225     fputs("			*)\n", scriptfile);
2226     fputs("			echo Please enter yes or no.\n", scriptfile);
2227     fputs("			;;\n", scriptfile);
2228     fputs("		esac\n", scriptfile);
2229     fputs("	done\n", scriptfile);
2230   }
2231 
2232   fputs("fi\n", scriptfile);
2233 
2234   write_space_checks(prodfull, scriptfile, rootsize ? "psw" : NULL,
2235                      usrsize ? "pss" : NULL, rootsize, usrsize);
2236   write_depends(prodname, dist, scriptfile, subpackage);
2237 
2238   fprintf(scriptfile, "if test ! -x %s/%s.remove; then\n",
2239           SoftwareDir, prodfull);
2240   fputs("	echo You do not appear to have the base software installed!\n",
2241         scriptfile);
2242   fputs("	echo Please install the full distribution instead.\n", scriptfile);
2243   fputs("	exit 1\n", scriptfile);
2244   fputs("fi\n", scriptfile);
2245 
2246   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2247     if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2248       qprintf(scriptfile, "%s/init.d/%s stop\n", SoftwareDir, file->dst);
2249 
2250   write_commands(dist, scriptfile, COMMAND_PRE_PATCH, subpackage);
2251 
2252   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2253     if (file->type == 'D' && file->subpackage == subpackage)
2254       break;
2255 
2256   if (i)
2257   {
2258     fputs("echo Creating new installation directories...\n", scriptfile);
2259 
2260     for (; i > 0; i --, file ++)
2261       if (file->type == 'D' && file->subpackage == subpackage)
2262       {
2263 	qprintf(scriptfile, "if test ! -d %s -a ! -f %s -a ! -h %s; then\n",
2264         	file->dst, file->dst, file->dst);
2265 	qprintf(scriptfile, "	mkdir -p %s\n", file->dst);
2266 	fputs("else\n", scriptfile);
2267 	qprintf(scriptfile, "	if test -f %s; then\n", file->dst);
2268 	qprintf(scriptfile, "		echo Error: %s already exists as a regular file!\n",
2269 	        file->dst);
2270 	fputs("		exit 1\n", scriptfile);
2271 	fputs("	fi\n", scriptfile);
2272 	fputs("fi\n", scriptfile);
2273 	qprintf(scriptfile, "chown %s %s\n", file->user, file->dst);
2274 	qprintf(scriptfile, "chgrp %s %s\n", file->group, file->dst);
2275 	qprintf(scriptfile, "chmod %o %s\n", file->mode, file->dst);
2276       }
2277   }
2278 
2279   fputs("echo Patching software...\n", scriptfile);
2280 
2281   if (rootsize)
2282   {
2283     if (CompressFiles)
2284       fprintf(scriptfile, "gzip -dc %s.psw | $ac_tar -\n", prodfull);
2285     else
2286       fprintf(scriptfile, "$ac_tar %s.psw\n", prodfull);
2287   }
2288 
2289   if (usrsize)
2290   {
2291     fputs("if echo Write Test >/usr/.writetest 2>/dev/null; then\n", scriptfile);
2292     if (CompressFiles)
2293       fprintf(scriptfile, "	gzip -dc %s.pss | $ac_tar -\n", prodfull);
2294     else
2295       fprintf(scriptfile, "	$ac_tar %s.pss\n", prodfull);
2296     fputs("fi\n", scriptfile);
2297   }
2298 
2299   fprintf(scriptfile, "rm -f %s/%s.remove\n", SoftwareDir, prodfull);
2300   fprintf(scriptfile, "cp %s.remove %s\n", prodfull, SoftwareDir);
2301   fprintf(scriptfile, "chmod 544 %s/%s.remove\n", SoftwareDir, prodfull);
2302 
2303   fputs("echo Updating file permissions...\n", scriptfile);
2304 
2305   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2306     if (strncmp(file->dst, "/usr", 4) != 0 &&
2307         strcmp(file->user, "root") != 0 && file->subpackage == subpackage)
2308       switch (file->type)
2309       {
2310 	case 'C' :
2311 	case 'F' :
2312 	    qprintf(scriptfile, "chown %s %s\n", file->user, file->dst);
2313 	    qprintf(scriptfile, "chgrp %s %s\n", file->group, file->dst);
2314 	    break;
2315       }
2316 
2317   fputs("if test -f /usr/.writetest; then\n", scriptfile);
2318   fputs("	rm -f /usr/.writetest\n", scriptfile);
2319   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2320     if (strncmp(file->dst, "/usr", 4) == 0 &&
2321         strcmp(file->user, "root") != 0 && file->subpackage == subpackage)
2322       switch (file->type)
2323       {
2324 	case 'C' :
2325 	case 'F' :
2326 	    qprintf(scriptfile, "	chown %s %s\n", file->user, file->dst);
2327 	    qprintf(scriptfile, "	chgrp %s %s\n", file->group, file->dst);
2328 	    break;
2329       }
2330   fputs("fi\n", scriptfile);
2331 
2332   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2333     if (file->type == 'C' && file->subpackage == subpackage)
2334       break;
2335 
2336   if (i)
2337   {
2338     fputs("echo Checking configuration files...\n", scriptfile);
2339 
2340     fputs("for file in", scriptfile);
2341     for (; i > 0; i --, file ++)
2342       if (file->type == 'C' && file->subpackage == subpackage)
2343         qprintf(scriptfile, " %s", file->dst);
2344 
2345     fputs("; do\n", scriptfile);
2346     fputs("	if test ! -f \"$file\"; then\n", scriptfile);
2347     fputs("		cp \"$file.N\" \"$file\"\n", scriptfile);
2348     fputs("	fi\n", scriptfile);
2349     fputs("done\n", scriptfile);
2350   }
2351 
2352   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2353     if (file->type == 'R' && file->subpackage == subpackage)
2354       break;
2355 
2356   if (i)
2357   {
2358     fputs("echo Removing files that are no longer used...\n", scriptfile);
2359 
2360     fputs("for file in", scriptfile);
2361     for (; i > 0; i --, file ++)
2362       if (file->type == 'R' && file->subpackage == subpackage)
2363         qprintf(scriptfile, " %s", file->dst);
2364 
2365     fputs("; do\n", scriptfile);
2366     fputs("	rm -f \"$file\"\n", scriptfile);
2367     fputs("	if test -d \"$file.O\" -o -f \"$file.O\" -o -h \"$file.O\"; then\n", scriptfile);
2368     fputs("		mv -f \"$file.O\" \"$file\"\n", scriptfile);
2369     fputs("	fi\n", scriptfile);
2370     fputs("done\n", scriptfile);
2371   }
2372 
2373   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2374     if (file->type == 'I' && file->subpackage == subpackage)
2375       break;
2376 
2377   if (i)
2378   {
2379     fputs("echo Setting up init scripts...\n", scriptfile);
2380 
2381    /*
2382     * Find where the frigging init scripts go...
2383     */
2384 
2385     fputs("rcdir=\"\"\n", scriptfile);
2386     fputs("for dir in /sbin/rc.d /sbin /etc/rc.d /etc ; do\n", scriptfile);
2387     fputs("	if test -d $dir/rc2.d -o -h $dir/rc2.d -o "
2388           "-d $dir/rc3.d -o -h $dir/rc3.d; then\n", scriptfile);
2389     fputs("		rcdir=\"$dir\"\n", scriptfile);
2390     fputs("	fi\n", scriptfile);
2391     fputs("done\n", scriptfile);
2392     fputs("if test \"$rcdir\" = \"\" ; then\n", scriptfile);
2393     fputs("	if test -d /usr/local/etc/rc.d; then\n", scriptfile);
2394     fputs("		for file in", scriptfile);
2395     for (; i > 0; i --, file ++)
2396       if (tolower(file->type) == 'I' && file->subpackage == subpackage)
2397         qprintf(scriptfile, " %s", file->dst);
2398     fputs("; do\n", scriptfile);
2399     fputs("			rm -f /usr/local/etc/rc.d/$file.sh\n", scriptfile);
2400     qprintf(scriptfile, "			ln -s %s/init.d/$file "
2401                         "/usr/local/etc/rc.d/$file.sh\n",
2402             SoftwareDir);
2403     fputs("		done\n", scriptfile);
2404     fputs("	else\n", scriptfile);
2405     fputs("		echo Unable to determine location of startup scripts!\n", scriptfile);
2406     fputs("	fi\n", scriptfile);
2407     fputs("else\n", scriptfile);
2408     for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2409       if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2410       {
2411 	fputs("	if test -d $rcdir/init.d; then\n", scriptfile);
2412 	qprintf(scriptfile, "		/bin/rm -f $rcdir/init.d/%s\n", file->dst);
2413 	qprintf(scriptfile, "		/bin/ln -s %s/init.d/%s "
2414                     "$rcdir/init.d/%s\n", SoftwareDir, file->dst, file->dst);
2415 	fputs("	else\n", scriptfile);
2416 	fputs("		if test -d /etc/init.d; then\n", scriptfile);
2417 	qprintf(scriptfile, "			/bin/rm -f /etc/init.d/%s\n", file->dst);
2418 	qprintf(scriptfile, "			/bin/ln -s %s/init.d/%s "
2419                     "/etc/init.d/%s\n", SoftwareDir, file->dst, file->dst);
2420 	fputs("		fi\n", scriptfile);
2421 	fputs("	fi\n", scriptfile);
2422 
2423 	for (runlevels = get_runlevels(dist->files + i, "0235");
2424              isdigit(*runlevels & 255);
2425 	     runlevels ++)
2426 	{
2427 	  if (*runlevels == '0')
2428             number = get_stop(file, 0);
2429 	  else
2430 	    number = get_start(file, 99);
2431 
2432           fprintf(scriptfile, "	if test -d $rcdir/rc%c.d; then\n", *runlevels);
2433 	  qprintf(scriptfile, "		/bin/rm -f $rcdir/rc%c.d/%c%02d%s\n",
2434 	          *runlevels, *runlevels == '0' ? 'K' : 'S', number, file->dst);
2435 	  qprintf(scriptfile, "		/bin/ln -s %s/init.d/%s "
2436                               "$rcdir/rc%c.d/%c%02d%s\n",
2437 		  SoftwareDir, file->dst, *runlevels,
2438 		  *runlevels == '0' ? 'K' : 'S', number, file->dst);
2439 	  fputs("	fi\n", scriptfile);
2440         }
2441 
2442 #ifdef __sgi
2443         fputs("	if test -x /etc/chkconfig; then\n", scriptfile);
2444         qprintf(scriptfile, "		/etc/chkconfig -f %s on\n", file->dst);
2445         fputs("	fi\n", scriptfile);
2446 #endif /* __sgi */
2447       }
2448 
2449     fputs("fi\n", scriptfile);
2450   }
2451 
2452   write_commands(dist, scriptfile, COMMAND_POST_PATCH, subpackage);
2453 
2454   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2455     if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2456       qprintf(scriptfile, "%s/init.d/%s start\n", SoftwareDir, file->dst);
2457 
2458   fputs("echo Patching is complete.\n", scriptfile);
2459 
2460   fclose(scriptfile);
2461 
2462   return (0);
2463 }
2464 
2465 
2466 /*
2467  * 'write_remove()' - Write the removal script.
2468  */
2469 
2470 static int				/* O - -1 on error, 0 on success */
write_remove(dist_t * dist,const char * prodname,int rootsize,int usrsize,const char * directory,const char * subpackage)2471 write_remove(dist_t     *dist,		/* I - Software distribution */
2472              const char *prodname,	/* I - Product name */
2473              int        rootsize,	/* I - Size of root files in kbytes */
2474 	     int        usrsize,	/* I - Size of /usr files in kbytes */
2475 	     const char *directory,	/* I - Directory */
2476 	     const char *subpackage)	/* I - Subpackage */
2477 {
2478   int		i;			/* Looping var */
2479   int		col;			/* Current column */
2480   FILE		*scriptfile;		/* Remove script */
2481   char		filename[1024];		/* Name of temporary file */
2482   char		prodfull[255];		/* Full product name */
2483   file_t	*file;			/* Software file */
2484   const char	*runlevels;		/* Run levels */
2485   int		number;			/* Start/stop number */
2486 
2487 
2488   if (Verbosity)
2489     puts("Writing removal script...");
2490 
2491   if (subpackage)
2492     snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
2493   else
2494     strlcpy(prodfull, prodname, sizeof(prodfull));
2495 
2496   snprintf(filename, sizeof(filename), "%s/%s.remove", directory, prodfull);
2497 
2498   if ((scriptfile = write_common(dist, "Removal", rootsize, usrsize,
2499                                  filename, subpackage)) == NULL)
2500   {
2501     fprintf(stderr, "epm: Unable to create removal script \"%s\" -\n"
2502                     "     %s\n", filename, strerror(errno));
2503     return (-1);
2504   }
2505 
2506   fputs("if test ! \"$*\" = \"now\"; then\n", scriptfile);
2507   fputs("	echo \"\"\n", scriptfile);
2508   qprintf(scriptfile, "	echo This removal script will remove the %s\n",
2509           dist->product);
2510   qprintf(scriptfile, "	echo software version %s from your system.\n",
2511           dist->version);
2512   fputs("	echo \"\"\n", scriptfile);
2513   fputs("	while true ; do\n", scriptfile);
2514   fputs("		echo $ac_n \"Do you wish to continue? $ac_c\"\n", scriptfile);
2515   fputs("		read yesno\n", scriptfile);
2516   fputs("		case \"$yesno\" in\n", scriptfile);
2517   fputs("			y | yes | Y | Yes | YES)\n", scriptfile);
2518   fputs("			break\n", scriptfile);
2519   fputs("			;;\n", scriptfile);
2520   fputs("			n | no | N | No | NO)\n", scriptfile);
2521   fputs("			exit 1\n", scriptfile);
2522   fputs("			;;\n", scriptfile);
2523   fputs("			*)\n", scriptfile);
2524   fputs("			echo Please enter yes or no.\n", scriptfile);
2525   fputs("			;;\n", scriptfile);
2526   fputs("		esac\n", scriptfile);
2527   fputs("	done\n", scriptfile);
2528   fputs("fi\n", scriptfile);
2529 
2530  /*
2531   * Find any removal commands in the list file...
2532   */
2533 
2534   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2535     if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2536       qprintf(scriptfile, "%s/init.d/%s stop\n", SoftwareDir, file->dst);
2537 
2538   write_commands(dist, scriptfile, COMMAND_PRE_REMOVE, subpackage);
2539 
2540   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2541     if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2542       break;
2543 
2544   if (i)
2545   {
2546     fputs("echo Cleaning up init scripts...\n", scriptfile);
2547 
2548    /*
2549     * Find where the frigging init scripts go...
2550     */
2551 
2552     fputs("rcdir=\"\"\n", scriptfile);
2553     fputs("for dir in /sbin/rc.d /sbin /etc/rc.d /etc ; do\n", scriptfile);
2554     fputs("	if test -d $dir/rc2.d -o -h $dir/rc2.d -o "
2555           "-d $dir/rc3.d -o -h $dir/rc3.d; then\n", scriptfile);
2556     fputs("		rcdir=\"$dir\"\n", scriptfile);
2557     fputs("	fi\n", scriptfile);
2558     fputs("done\n", scriptfile);
2559     fputs("if test \"$rcdir\" = \"\" ; then\n", scriptfile);
2560     fputs("	if test -d /usr/local/etc/rc.d; then\n", scriptfile);
2561     fputs("		for file in", scriptfile);
2562     for (; i > 0; i --, file ++)
2563       if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2564         qprintf(scriptfile, " %s", file->dst);
2565     fputs("; do\n", scriptfile);
2566     fputs("			rm -f /usr/local/etc/rc.d/$file.sh\n", scriptfile);
2567     fputs("		done\n", scriptfile);
2568     fputs("	else\n", scriptfile);
2569     fputs("		echo Unable to determine location of startup scripts!\n", scriptfile);
2570     fputs("	fi\n", scriptfile);
2571     fputs("else\n", scriptfile);
2572     for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2573       if (tolower(file->type) == 'i' && file->subpackage == subpackage)
2574       {
2575         qprintf(scriptfile, "	%s/init.d/%s stop\n", SoftwareDir, file->dst);
2576 
2577 	fputs("	if test -d $rcdir/init.d; then\n", scriptfile);
2578 	qprintf(scriptfile, "		/bin/rm -f $rcdir/init.d/%s\n", file->dst);
2579 	fputs("	else\n", scriptfile);
2580 	fputs("		if test -d /etc/init.d; then\n", scriptfile);
2581 	qprintf(scriptfile, "			/bin/rm -f /etc/init.d/%s\n", file->dst);
2582 	fputs("		fi\n", scriptfile);
2583 	fputs("	fi\n", scriptfile);
2584 
2585 	for (runlevels = get_runlevels(dist->files + i, "0235");
2586              isdigit(*runlevels & 255);
2587 	     runlevels ++)
2588 	{
2589 	  if (*runlevels == '0')
2590             number = get_stop(file, 0);
2591 	  else
2592 	    number = get_start(file, 99);
2593 
2594           fprintf(scriptfile, "	if test -d $rcdir/rc%c.d; then\n", *runlevels);
2595 	  qprintf(scriptfile, "		/bin/rm -f $rcdir/rc%c.d/%c%02d%s\n",
2596 	          *runlevels, *runlevels == '0' ? 'K' : 'S', number, file->dst);
2597 	  fputs("	fi\n", scriptfile);
2598         }
2599 
2600 #ifdef __sgi
2601         fputs("	if test -x /etc/chkconfig; then\n", scriptfile);
2602         qprintf(scriptfile, "		rm -f /etc/config/%s\n", file->dst);
2603         fputs("	fi\n", scriptfile);
2604 #endif /* __sgi */
2605       }
2606 
2607     fputs("fi\n", scriptfile);
2608   }
2609 
2610   fputs("echo Removing/restoring installed files...\n", scriptfile);
2611 
2612   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2613     if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
2614         strncmp(file->dst, "/usr", 4) != 0 && file->subpackage == subpackage)
2615       break;
2616 
2617   if (i)
2618   {
2619     col = fputs("for file in", scriptfile);
2620     for (; i > 0; i --, file ++)
2621       if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
2622           strncmp(file->dst, "/usr", 4) != 0 && file->subpackage == subpackage)
2623       {
2624         if (col > 80)
2625 	  col = qprintf(scriptfile, " \\\n%s", file->dst) - 2;
2626 	else
2627           col += qprintf(scriptfile, " %s", file->dst);
2628       }
2629 
2630     fputs("; do\n", scriptfile);
2631     fputs("	rm -f \"$file\"\n", scriptfile);
2632     fputs("	if test -d \"$file.O\" -o -f \"$file.O\" -o -h \"$file.O\"; then\n", scriptfile);
2633     fputs("		mv -f \"$file.O\" \"$file\"\n", scriptfile);
2634     fputs("	fi\n", scriptfile);
2635     fputs("done\n", scriptfile);
2636   }
2637 
2638   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2639     if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
2640         strncmp(file->dst, "/usr", 4) == 0 && file->subpackage == subpackage)
2641       break;
2642 
2643   if (i)
2644   {
2645     fputs("if test -w /usr ; then\n", scriptfile);
2646     col = fputs("	for file in", scriptfile);
2647     for (; i > 0; i --, file ++)
2648       if ((tolower(file->type) == 'f' || tolower(file->type) == 'l') &&
2649           strncmp(file->dst, "/usr", 4) == 0 && file->subpackage == subpackage)
2650       {
2651         if (col > 80)
2652 	  col = qprintf(scriptfile, " \\\n%s", file->dst) - 2;
2653 	else
2654           col += qprintf(scriptfile, " %s", file->dst);
2655       }
2656 
2657     fputs("; do\n", scriptfile);
2658     fputs("		rm -f \"$file\"\n", scriptfile);
2659     fputs("		if test -d \"$file.O\" -o -f \"$file.O\" -o -h \"$file.O\"; then\n", scriptfile);
2660     fputs("			mv -f \"$file.O\" \"$file\"\n", scriptfile);
2661     fputs("		fi\n", scriptfile);
2662     fputs("	done\n", scriptfile);
2663     fputs("fi\n", scriptfile);
2664   }
2665 
2666   fputs("echo Checking configuration files...\n", scriptfile);
2667 
2668   for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
2669     if (tolower(file->type) == 'c' && file->subpackage == subpackage)
2670       break;
2671 
2672   if (i)
2673   {
2674     col = fputs("for file in", scriptfile);
2675     for (; i > 0; i --, file ++)
2676       if (tolower(file->type) == 'c' && file->subpackage == subpackage)
2677       {
2678         if (col > 80)
2679 	  col = qprintf(scriptfile, " \\\n%s", file->dst) - 2;
2680 	else
2681           col += qprintf(scriptfile, " %s", file->dst);
2682       }
2683 
2684     fputs("; do\n", scriptfile);
2685     fputs("	if cmp -s \"$file\" \"$file.N\"; then\n", scriptfile);
2686     fputs("		# Config file not changed\n", scriptfile);
2687     fputs("		rm -f \"$file\"\n", scriptfile);
2688     fputs("	fi\n", scriptfile);
2689     fputs("	rm -f \"$file.N\"\n", scriptfile);
2690     fputs("done\n", scriptfile);
2691   }
2692 
2693   for (i = dist->num_files, file = dist->files + i - 1; i > 0; i --, file --)
2694     if (tolower(file->type) == 'd' && file->subpackage == subpackage)
2695       break;
2696 
2697   if (i)
2698   {
2699     fputs("echo Removing empty installation directories...\n", scriptfile);
2700 
2701     for (; i > 0; i --, file --)
2702       if (tolower(file->type) == 'd' && file->subpackage == subpackage)
2703       {
2704 	qprintf(scriptfile, "if test -d %s; then\n", file->dst);
2705 	qprintf(scriptfile, "	rmdir %s >/dev/null 2>&1\n", file->dst);
2706 	fputs("fi\n", scriptfile);
2707       }
2708   }
2709 
2710   write_commands(dist, scriptfile, COMMAND_POST_REMOVE, subpackage);
2711 
2712   fprintf(scriptfile, "rm -f %s/%s.remove\n", SoftwareDir, prodfull);
2713 
2714   fputs("echo Removal is complete.\n", scriptfile);
2715 
2716   fclose(scriptfile);
2717 
2718   return (0);
2719 }
2720 
2721 
2722 /*
2723  * 'write_space_checks()' - Write disk space checks for the installer.
2724  */
2725 
2726 static int				/* O - 0 on success, -1 on error */
write_space_checks(const char * prodname,FILE * fp,const char * sw,const char * ss,int rootsize,int usrsize)2727 write_space_checks(const char *prodname,/* I - Distribution name */
2728                    FILE       *fp,	/* I - File to write to */
2729                    const char *sw,	/* I - / archive */
2730 		   const char *ss,	/* I - /usr archive */
2731 		   int        rootsize,	/* I - / install size in kbytes */
2732 		   int        usrsize)	/* I - /usr install size in kbytes */
2733 {
2734   fputs("case `uname` in\n", fp);
2735   fputs("	AIX)\n", fp);
2736   fputs("	dfroot=`df -k / | tr '\\n' ' '`\n", fp);
2737   fputs("	dfusr=`df -k /usr | tr '\\n' ' '`\n", fp);
2738   fputs("	fsroot=`echo $dfroot | awk '{print $15}'`\n", fp);
2739   fputs("	sproot=`echo $dfroot | awk '{print $11}'`\n", fp);
2740   fputs("	fsusr=`echo $dfusr | awk '{print $15}'`\n", fp);
2741   fputs("	spusr=`echo $dfusr | awk '{print $11}'`\n", fp);
2742   fputs("	;;\n\n", fp);
2743   fputs("	HP-UX)\n", fp);
2744   fputs("	dfroot=`df -k / | tr '\\n' ' '`\n", fp);
2745   fputs("	dfusr=`df -k /usr | tr '\\n' ' '`\n", fp);
2746   fputs("	fsroot=`echo $dfroot | awk '{print $1}'`\n", fp);
2747   fputs("	sproot=`echo $dfroot | awk '{print $9}'`\n", fp);
2748   fputs("	fsusr=`echo $dfusr | awk '{print $1}'`\n", fp);
2749   fputs("	spusr=`echo $dfusr | awk '{print $9}'`\n", fp);
2750   fputs("	;;\n\n", fp);
2751   fputs("	IRIX*)\n", fp);
2752   fputs("	dfroot=`df -k / | tr '\\n' ' '`\n", fp);
2753   fputs("	dfusr=`df -k /usr | tr '\\n' ' '`\n", fp);
2754   fputs("	fsroot=`echo $dfroot | awk '{print $15}'`\n", fp);
2755   fputs("	sproot=`echo $dfroot | awk '{print $13}'`\n", fp);
2756   fputs("	fsusr=`echo $dfusr | awk '{print $15}'`\n", fp);
2757   fputs("	spusr=`echo $dfusr | awk '{print $13}'`\n", fp);
2758   fputs("	;;\n\n", fp);
2759   fputs("	SCO*)\n", fp);
2760   fputs("	dfroot=`df -k -B / | tr '\\n' ' '`\n", fp);
2761   fputs("	dfusr=`df -k -B /usr | tr '\\n' ' '`\n", fp);
2762   fputs("	fsroot=`echo $dfroot | awk '{print $13}'`\n", fp);
2763   fputs("	sproot=`echo $dfroot | awk '{print $11}'`\n", fp);
2764   fputs("	fsusr=`echo $dfusr | awk '{print $13}'`\n", fp);
2765   fputs("	spusr=`echo $dfusr | awk '{print $11}'`\n", fp);
2766   fputs("	;;\n\n", fp);
2767   fputs("	*)\n", fp);
2768   fputs("	dfroot=`df -k / | tr '\\n' ' '`\n", fp);
2769   fputs("	dfusr=`df -k /usr | tr '\\n' ' '`\n", fp);
2770   fputs("	fsroot=`echo $dfroot | awk '{print $13}'`\n", fp);
2771   fputs("	sproot=`echo $dfroot | awk '{print $11}'`\n", fp);
2772   fputs("	fsusr=`echo $dfusr | awk '{print $13}'`\n", fp);
2773   fputs("	spusr=`echo $dfusr | awk '{print $11}'`\n", fp);
2774   fputs("	;;\n", fp);
2775   fputs("esac\n", fp);
2776   fputs("\n", fp);
2777 
2778   fputs("if test x$sproot = x -o x$spusr = x; then\n", fp);
2779   fputs("	echo WARNING: Unable to determine available disk space\\; "
2780         "installing blindly...\n", fp);
2781   fputs("else\n", fp);
2782   fputs("	if test x$fsroot = x$fsusr; then\n", fp);
2783   fprintf(fp, "		if test %d -gt $sproot; then\n", rootsize + usrsize);
2784   fputs("			echo Not enough free disk space for "
2785         "software:\n", fp);
2786   fprintf(fp, "			echo You need %d kbytes but only have "
2787               "$sproot kbytes available.\n", rootsize + usrsize);
2788   fputs("			exit 1\n", fp);
2789   fputs("		fi\n", fp);
2790   fputs("	else\n", fp);
2791   fprintf(fp, "		if test %d -gt $sproot; then\n", rootsize);
2792   fputs("			echo Not enough free disk space for "
2793         "software:\n", fp);
2794   fprintf(fp, "			echo You need %d kbytes in / but only have "
2795               "$sproot kbytes available.\n", rootsize);
2796   fputs("			exit 1\n", fp);
2797   fputs("		fi\n", fp);
2798   fputs("\n", fp);
2799   fprintf(fp, "		if test %d -gt $spusr; then\n", usrsize);
2800   fputs("			echo Not enough free disk space for "
2801         "software:\n", fp);
2802   fprintf(fp, "			echo You need %d kbytes in /usr but only have "
2803               "$spusr kbytes available.\n", usrsize);
2804   fputs("			exit 1\n", fp);
2805   fputs("		fi\n", fp);
2806   fputs("	fi\n", fp);
2807   fputs("fi\n", fp);
2808 
2809   return (0);
2810 }
2811