1 /*
2 * Red Hat package gateway for the ESP Package Manager (EPM).
3 *
4 * Copyright © 1999-2020 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 int move_rpms(const char *prodname, const char *directory,
30 const char *platname, dist_t *dist,
31 struct utsname *platform,
32 const char *rpmdir, const char *subpackage,
33 const char *release);
34 static int write_spec(int format, const char *prodname, dist_t *dist,
35 FILE *fp, const char *subpackage);
36
37
38 /*
39 * 'make_rpm()' - Make a Red Hat software distribution package.
40 */
41
42 int /* O - 0 = success, 1 = fail */
make_rpm(int format,const char * prodname,const char * directory,const char * platname,dist_t * dist,struct utsname * platform,const char * setup,const char * types)43 make_rpm(int format, /* I - Subformat */
44 const char *prodname, /* I - Product short name */
45 const char *directory, /* I - Directory for distribution files */
46 const char *platname, /* I - Platform name */
47 dist_t *dist, /* I - Distribution information */
48 struct utsname *platform, /* I - Platform information */
49 const char *setup, /* I - Setup GUI image */
50 const char *types) /* I - Setup GUI install types */
51 {
52 int i; /* Looping var */
53 FILE *fp; /* Spec file */
54 tarf_t *tarfile; /* Distribution tar file */
55 char specname[1024]; /* Spec filename */
56 char name[1024], /* Product filename */
57 filename[1024]; /* Destination filename */
58 file_t *file; /* Current distribution file */
59 char absdir[1024]; /* Absolute directory */
60 char rpmdir[1024]; /* RPMDIR env var */
61 char release[256]; /* Release: number */
62 const char *build_option; /* Additional rpmbuild option */
63
64
65 if (Verbosity)
66 puts("Creating RPM distribution...");
67
68 if (directory[0] != '/')
69 {
70 char current[1024]; /* Current directory */
71
72
73 getcwd(current, sizeof(current));
74
75 snprintf(absdir, sizeof(absdir), "%s/%s", current, directory);
76 }
77 else
78 strlcpy(absdir, directory, sizeof(absdir));
79
80 /*
81 * Write the spec file for RPM...
82 */
83
84 if (Verbosity)
85 puts("Creating spec file...");
86
87 snprintf(specname, sizeof(specname), "%s/%s.spec", directory, prodname);
88
89 if ((fp = fopen(specname, "w")) == NULL)
90 {
91 fprintf(stderr, "epm: Unable to create spec file \"%s\": %s\n", specname, strerror(errno));
92 return (1);
93 }
94
95 if (dist->release[0])
96 strlcpy(release, dist->release, sizeof(release));
97 else
98 strlcpy(release, "0", sizeof(release));
99
100 fprintf(fp, "Name: %s\n", prodname);
101 fprintf(fp, "Version: %s\n", dist->version);
102 if (dist->epoch)
103 fprintf(fp, "Epoch: %d\n", dist->epoch);
104 fprintf(fp, "Release: %s\n", release);
105 fprintf(fp, "License: %s\n", dist->copyright);
106 fprintf(fp, "Packager: %s\n", dist->packager);
107 fprintf(fp, "Vendor: %s\n", dist->vendor);
108
109 /*
110 * Tell RPM to put the distributions in the output directory...
111 */
112
113 #ifdef EPM_RPMTOPDIR
114 fprintf(fp, "%%define _topdir %s\n", absdir);
115 strlcpy(rpmdir, absdir, sizeof(rpmdir));
116 #else
117 if (getenv("RPMDIR"))
118 strlcpy(rpmdir, getenv("RPMDIR"), sizeof(rpmdir));
119 else if (!access("/usr/src/redhat", 0))
120 strlcpy(rpmdir, "/usr/src/redhat", sizeof(rpmdir));
121 else if (!access("/usr/src/Mandrake", 0))
122 strlcpy(rpmdir, "/usr/src/Mandrake", sizeof(rpmdir));
123 else
124 strlcpy(rpmdir, "/usr/src/RPM", sizeof(rpmdir));
125 #endif /* EPM_RPMTOPDIR */
126
127 snprintf(filename, sizeof(filename), "%s/BUILD", directory);
128
129 make_directory(filename, 0, getuid(), getgid());
130
131 snprintf(filename, sizeof(filename), "%s/RPMS", directory);
132
133 make_directory(filename, 0, getuid(), getgid());
134
135 snprintf(filename, sizeof(filename), "%s/rpms", directory);
136 symlink("RPMS", filename);
137
138 if (!strcmp(platform->machine, "intel"))
139 snprintf(filename, sizeof(filename), "%s/RPMS/i386", directory);
140 else if (!strcmp(platform->machine, "ppc"))
141 snprintf(filename, sizeof(filename), "%s/RPMS/ppc", directory);
142 else
143 snprintf(filename, sizeof(filename), "%s/RPMS/%s", directory,
144 platform->machine);
145
146 make_directory(filename, 0, getuid(), getgid());
147
148 /*
149 * Now list all of the subpackages...
150 */
151
152 write_spec(format, prodname, dist, fp, NULL);
153 for (i = 0; i < dist->num_subpackages; i ++)
154 write_spec(format, prodname, dist, fp, dist->subpackages[i]);
155
156 /*
157 * Close the spec file...
158 */
159
160 fclose(fp);
161
162 /*
163 * Copy the files over...
164 */
165
166 if (Verbosity)
167 puts("Copying temporary distribution files...");
168
169 for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
170 {
171 /*
172 * Copy the file or make the directory or make the symlink as needed...
173 */
174
175 switch (tolower(file->type))
176 {
177 case 'c' :
178 case 'f' :
179 snprintf(filename, sizeof(filename), "%s/buildroot%s", directory, file->dst);
180
181 if (Verbosity > 1)
182 printf("%s -> %s...\n", file->src, filename);
183
184 if (copy_file(filename, file->src, 0, -1, -1))
185 return (1);
186 break;
187 case 'i' :
188 snprintf(filename, sizeof(filename), "%s/buildroot%s/init.d/%s", directory, SoftwareDir, file->dst);
189
190 if (Verbosity > 1)
191 printf("%s -> %s...\n", file->src, filename);
192
193 if (copy_file(filename, file->src, 0, -1, -1))
194 return (1);
195 break;
196 case 'd' :
197 snprintf(filename, sizeof(filename), "%s/buildroot%s", directory, file->dst);
198
199 if (Verbosity > 1)
200 printf("Directory %s...\n", filename);
201
202 make_directory(filename, 0755, -1, -1);
203 break;
204 case 'l' :
205 snprintf(filename, sizeof(filename), "%s/buildroot%s", directory, file->dst);
206
207 if (Verbosity > 1)
208 printf("%s -> %s...\n", file->src, filename);
209
210 make_link(filename, file->src);
211 break;
212 }
213 }
214
215 /*
216 * Build the distribution from the spec file...
217 */
218
219 if (Verbosity)
220 puts("Building RPM binary distribution...");
221
222 if (format == PACKAGE_RPM_SIGNED)
223 build_option = "-signed ";
224 else
225 build_option = "";
226
227 if (!strcmp(platform->machine, "intel"))
228 {
229 if (run_command(NULL, EPM_RPMBUILD " -bb --buildroot \"%s/buildroot\" "
230 EPM_RPMARCH "i386 %s%s", absdir, build_option,
231 specname))
232 return (1);
233 }
234 else if (!strcmp(platform->machine, "ppc"))
235 {
236 if (run_command(NULL, EPM_RPMBUILD " -bb --buildroot \"%s/buildroot\" "
237 EPM_RPMARCH "ppc %s%s", absdir, build_option,
238 specname))
239 return (1);
240 }
241 else if (run_command(NULL, EPM_RPMBUILD " -bb --buildroot \"%s/buildroot\" "
242 EPM_RPMARCH "%s %s%s", absdir, platform->machine,
243 build_option, specname))
244 return (1);
245
246 /*
247 * Move the RPMs to the local directory and rename the RPMs using the
248 * product name specified by the user...
249 */
250
251 move_rpms(prodname, directory, platname, dist, platform, rpmdir, NULL,
252 release);
253
254 for (i = 0; i < dist->num_subpackages; i ++)
255 move_rpms(prodname, directory, platname, dist, platform, rpmdir,
256 dist->subpackages[i], release);
257
258 /*
259 * Build a compressed tar file to hold all of the subpackages...
260 */
261
262 if (dist->num_subpackages || setup)
263 {
264 /*
265 * Figure out the full name of the distribution...
266 */
267
268 if (dist->release[0])
269 snprintf(name, sizeof(name), "%s-%s-%s", prodname, dist->version,
270 dist->release);
271 else
272 snprintf(name, sizeof(name), "%s-%s", prodname, dist->version);
273
274 if (platname[0])
275 {
276 strlcat(name, "-", sizeof(name));
277 strlcat(name, platname, sizeof(name));
278 }
279
280 /*
281 * Create a compressed tar file...
282 */
283
284 snprintf(filename, sizeof(filename), "%s/%s.rpm.tgz", directory, name);
285
286 if ((tarfile = tar_open(filename, 1)) == NULL)
287 return (1);
288
289 /*
290 * Archive the setup and uninst GUIs and their data files...
291 */
292
293 if (setup)
294 {
295 /*
296 * Include the ESP Software Installation Wizard (setup)...
297 */
298
299 const char *setup_img; /* Setup image name */
300 struct stat srcstat; /* File information */
301
302
303 if (stat(SetupProgram, &srcstat))
304 {
305 fprintf(stderr, "epm: Unable to stat GUI setup program %s: %s\n",
306 SetupProgram, strerror(errno));
307 tar_close(tarfile);
308 return (-1);
309 }
310
311 if (tar_header(tarfile, TAR_NORMAL, 0555, srcstat.st_size,
312 srcstat.st_mtime, "root", "root", "setup", NULL) < 0)
313 {
314 tar_close(tarfile);
315 return (-1);
316 }
317
318 if (tar_file(tarfile, SetupProgram) < 0)
319 {
320 tar_close(tarfile);
321 return (-1);
322 }
323
324 if (Verbosity)
325 printf(" %7.0fk setup\n", (srcstat.st_size + 1023) / 1024.0);
326
327 /*
328 * And the image file...
329 */
330
331 stat(setup, &srcstat);
332
333 if (strlen(setup) > 4 && !strcmp(setup + strlen(setup) - 4, ".gif"))
334 setup_img = "setup.gif";
335 else if (strlen(setup) > 4 && !strcmp(setup + strlen(setup) - 4, ".jpg"))
336 setup_img = "setup.jpg";
337 else if (strlen(setup) > 4 && !strcmp(setup + strlen(setup) - 4, ".png"))
338 setup_img = "setup.png";
339 else
340 setup_img = "setup.xpm";
341
342 if (tar_header(tarfile, TAR_NORMAL, 0444, srcstat.st_size,
343 srcstat.st_mtime, "root", "root", setup_img, NULL) < 0)
344 {
345 tar_close(tarfile);
346 return (-1);
347 }
348
349 if (tar_file(tarfile, setup) < 0)
350 {
351 tar_close(tarfile);
352 return (-1);
353 }
354
355 if (Verbosity)
356 printf(" %7.0fk %s\n", (srcstat.st_size + 1023) / 1024.0, setup_img);
357
358 /*
359 * And the types file...
360 */
361
362 if (types)
363 {
364 stat(types, &srcstat);
365
366 if (tar_header(tarfile, TAR_NORMAL, 0444, srcstat.st_size,
367 srcstat.st_mtime, "root", "root", "setup.types", NULL) < 0)
368 {
369 tar_close(tarfile);
370 return (-1);
371 }
372
373 if (tar_file(tarfile, types) < 0)
374 {
375 tar_close(tarfile);
376 return (-1);
377 }
378
379 if (Verbosity)
380 printf(" %7.0fk setup.types\n", (srcstat.st_size + 1023) / 1024.0);
381 }
382
383 /*
384 * Include the ESP Software Removal Wizard (uninst)...
385 */
386
387 if (stat(UninstProgram, &srcstat))
388 {
389 fprintf(stderr, "epm: Unable to stat GUI uninstall program %s: %s\n",
390 UninstProgram, strerror(errno));
391 tar_close(tarfile);
392 return (-1);
393 }
394
395 if (tar_header(tarfile, TAR_NORMAL, 0555, srcstat.st_size,
396 srcstat.st_mtime, "root", "root", "uninst", NULL) < 0)
397 {
398 tar_close(tarfile);
399 return (-1);
400 }
401
402 if (tar_file(tarfile, UninstProgram) < 0)
403 {
404 tar_close(tarfile);
405 return (-1);
406 }
407
408 if (Verbosity)
409 printf(" %7.0fk uninst\n", (srcstat.st_size + 1023) / 1024.0);
410 }
411
412 /*
413 * Archive the main package and subpackages...
414 */
415
416 if (tar_package(tarfile, "rpm", prodname, directory, platname, dist, NULL))
417 {
418 tar_close(tarfile);
419 return (1);
420 }
421
422 for (i = 0; i < dist->num_subpackages; i ++)
423 {
424 if (tar_package(tarfile, "rpm", prodname, directory, platname, dist,
425 dist->subpackages[i]))
426 {
427 tar_close(tarfile);
428 return (1);
429 }
430 }
431
432 tar_close(tarfile);
433 }
434
435 /*
436 * Remove temporary files...
437 */
438
439 if (!KeepFiles)
440 {
441 if (Verbosity)
442 puts("Removing temporary distribution files...");
443
444 snprintf(filename, sizeof(filename), "%s/BUILD", directory);
445 unlink_directory(filename);
446
447 snprintf(filename, sizeof(filename), "%s/RPMS", directory);
448 unlink_directory(filename);
449
450 snprintf(filename, sizeof(filename), "%s/rpms", directory);
451 unlink(filename);
452
453 unlink(specname);
454
455 if (dist->num_subpackages)
456 {
457 /*
458 * Remove .rpm files since they are now in a .tgz file...
459 */
460
461 unlink_package("rpm", prodname, directory, platname, dist, NULL);
462
463 for (i = 0; i < dist->num_subpackages; i ++)
464 unlink_package("rpm", prodname, directory, platname, dist,
465 dist->subpackages[i]);
466 }
467 }
468
469 return (0);
470 }
471
472
473 /*
474 * 'move_rpms()' - Move RPM packages to the build directory...
475 */
476
477 static int /* O - 0 = success, 1 = fail */
move_rpms(const char * prodname,const char * directory,const char * platname,dist_t * dist,struct utsname * platform,const char * rpmdir,const char * subpackage,const char * release)478 move_rpms(const char *prodname, /* I - Product short name */
479 const char *directory, /* I - Directory for distribution files */
480 const char *platname, /* I - Platform name */
481 dist_t *dist, /* I - Distribution information */
482 struct utsname *platform, /* I - Platform information */
483 const char *rpmdir, /* I - RPM directory */
484 const char *subpackage, /* I - Subpackage name */
485 const char *release) /* I - Release: value */
486 {
487 char rpmname[1024]; /* RPM name */
488 char prodfull[1024]; /* Full product name */
489 struct stat rpminfo; /* RPM file info */
490
491
492 /*
493 * Move the RPMs to the local directory and rename the RPMs using the
494 * product name specified by the user...
495 */
496
497 if (subpackage)
498 snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
499 else
500 strlcpy(prodfull, prodname, sizeof(prodfull));
501
502 if (dist->release[0])
503 snprintf(rpmname, sizeof(rpmname), "%s/%s-%s-%s", directory, prodfull,
504 dist->version, dist->release);
505 else
506 snprintf(rpmname, sizeof(rpmname), "%s/%s-%s", directory, prodfull,
507 dist->version);
508
509 if (platname[0])
510 {
511 strlcat(rpmname, "-", sizeof(rpmname));
512 strlcat(rpmname, platname, sizeof(rpmname));
513 }
514
515 strlcat(rpmname, ".rpm", sizeof(rpmname));
516
517 if (!strcmp(platform->machine, "intel"))
518 run_command(NULL, "/bin/mv %s/RPMS/i386/%s-%s-%s.i386.rpm %s",
519 rpmdir, prodfull, dist->version, release,
520 rpmname);
521 else if (!strcmp(platform->sysname, "aix") && !strcmp(platform->machine, "ppc"))
522 run_command(NULL, "/bin/mv %s/RPMS/ppc/%s-%s-%s.%s%s.ppc.rpm %s",
523 rpmdir, prodfull, dist->version, release, platform->sysname, platform->release,
524 rpmname);
525 else if (!strcmp(platform->machine, "ppc"))
526 run_command(NULL, "/bin/mv %s/RPMS/powerpc/%s-%s-%s.powerpc.rpm %s",
527 rpmdir, prodfull, dist->version, release,
528 rpmname);
529 else
530 run_command(NULL, "/bin/mv %s/RPMS/%s/%s-%s-%s.%s.rpm %s",
531 rpmdir, platform->machine, prodfull, dist->version,
532 release, platform->machine, rpmname);
533
534 if (Verbosity)
535 {
536 stat(rpmname, &rpminfo);
537
538 printf(" %7.0fk %s\n", rpminfo.st_size / 1024.0, rpmname);
539 }
540
541 return (0);
542 }
543
544
545 /*
546 * 'write_spec()' - Write the subpackage-specific parts of the RPM spec file.
547 */
548
549 static int /* O - 0 on success, -1 on error */
write_spec(int format,const char * prodname,dist_t * dist,FILE * fp,const char * subpackage)550 write_spec(int format, /* I - Subformat */
551 const char *prodname, /* I - Product name */
552 dist_t *dist, /* I - Distribution */
553 FILE *fp, /* I - Spec file */
554 const char *subpackage) /* I - Subpackage name */
555 {
556 int i; /* Looping var */
557 char name[1024]; /* Full product name */
558 const char *product; /* Product to depend on */
559 file_t *file; /* Current distribution file */
560 command_t *c; /* Current command */
561 depend_t *d; /* Current dependency */
562 const char *runlevels; /* Run levels */
563 int number; /* Start/stop number */
564 int have_commands; /* Have commands in current section? */
565
566
567 /*
568 * Get the name we'll use for the subpackage...
569 */
570
571 if (subpackage)
572 snprintf(name, sizeof(name), " %s", subpackage);
573 else
574 name[0] = '\0';
575
576 /*
577 * Common stuff...
578 */
579
580 if (subpackage)
581 {
582 fprintf(fp, "%%package%s\n", name);
583 fprintf(fp, "Summary: %s", dist->product);
584
585 for (i = 0; i < dist->num_descriptions; i ++)
586 if (dist->descriptions[i].subpackage == subpackage)
587 break;
588
589 if (i < dist->num_descriptions)
590 {
591 char line[1024], /* First line of description... */
592 *ptr; /* Pointer into line */
593
594
595 strlcpy(line, dist->descriptions[i].description, sizeof(line));
596 if ((ptr = strchr(line, '\n')) != NULL)
597 *ptr = '\0';
598
599 fprintf(fp, " - %s", line);
600 }
601 fputs("\n", fp);
602 }
603 else
604 fprintf(fp, "Summary: %s\n", dist->product);
605
606 fputs("Group: Applications\n", fp);
607
608 /*
609 * List all of the dependencies...
610 */
611
612 for (i = dist->num_depends, d = dist->depends; i > 0; i --, d ++)
613 {
614 if (d->subpackage != subpackage)
615 continue;
616
617 if (!strcmp(d->product, "_self"))
618 product = prodname;
619 else
620 product = d->product;
621
622 if (d->type == DEPEND_REQUIRES)
623 fprintf(fp, "Requires: %s", product);
624 else if (d->type == DEPEND_PROVIDES)
625 fprintf(fp, "Provides: %s", product);
626 else if (d->type == DEPEND_REPLACES)
627 fprintf(fp, "Obsoletes: %s", product);
628 else
629 fprintf(fp, "Conflicts: %s", product);
630
631 if (d->vernumber[0] == 0)
632 {
633 if (d->vernumber[1] < INT_MAX)
634 fprintf(fp, " <= %s\n", d->version[1]);
635 else
636 putc('\n', fp);
637 }
638 else if (d->vernumber[0] && d->vernumber[1] < INT_MAX)
639 {
640 if (d->vernumber[0] < INT_MAX && d->vernumber[1] < INT_MAX)
641 fprintf(fp, " >= %s, %s <= %s\n", d->version[0], product,
642 d->version[1]);
643 }
644 else if (d->vernumber[0] != d->vernumber[1])
645 fprintf(fp, " >= %s\n", d->version[0]);
646 else
647 fprintf(fp, " = %s\n", d->version[0]);
648 }
649
650 for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
651 if (c->type == COMMAND_LITERAL && c->subpackage == subpackage &&
652 !strcmp(c->section, "spec"))
653 break;
654
655 if (i > 0)
656 {
657 for (; i > 0; i --, c ++)
658 if (c->type == COMMAND_LITERAL && c->subpackage == subpackage &&
659 !strcmp(c->section, "spec"))
660 fprintf(fp, "%s\n", c->command);
661 }
662
663 /*
664 * Pre/post install commands...
665 */
666
667 for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
668 if (c->type == COMMAND_PRE_INSTALL && c->subpackage == subpackage)
669 break;
670
671 if (i > 0)
672 {
673 fprintf(fp, "%%pre%s\n", name);
674 for (; i > 0; i --, c ++)
675 if (c->type == COMMAND_PRE_INSTALL && c->subpackage == subpackage)
676 fprintf(fp, "%s\n", c->command);
677 }
678
679 for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
680 if (c->type == COMMAND_POST_INSTALL && c->subpackage == subpackage)
681 break;
682
683 if (i > 0)
684 {
685 have_commands = 1;
686
687 fprintf(fp, "%%post%s\n", name);
688 for (; i > 0; i --, c ++)
689 if (c->type == COMMAND_POST_INSTALL && c->subpackage == subpackage)
690 fprintf(fp, "%s\n", c->command);
691
692 }
693 else
694 have_commands = 0;
695
696 for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
697 if (tolower(file->type) == 'i' && file->subpackage == subpackage)
698 break;
699
700 if (i)
701 {
702 if (!have_commands)
703 fprintf(fp, "%%post%s\n", name);
704
705 fputs("if test \"x$1\" = x1; then\n", fp);
706 fputs(" echo Setting up init scripts...\n", fp);
707
708 /*
709 * Find where the frigging init scripts go...
710 */
711
712 fputs(" rcdir=\"\"\n", fp);
713 fputs(" for dir in /sbin/rc.d /sbin /etc/rc.d /etc ; do\n", fp);
714 fputs(" if test -d $dir/rc3.d -o -h $dir/rc3.d; then\n", fp);
715 fputs(" rcdir=\"$dir\"\n", fp);
716 fputs(" fi\n", fp);
717 fputs(" done\n", fp);
718 fputs(" if test \"$rcdir\" = \"\" ; then\n", fp);
719 fputs(" echo Unable to determine location of startup scripts!\n", fp);
720 fputs(" else\n", fp);
721 for (; i > 0; i --, file ++)
722 {
723 if (tolower(file->type) == 'i' && file->subpackage == subpackage)
724 {
725 fputs(" if test -d $rcdir/init.d; then\n", fp);
726 qprintf(fp, " /bin/rm -f $rcdir/init.d/%s\n", file->dst);
727 qprintf(fp, " /bin/ln -s %s/init.d/%s "
728 "$rcdir/init.d/%s\n", SoftwareDir, file->dst, file->dst);
729 fputs(" else\n", fp);
730 fputs(" if test -d /etc/init.d; then\n", fp);
731 qprintf(fp, " /bin/rm -f /etc/init.d/%s\n", file->dst);
732 qprintf(fp, " /bin/ln -s %s/init.d/%s "
733 "/etc/init.d/%s\n", SoftwareDir, file->dst, file->dst);
734 fputs(" fi\n", fp);
735 fputs(" fi\n", fp);
736
737 for (runlevels = get_runlevels(dist->files + i, "0123456");
738 isdigit(*runlevels & 255);
739 runlevels ++)
740 {
741 if (*runlevels == '0')
742 number = get_stop(file, 0);
743 else
744 number = get_start(file, 99);
745
746 qprintf(fp, " /bin/rm -f $rcdir/rc%c.d/%c%02d%s\n", *runlevels,
747 (*runlevels == '0' || *runlevels == '1' ||
748 *runlevels == '6') ? 'K' : 'S', number, file->dst);
749 qprintf(fp, " /bin/ln -s %s/init.d/%s "
750 "$rcdir/rc%c.d/%c%02d%s\n", SoftwareDir, file->dst,
751 *runlevels,
752 (*runlevels == '0' || *runlevels == '1' ||
753 *runlevels == '6') ? 'K' : 'S', number, file->dst);
754 }
755
756 qprintf(fp, " %s/init.d/%s start\n", SoftwareDir, file->dst);
757 }
758 }
759
760 fputs(" fi\n", fp);
761
762 fputs("fi\n", fp);
763 }
764
765 for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
766 if (tolower(file->type) == 'i' && file->subpackage == subpackage)
767 break;
768
769 if (i)
770 {
771 have_commands = 1;
772
773 fprintf(fp, "%%preun%s\n", name);
774 fputs("if test \"x$1\" = x0; then\n", fp);
775 fputs(" echo Cleaning up init scripts...\n", fp);
776
777 /*
778 * Find where the frigging init scripts go...
779 */
780
781 fputs(" rcdir=\"\"\n", fp);
782 fputs(" for dir in /sbin/rc.d /sbin /etc/rc.d /etc ; do\n", fp);
783 fputs(" if test -d $dir/rc3.d -o -h $dir/rc3.d; then\n", fp);
784 fputs(" rcdir=\"$dir\"\n", fp);
785 fputs(" fi\n", fp);
786 fputs(" done\n", fp);
787 fputs(" if test \"$rcdir\" = \"\" ; then\n", fp);
788 fputs(" echo Unable to determine location of startup scripts!\n", fp);
789 fputs(" else\n", fp);
790 for (; i > 0; i --, file ++)
791 {
792 if (tolower(file->type) == 'i' && file->subpackage == subpackage)
793 {
794 qprintf(fp, " %s/init.d/%s stop\n", SoftwareDir, file->dst);
795
796 fputs(" if test -d $rcdir/init.d; then\n", fp);
797 qprintf(fp, " /bin/rm -f $rcdir/init.d/%s\n", file->dst);
798 fputs(" else\n", fp);
799 fputs(" if test -d /etc/init.d; then\n", fp);
800 qprintf(fp, " /bin/rm -f /etc/init.d/%s\n", file->dst);
801 fputs(" fi\n", fp);
802 fputs(" fi\n", fp);
803
804 for (runlevels = get_runlevels(dist->files + i, "0123456");
805 isdigit(*runlevels & 255);
806 runlevels ++)
807 {
808 if (*runlevels == '0')
809 number = get_stop(file, 0);
810 else
811 number = get_start(file, 99);
812
813 qprintf(fp, " /bin/rm -f $rcdir/rc%c.d/%c%02d%s\n", *runlevels,
814 (*runlevels == '0' || *runlevels == '1' ||
815 *runlevels == '6') ? 'K' : 'S', number, file->dst);
816 }
817 }
818 }
819
820 fputs(" fi\n", fp);
821
822 fputs("fi\n", fp);
823 }
824 else
825 have_commands = 0;
826
827 for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
828 if (c->type == COMMAND_PRE_REMOVE && c->subpackage == subpackage)
829 break;
830
831 if (i > 0)
832 {
833 if (!have_commands)
834 fprintf(fp, "%%preun%s\n", name);
835
836 for (; i > 0; i --, c ++)
837 if (c->type == COMMAND_PRE_REMOVE && c->subpackage == subpackage)
838 fprintf(fp, "%s\n", c->command);
839 }
840
841 for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
842 if (c->type == COMMAND_POST_REMOVE && c->subpackage == subpackage)
843 break;
844
845 if (i > 0)
846 {
847 fprintf(fp, "%%postun%s\n", name);
848 for (; i > 0; i --, c ++)
849 if (c->type == COMMAND_POST_REMOVE && c->subpackage == subpackage)
850 fprintf(fp, "%s\n", c->command);
851 }
852
853 /*
854 * Description...
855 */
856
857 for (i = 0; i < dist->num_descriptions; i ++)
858 if (dist->descriptions[i].subpackage == subpackage)
859 break;
860
861 if (i < dist->num_descriptions)
862 {
863 fprintf(fp, "%%description %s\n", name);
864
865 for (; i < dist->num_descriptions; i ++)
866 if (dist->descriptions[i].subpackage == subpackage)
867 fprintf(fp, "%s\n", dist->descriptions[i].description);
868 }
869
870 /*
871 * Files...
872 */
873
874 fprintf(fp, "%%files%s\n", name);
875 for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
876 if (file->subpackage == subpackage)
877 switch (tolower(file->type))
878 {
879 case 'c' :
880 fprintf(fp, "%%attr(%04o,%s,%s) %%config(noreplace) \"%s\"\n",
881 file->mode, file->user, file->group, file->dst);
882 break;
883 case 'd' :
884 fprintf(fp, "%%attr(%04o,%s,%s) %%dir \"%s\"\n", file->mode,
885 file->user, file->group, file->dst);
886 break;
887 case 'f' :
888 case 'l' :
889 fprintf(fp, "%%attr(%04o,%s,%s) \"%s\"\n", file->mode, file->user,
890 file->group, file->dst);
891 break;
892 case 'i' :
893 fprintf(fp, "%%attr(0555,root,root) \"%s/init.d/%s\"\n", SoftwareDir, file->dst);
894 break;
895 }
896
897 return (0);
898 }
899