/*BINFMTC:
 *  cowbuilder / pbuilder with cowdancer
 *  Copyright (C) 2005 Junichi Uekawa
 *
 *  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 of the License, 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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
/* 
  sudo ./cowbuilder --create --distribution sid --basepath /mnt/120g-1/dancer/cow/cow
  sudo ./cowbuilder --update --basepath /mnt/120g-1/dancer/cow/cow

  sudo mkdir /mnt/120g-1/dancer/cow/cow
  cd /mnt/120g-1/dancer/cow/cow
  sudo tar xfzp /var/cache/pbuilder/base.tgz
  sudo chroot . dpkg -i tmp/cowdancer_0.3_i386.deb

  sudo ./cowbuilder.c --build --basepath /mnt/120g-1/dancer/cow/cow $FILENAME

 */

#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>

typedef struct pbuilderconfig 
{
  int mountproc;
  int mountdev;
  int mountdevpts;
  char* buildplace;		/* /var/cache/pbuilder/buildplace/XXX.$$ */
  char* basepath;		/* /var/cache/pbuilder/buildplace/XXX */
  char* distribution;
  enum {
    pbuilder_do_nothing=0,
    pbuilder_build,
    pbuilder_create,
    pbuilder_update
  } operation;  
}pbuilderconfig;


int cpbuilder_build(const struct pbuilderconfig* pc, const char* dscfile_)
{
  const char* dscfile=canonicalize_file_name(dscfile_);
  char* buf;


  if (!dscfile)
    {
      fprintf(stderr, "File not found: %s\n", dscfile_);
      return 1;
    }
  
  asprintf(&buf, "rm -rf \"%s\" ; cp -al \"%s\" \"%s\"",
	   pc->buildplace, 
	   pc->basepath, 
	   pc->buildplace);
  printf ("%s\n", buf);
  system (buf);
  asprintf(&buf, "pbuilder build --buildplace '%s' --no-targz  --internal-chrootexec 'chroot %s cow-shell' '%s'",
	   pc->buildplace, 
	   pc->buildplace,
	   dscfile);
  printf ("%s\n", buf);
  system (buf);
}

int cpbuilder_create(const struct pbuilderconfig* pc)
{
  char* buf;

  asprintf(&buf, "pbuilder create --distribution %s --buildplace %s --no-targz",
	   pc->distribution, 
	   pc->basepath);
  printf("Invoking pbuilder: %s", buf);
  return system(buf);
}

int cpbuilder_update(const struct pbuilderconfig* pc)
{
  /* TBD */
}

int main(int ac, char** av)
{
  int c;			/* option */
  int index_point;
  static pbuilderconfig pc;

  static struct option long_options[]=
  {
    {"basepath", required_argument, 0, 'b'},
    {"distribution", required_argument, 0, 'd'},
    {"mountproc", no_argument, &pc.mountproc, 1},
    {"mountdev", no_argument, &pc.mountdev, 1},
    {"mountdevpts", no_argument, &pc.mountdevpts, 1},
    {"nomountproc", no_argument, &pc.mountproc, 0},
    {"nomountdev", no_argument, &pc.mountdev, 0},
    {"nomountdevpts", no_argument, &pc.mountdevpts, 0},
    {"build", no_argument, (int*)&pc.operation, pbuilder_build},
    {"create", no_argument, (int*)&pc.operation, pbuilder_create},
    {"update", no_argument, (int*)&pc.operation, pbuilder_update},
    {"help", no_argument, 0, 'h'},
    {"version", no_argument, 0, 'v'},
    {0,0,0,0}
  };

  /* define pc to be clear. */
  memset (&pc, 0, sizeof(pbuilderconfig));

  /* load config files here. */
  while((c = getopt_long (ac, av, "b:d:hv", long_options, &index_point)) != -1)
    {
      switch (c)
	{
	case 'b':
	  pc.basepath = canonicalize_file_name (optarg);
	  break;
	case 'd':
	  pc.distribution = strdup(optarg);
	  break;
	case 'h':
	  break;
	case 'v':
	  break;
	case 0:
	  /* other cases with long option with flags,
	     this is expected behavior, so ignore it.
	  */
	  break;	  
	default:
	  fprintf(stderr, "Unhandled option\n");
	  /* Error case. */
	  return 1;
	}
    }

  /* set default values */
  if (!pc.basepath) 
    pc.basepath=strdup("/var/cache/pbuilder/build/cow");
  asprintf(&(pc.buildplace), "%s%i", pc.basepath, (int)getpid());

  switch(pc.operation)
    {
    case pbuilder_build:
      cpbuilder_build(&pc, av[optind]);
      break;
      
    case pbuilder_create:
      cpbuilder_create(&pc);
      break;
      
    case pbuilder_update:
      cpbuilder_update(&pc);
      break;
      
    default:
      fprintf(stderr, "No operation selected\n");
      return 1;
    }
  
  return 0;
}
