/*
 * "$Id: inst.c,v 1.25 2002/12/17 18:57:55 swdev Exp $"
 *
 *   IRIX package gateway for the ESP Package Manager (EPM).
 *
 *   Copyright 1999-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_inst() - Make an IRIX software distribution package.
 */

/*
 * Include necessary headers...
 */

#include "epm.h"


/*
 * 'make_inst()' - Make an IRIX software distribution package.
 */

int					/* O - 0 = success, 1 = fail */
make_inst(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/IDB/script file */
  tarf_t	*tarfile;		/* .tardist file */
  char		name[1024];		/* Full product name */
  char		specname[1024];		/* Spec filename */
  char		idbname[1024];		/* IDB filename */
  char		filename[1024],		/* Destination filename */
		srcname[1024],		/* Name of source file in distribution */
		dstname[1024];		/* Name of destination file in distribution */
  char		preinstall[1024],	/* Pre install script */
		postinstall[1024],	/* Post install script */
		preremove[1024],	/* Pre remove script */
		postremove[1024];	/* Post remove script */
  char		subsys[255];		/* Subsystem name */
  file_t	*file;			/* Current distribution file */
  command_t	*c;			/* Current command */
  depend_t	*d;			/* Current dependency */
  struct stat	fileinfo;		/* File information */
  const char	*runlevels;		/* Run levels */
  static const char *extensions[] =	/* INST file extensions */
		{
		  "",
		  ".idb",
		  ".man",
		  ".sw"
		};


  (void)platform; /* Eliminates compiler warning about unused variable */

  if (Verbosity)
    puts("Creating inst distribution...");

  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);

 /*
  * Write the spec file for gendist...
  */

  if (Verbosity)
    puts("Creating spec file...");

  snprintf(specname, sizeof(specname), "%s/spec", directory);

  if ((fp = fopen(specname, "w")) == NULL)
  {
    fprintf(stderr, "epm: Unable to create spec file \"%s\" - %s\n", specname,
            strerror(errno));
    return (1);
  }

  fprintf(fp, "product %s\n", prodname);
  qprintf(fp, "	id \"%s, %s\"\n", dist->product, dist->version);

  fputs("	image sw\n", fp);
  qprintf(fp, "		id \"%s, Software, %s\"\n", dist->product,
          dist->version);
  fprintf(fp, "		version %d\n", dist->vernumber);
  fputs("		subsys eoe default\n", fp);
  qprintf(fp, "			id \"%s, Software, %s\"\n", dist->product,
          dist->version);
  fprintf(fp, "			exp \"%s.sw.eoe\"\n", prodname);

  for (i = dist->num_depends, d = dist->depends; i > 0; i --, d ++)
    if (d->type == DEPEND_REQUIRES)
      break;

  if (i)
  {
    fputs("			prereq\n", fp);
    fputs("			(\n", fp);
    for (; i > 0; i --, d ++)
      if (d->type == DEPEND_REQUIRES)
      {
        if (strchr(d->product, '.') != NULL)
  	  fprintf(fp, "				%s %d %d\n",
         	  d->product, d->vernumber[0], d->vernumber[1]);
        else if (d->product[0] != '/')
  	  fprintf(fp, "				%s.sw.eoe %d %d\n",
         	  d->product, d->vernumber[0], d->vernumber[1]);
      }
    fputs("			)\n", fp);
  }

  for (i = dist->num_depends, d = dist->depends; i > 0; i --, d ++)
    if (d->type == DEPEND_REPLACES)
    {
      if (strchr(d->product, '.') != NULL)
        fprintf(fp, "			replaces %s %d %d\n",
         	d->product, d->vernumber[0], d->vernumber[1]);
      else if (d->product[0] != '/')
        fprintf(fp, "			replaces %s.sw.eoe %d %d\n",
         	d->product, d->vernumber[0], d->vernumber[1]);
    }
    else if (d->type == DEPEND_INCOMPAT)
    {
      if (strchr(d->product, '.') != NULL)
        fprintf(fp, "			incompat %s %d %d\n",
         	d->product, d->vernumber[0], d->vernumber[1]);
      else if (d->product[0] != '/')
        fprintf(fp, "			incompat %s.sw.eoe %d %d\n",
         	d->product, d->vernumber[0], d->vernumber[1]);
    }

  fputs("		endsubsys\n", fp);
  fputs("	endimage\n", fp);

  fputs("	image man\n", fp);
  qprintf(fp, "		id \"%s, Man Pages, %s\"\n", dist->product,
          dist->version);
  fprintf(fp, "		version %d\n", dist->vernumber);
  fputs("		subsys eoe default\n", fp);
  qprintf(fp, "			id \"%s, Man Pages, %s\"\n", dist->product,
          dist->version);
  fprintf(fp, "			exp \"%s.man.eoe\"\n", prodname);
  fputs("		endsubsys\n", fp);
  fputs("	endimage\n", fp);

  fputs("endproduct\n", fp);

  fclose(fp);

 /*
  * Add symlinks for init scripts...
  */

  for (i = 0; i < dist->num_files; i ++)
    if (tolower(dist->files[i].type) == 'i')
    {
     /*
      * Make symlinks for all of the selected run levels...
      */

      for (runlevels = get_runlevels(dist->files + i, "02");
           isdigit(*runlevels);
	   runlevels ++)
      {
	file = add_file(dist);
	file->type = 'l';
	file->mode = 0;
	strcpy(file->user, "root");
	strcpy(file->group, "sys");
	snprintf(file->src, sizeof(file->src), "../init.d/%s",
        	 dist->files[i].dst);

        if (*runlevels == '0')
	  snprintf(file->dst, sizeof(file->dst), "/etc/rc0.d/K%02d%s",
        	   get_stop(dist->files + i, 0), dist->files[i].dst);
        else
	  snprintf(file->dst, sizeof(file->dst), "/etc/rc%c.d/S%02d%s",
        	   *runlevels, get_start(dist->files + i, 99),
		   dist->files[i].dst);
      }

     /*
      * Then send the original file to /etc/init.d...
      */

      file = dist->files + i;

      snprintf(filename, sizeof(filename), "/etc/init.d/%s", file->dst);
      strcpy(file->dst, filename);
    }

 /*
  * Add preinstall script as needed...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_PRE_INSTALL)
      break;

  if (i)
  {
   /*
    * Add the preinstall script file to the list...
    */

    file = add_file(dist);
    file->type = '1';
    file->mode = 0555;
    strcpy(file->user, "root");
    strcpy(file->group, "sys");
    snprintf(file->src, sizeof(file->src), "%s/%s.preinstall", directory,
             prodname);
    snprintf(file->dst, sizeof(file->dst), "%s/%s.preinstall", SoftwareDir,
             prodname);

   /*
    * Then create the install script...
    */

    if (Verbosity)
      puts("Creating preinstall script...");

    snprintf(preinstall, sizeof(preinstall), "%s/%s.preinstall", directory, prodname);

    if ((fp = fopen(preinstall, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", preinstall,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (; i > 0; i --, c ++)
      if (c->type == COMMAND_PRE_INSTALL)
        fprintf(fp, "%s\n", c->command);

    fclose(fp);
  }
  else
    preinstall[0] = '\0';

 /*
  * Add postinstall script as needed...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_POST_INSTALL)
      break;

  if (i)
  {
   /*
    * Add the postinstall script file to the list...
    */

    file = add_file(dist);
    file->type = '2';
    file->mode = 0555;
    strcpy(file->user, "root");
    strcpy(file->group, "sys");
    snprintf(file->src, sizeof(file->src), "%s/%s.postinstall", directory,
             prodname);
    snprintf(file->dst, sizeof(file->dst), "%s/%s.postinstall", SoftwareDir,
             prodname);

   /*
    * Then create the install script...
    */

    if (Verbosity)
      puts("Creating postinstall script...");

    snprintf(postinstall, sizeof(postinstall), "%s/%s.postinstall", directory, prodname);

    if ((fp = fopen(postinstall, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", postinstall,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (; i > 0; i --, c ++)
      if (c->type == COMMAND_POST_INSTALL)
        fprintf(fp, "%s\n", c->command);

    fclose(fp);
  }
  else
    postinstall[0] = '\0';

 /*
  * Add preremove script as needed...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_PRE_REMOVE)
      break;

  if (i)
  {
   /*
    * Add the preremove script file to the list...
    */

    file = add_file(dist);
    file->type = '3';
    file->mode = 0555;
    strcpy(file->user, "root");
    strcpy(file->group, "sys");
    snprintf(file->src, sizeof(file->src), "%s/%s.preremove", directory,
             prodname);
    snprintf(file->dst, sizeof(file->dst), "%s/%s.preremove", SoftwareDir,
             prodname);

   /*
    * Then create the install script...
    */

    if (Verbosity)
      puts("Creating preremove script...");

    snprintf(preremove, sizeof(preremove), "%s/%s.preremove", directory, prodname);

    if ((fp = fopen(preremove, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", preremove,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (; i > 0; i --, c ++)
      if (c->type == COMMAND_PRE_REMOVE)
        fprintf(fp, "%s\n", c->command);

    qprintf(fp, "/bin/rm -f %s.copy\n", file->dst);

    fclose(fp);
  }
  else
    preremove[0] = '\0';

 /*
  * Add postremove script as needed...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_POST_REMOVE)
      break;

  if (i)
  {
   /*
    * Add the postremove script file to the list...
    */

    file = add_file(dist);
    file->type = '4';
    file->mode = 0555;
    strcpy(file->user, "root");
    strcpy(file->group, "sys");
    snprintf(file->src, sizeof(file->src), "%s/%s.postremove", directory,
             prodname);
    snprintf(file->dst, sizeof(file->dst), "%s/%s.postremove", SoftwareDir,
             prodname);

   /*
    * Then create the remove script...
    */

    if (Verbosity)
      puts("Creating postremove script...");

    snprintf(postremove, sizeof(postremove), "%s/%s.postremove", directory, prodname);

    if ((fp = fopen(postremove, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", postremove,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (; i > 0; i --, c ++)
      if (c->type == COMMAND_POST_REMOVE)
        fprintf(fp, "%s\n", c->command);

    qprintf(fp, "/bin/rm -f %s.copy\n", file->dst);

    fclose(fp);
  }
  else
    postremove[0] = '\0';

 /*
  * Sort the file list by the destination name, since gendist needs a sorted
  * list...
  */

  sort_dist_files(dist);

 /*
  * Write the idb file for gendist...
  */

  if (Verbosity)
    puts("Creating idb file...");

  snprintf(idbname, sizeof(idbname), "%s/idb", directory);

  if ((fp = fopen(idbname, "w")) == NULL)
  {
    fprintf(stderr, "epm: Unable to create idb file \"%s\" - %s\n", idbname,
            strerror(errno));
    return (1);
  }

  for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
  {
    if (strstr(file->dst, "/man/") != NULL ||
        strstr(file->dst, "/catman/") != NULL)
      snprintf(subsys, sizeof(subsys), "%s.man.eoe", prodname);
    else
      snprintf(subsys, sizeof(subsys), "%s.sw.eoe", prodname);

    switch (tolower(file->type))
    {
      case '1' :
          qprintf(fp, "f %04o %s %s %s %s %s postop($rbase/%s)\n", file->mode,
	          file->user, file->group, file->dst + 1, file->src, subsys,
		  file->dst + 1);
          break;
      case '2' :
          qprintf(fp, "f %04o %s %s %s %s %s exitop($rbase/%s)\n", file->mode,
	          file->user, file->group, file->dst + 1, file->src, subsys,
		  file->dst + 1);
          break;
      case '3' :
      case '4' :
          qprintf(fp, "f %04o %s %s %s %s %s "
	              "postop(cp $rbase/%s $rbase/%s.copy) "
		      "removeop($rbase/%s.copy)\n",
                  file->mode, file->user, file->group, file->dst + 1,
		  file->src, subsys, file->dst + 1, file->dst + 1,
		  file->dst + 1);
          break;
      case 'c' :
          qprintf(fp, "f %04o %s %s %s %s %s config(suggest)\n", file->mode,
	          file->user, file->group, file->dst + 1, file->src, subsys);
          break;
      case 'd' :
          qprintf(fp, "d %04o %s %s %s - %s\n", file->mode,
	          file->user, file->group, file->dst + 1, subsys);
          break;
      case 'f' :
          qprintf(fp, "f %04o %s %s %s %s %s\n", file->mode,
	          file->user, file->group, file->dst + 1, file->src, subsys);
          break;
      case 'i' :
          qprintf(fp, "f %04o %s %s %s %s %s exitop($rbase/etc/init.d/%s start) removeop($rbase/etc/init.d/%s stop)\n",
	          file->mode, file->user, file->group, file->dst + 1,
		  file->src, subsys, file->dst + 12, file->dst + 12);
          break;
      case 'l' :
          qprintf(fp, "l %04o %s %s %s - %s symval(%s)\n", file->mode,
	          file->user, file->group, file->dst + 1, subsys, file->src);
          break;
    }
  }

  fclose(fp);

 /*
  * Build the distribution from the spec file...
  */

  if (Verbosity)
    puts("Building INST binary distribution...");

  if (run_command(NULL, "gendist %s -dist %s -sbase . -idb %s -spec %s",
                  Verbosity == 0 ? "" : "-v", directory, idbname, specname))
    return (1);

 /*
  * Build the tardist file...
  */

  if (Verbosity)
    printf("Writing tardist file:");

  snprintf(filename, sizeof(filename), "%s/%s.tardist", directory, name);
  if ((tarfile = tar_open(filename, 0)) == NULL)
  {
    if (Verbosity)
      puts("");

    fprintf(stderr, "epm: Unable to create file \"%s\" -\n     %s\n",
            filename, strerror(errno));
    return (1);
  }

  for (i = 0; i < 4; i ++)
  {
    snprintf(srcname, sizeof(srcname), "%s/%s%s", directory, prodname, extensions[i]);
    snprintf(dstname, sizeof(dstname), "%s%s", prodname, extensions[i]);

    stat(srcname, &fileinfo);
    if (tar_header(tarfile, TAR_NORMAL, fileinfo.st_mode, fileinfo.st_size,
	           fileinfo.st_mtime, "root", "sys", dstname, NULL) < 0)
    {
      if (Verbosity)
        puts("");

      fprintf(stderr, "epm: Error writing file header - %s\n",
	      strerror(errno));
      return (-1);
    }

    if (tar_file(tarfile, srcname) < 0)
    {
      if (Verbosity)
        puts("");

      fprintf(stderr, "epm: Error writing file data for %s -\n    %s\n",
	      dstname, strerror(errno));
      return (-1);
    }

    if (Verbosity)
    {
      printf(" %s%s", prodname, extensions[i]);
      fflush(stdout);
    }
  }

  tar_close(tarfile);

  if (Verbosity)
  {
    stat(filename, &fileinfo);
    if (fileinfo.st_size > (1024 * 1024))
      printf(" size=%.1fM\n", fileinfo.st_size / 1024.0 / 1024.0);
    else
      printf(" size=%.0fk\n", fileinfo.st_size / 1024.0);
  }

 /*
  * Remove temporary files...
  */

  if (!KeepFiles)
  {
    if (Verbosity)
      puts("Removing temporary distribution files...");

    if (preinstall[0])
      unlink(preinstall);
    if (postinstall[0])
      unlink(postinstall);
    if (preremove[0])
      unlink(preremove);
    if (postremove[0])
      unlink(postremove);

    unlink(idbname);
    unlink(specname);
  }

  return (0);
}


/*
 * End of "$Id: inst.c,v 1.25 2002/12/17 18:57:55 swdev Exp $".
 */
