/* * "$Id: osx.c,v 1.10 2003/07/23 21:41:08 mike Exp $" * * MacOS X package gateway for the ESP Package Manager (EPM). * * Copyright 2002-2003 by Easy Software Products. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Contents: * * make_osx() - Make a MacOS X software distribution package. */ /* * Include necessary headers... */ #include "epm.h" /* * 'make_osx()' - Make a Red Hat software distribution package. */ int /* O - 0 = success, 1 = fail */ make_osx(const char *prodname, /* I - Product short name */ const char *directory, /* I - Directory for distribution files */ const char *platname, /* I - Platform name */ dist_t *dist, /* I - Distribution information */ struct utsname *platform) /* I - Platform information */ { int i; /* Looping var */ FILE *fp; /* Spec file */ char name[1024]; /* Full product name */ char filename[1024]; /* Destination filename */ file_t *file; /* Current distribution file */ command_t *c; /* Current command */ struct passwd *pwd; /* Pointer to user record */ struct group *grp; /* Pointer to group record */ char current[1024]; /* Current directory */ const char *option; /* Init script option */ if (Verbosity) puts("Creating MacOS X distribution..."); getcwd(current, sizeof(current)); if (dist->relnumber) { if (platname[0]) snprintf(name, sizeof(name), "%s-%s-%d-%s", prodname, dist->version, dist->relnumber, platname); else snprintf(name, sizeof(name), "%s-%s-%d", prodname, dist->version, dist->relnumber); } else if (platname[0]) snprintf(name, sizeof(name), "%s-%s-%s", prodname, dist->version, platname); else snprintf(name, sizeof(name), "%s-%s", prodname, dist->version); /* * Copy the resources for the license, readme, and welcome (description) * stuff... */ if (Verbosity) puts("Copying temporary resource files..."); snprintf(filename, sizeof(filename), "%s/Resources", directory); make_directory(filename, 0777, 0, 0); snprintf(filename, sizeof(filename), "%s/Resources/License.txt", directory); copy_file(filename, dist->license, 0644, 0, 0); snprintf(filename, sizeof(filename), "%s/Resources/ReadMe.txt", directory); copy_file(filename, dist->readme, 0644, 0, 0); snprintf(filename, sizeof(filename), "%s/Resources/Welcome.txt", directory); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create welcome file \"%s\" - %s\n", filename, strerror(errno)); return (1); } fprintf(fp, "%s version %s\n", dist->product, dist->version); fprintf(fp, "Copyright %s\n", dist->copyright); for (i = 0; i < dist->num_descriptions; i ++) fprintf(fp, "%s\n", dist->descriptions[i]); fclose(fp); snprintf(filename, sizeof(filename), "%s/%s-desc.plist", directory, prodname); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create description file \"%s\" - %s\n", filename, strerror(errno)); return (1); } fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fputs(" IFPkgDescriptionDeleteWarning\n", fp); fputs(" \n", fp); fputs(" IFPkgDescriptionDescription\n", fp); fputs(" ", fp); for (i = 0; i < dist->num_descriptions; i ++) fprintf(fp, "%s\n", dist->descriptions[i]); fputs("\n", fp); fputs(" IFPkgDescriptionTitle\n", fp); fprintf(fp, " %s\n", dist->product); fputs(" IFPkgDescriptionVersion\n", fp); fprintf(fp, " %s\n", dist->version); fputs("\n", fp); fputs("\n", fp); fclose(fp); /* * Do the info file for the packager... */ snprintf(filename, sizeof(filename), "%s/%s-info.plist", directory, prodname); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create package information file \"%s\" - %s\n", filename, strerror(errno)); return (1); } fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fputs(" IFPkgFormatVersion\n", fp); fputs(" 0.1\n", fp); fputs(" IFPkgFlagAuthorizationAction\n", fp); fputs(" RootAuthorization\n", fp); fputs(" CFBundleName\n", fp); fprintf(fp, " %s\n", dist->product); fputs(" CFBundleGetInfoString\n", fp); fprintf(fp, " %s %s\n", dist->product, dist->version); fputs(" CFBundleShortVersionString\n", fp); fprintf(fp, " %s\n", dist->version); fputs("\n", fp); fputs("\n", fp); fclose(fp); /* * Do pre/post install commands... */ for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++) if (c->type == COMMAND_PRE_INSTALL) break; if (i) { snprintf(filename, sizeof(filename), "%s/Resources/preflight", directory); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create preinstall script \"%s\" - %s\n", filename, strerror(errno)); return (1); } fputs("#!/bin/sh\n", fp); for (; i > 0; i --, c ++) if (c->type == COMMAND_PRE_INSTALL) fprintf(fp, "%s\n", c->command); fclose(fp); chmod(filename, 0755); } for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++) if (c->type == COMMAND_POST_INSTALL) break; if (!i) { for (i = dist->num_files, file = dist->files; i > 0; i --, file ++) if (tolower(file->type) == 'i') break; } if (i) { snprintf(filename, sizeof(filename), "%s/Resources/postflight", directory); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create postinstall script \"%s\" - %s\n", filename, strerror(errno)); return (1); } fputs("#!/bin/sh\n", fp); for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++) if (c->type == COMMAND_POST_INSTALL) fprintf(fp, "%s\n", c->command); for (i = dist->num_files, file = dist->files; i > 0; i --, file ++) if (tolower(file->type) == 'i') qprintf(fp, "/Library/StartupItems/%s/%s start\n", file->dst, file->dst); fclose(fp); chmod(filename, 0755); } /* * Copy the files over... */ if (Verbosity) puts("Copying temporary distribution files..."); for (i = dist->num_files, file = dist->files; i > 0; i --, file ++) { /* * Find the username and groupname IDs... */ pwd = getpwnam(file->user); grp = getgrnam(file->group); endpwent(); endgrent(); /* * Copy the file or make the directory or make the symlink as needed... */ switch (tolower(file->type)) { case 'c' : case 'f' : if (strncmp(file->dst, "/etc/", 5) == 0) snprintf(filename, sizeof(filename), "%s/Package/private%s", directory, file->dst); else snprintf(filename, sizeof(filename), "%s/Package%s", directory, file->dst); if (Verbosity > 1) printf("%s -> %s...\n", file->src, filename); if (copy_file(filename, file->src, file->mode, pwd ? pwd->pw_uid : 0, grp ? grp->gr_gid : 0)) return (1); break; case 'i' : snprintf(filename, sizeof(filename), "%s/Package/Library/StartupItems/%s/%s", directory, file->dst, file->dst); if (Verbosity > 1) printf("%s -> %s...\n", file->src, filename); if (copy_file(filename, file->src, file->mode, pwd ? pwd->pw_uid : 0, grp ? grp->gr_gid : 0)) return (1); snprintf(filename, sizeof(filename), "%s/Package/Library/StartupItems/%s/StartupParameters.plist", directory, file->dst); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create init data file \"%s\" - %s\n", filename, strerror(errno)); return (1); } fputs("{\n", fp); fprintf(fp, " Description = \"%s\";\n", dist->product); qprintf(fp, " Provides = (%s);\n", get_option(file, "provides", file->dst)); if ((option = get_option(file, "requires", NULL)) != NULL) qprintf(fp, " Requires = (%s);\n", option); if ((option = get_option(file, "uses", NULL)) != NULL) qprintf(fp, " Uses = (%s);\n", option); if ((option = get_option(file, "order", NULL)) != NULL) qprintf(fp, " OrderPreference = \"%s\";\n", option); fputs("}\n", fp); fclose(fp); snprintf(filename, sizeof(filename), "%s/Package/Library/StartupItems/%s/Resources/English.lproj", directory, file->dst); make_directory(filename, 0777, 0, 0); snprintf(filename, sizeof(filename), "%s/Package/Library/StartupItems/%s/Resources/English.lproj/Localizable.strings", directory, file->dst); if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "epm: Unable to create init strings file \"%s\" - %s\n", filename, strerror(errno)); return (1); } fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fprintf(fp, " Starting %s\n", dist->product); fprintf(fp, " Starting %s\n", dist->product); fputs("\n", fp); fputs("\n", fp); fclose(fp); break; case 'd' : if (strncmp(file->dst, "/etc/", 5) == 0 || strcmp(file->dst, "/etc") == 0) snprintf(filename, sizeof(filename), "%s/Package/private%s", directory, file->dst); else snprintf(filename, sizeof(filename), "%s/Package%s", directory, file->dst); if (Verbosity > 1) printf("Directory %s...\n", filename); make_directory(filename, file->mode, pwd ? pwd->pw_uid : 0, grp ? grp->gr_gid : 0); break; case 'l' : if (strncmp(file->dst, "/etc/", 5) == 0) snprintf(filename, sizeof(filename), "%s/Package/private%s", directory, file->dst); else snprintf(filename, sizeof(filename), "%s/Package%s", directory, file->dst); if (Verbosity > 1) printf("%s -> %s...\n", file->src, filename); make_link(filename, file->src); break; } } /* * Build the distribution... */ if (Verbosity) puts("Building OSX package..."); if (directory[0] == '/') { strncpy(filename, directory, sizeof(filename) - 1); filename[sizeof(filename) - 1] = '\0'; } else snprintf(filename, sizeof(filename), "%s/%s", current, directory); run_command(NULL, "/Developer/Applications/PackageMaker.app/" "Contents/MacOS/PackageMaker -build " "-p %s/%s.pkg -f %s/Package -r %s/Resources -d %s/%s-desc.plist -i %s/%s-info.plist", filename, prodname, filename, filename, filename, prodname, filename, prodname); snprintf(filename, sizeof(filename), "%s/%s.pkg", directory, prodname); if (access(filename, 0)) return (1); /* * Remove temporary files... */ if (!KeepFiles) { if (Verbosity) puts("Removing temporary distribution files..."); run_command(NULL, "/bin/rm -rf %s/Resources", directory); run_command(NULL, "/bin/rm -rf %s/Package", directory); snprintf(filename, sizeof(filename), "%s/%s-desc.plist", directory, prodname); unlink(filename); snprintf(filename, sizeof(filename), "%s/%s-info.plist", directory, prodname); unlink(filename); } return (0); } /* * End of "$Id: osx.c,v 1.10 2003/07/23 21:41:08 mike Exp $". */