Index: /trunk/Ohana/src/imregister/detrend/altpath.c
===================================================================
--- /trunk/Ohana/src/imregister/detrend/altpath.c	(revision 76)
+++ /trunk/Ohana/src/imregister/detrend/altpath.c	(revision 76)
@@ -0,0 +1,132 @@
+# include "imregister.h"
+# include "detrend.h"
+
+int SetAltpath (Match *match, int Nmatch) {
+  
+  int i, j, n, found, status;
+  int Nimage, Nlist, Ncurrent, Nadd, Nremove;
+  int *list, *current, *curfound, *add, *remove;
+  char *dBPath, input[256], output[256], line[1024];
+  DetReg *image;
+  
+  image = get_images (&Nimage);
+  ALLOCATE (current, int, Nimage);
+
+  /* identify current altpath images */
+  Ncurrent = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (image[i].altpath) {
+      current[Ncurrent] = i;
+      Ncurrent++; 
+    }
+  }
+
+  /* extract 'remove' and 'add' entries from current & match */
+  ALLOCATE (remove, int, Nimage);
+  ALLOCATE (add, int, Nimage);
+  
+  ALLOCATE (curfound, int, Ncurrent);
+  bzero (curfound, Ncurrent*sizeof(int));
+
+  Nadd = Nremove = 0;
+  for (i = 0; i < Nmatch; i++) {
+    found = FALSE;
+    for (j = 0; !found && (j < Ncurrent); j++) {
+      if (match[i].image == current[j]) {
+	found = TRUE;
+	curfound[j] = TRUE;
+      }
+    }
+    if (!found) {
+      add[Nadd] = match[i].image;
+      Nadd ++;
+    }
+  }
+  for (i = 0; i < Ncurrent; i++) {
+    if (!curfound[i]) {
+      remove[Nremove] = current[i];
+      Nremove ++;
+    }
+  }
+  free (current);
+  free (curfound);
+  
+  ALLOCATE (list, int, Nimage);
+  Nlist = 0;
+
+  dBPath = get_dBPath ();
+
+  /* set altpath for 'add' images */
+  for (j = 0; j < Nadd; j++) {
+    i = add[j];
+    image[i].altpath = TRUE;
+    list[Nlist] = i;
+    Nlist ++;
+    for (n = 0; n < NDetrendAltDB; n++) {
+      sprintf (input, "%s/%s", dBPath, image[i].filename);
+      sprintf (output, "%s/%s", DetrendAltDB[n], image[i].filename);
+      status = ckpathname (output);
+      if (!status) {
+	remove[Nremove] = i;
+	Nremove ++;
+	break;
+      }
+      sprintf (line, "cp %s %s", input, output);
+      fprintf (stderr, "%s\n", line);
+      status = system (line);
+      if (status) {
+	remove[Nremove] = i;
+	Nremove ++;
+	break;
+      }
+    }
+  }
+
+  /* unset altpath for 'remove' images */
+  for (j = 0; j < Nremove; j++) {
+    i = remove[j];
+    image[i].altpath = FALSE;
+    list[Nlist] = i;
+    Nlist ++;
+    for (n = 0; n < NDetrendAltDB; n++) {
+      sprintf (output, "%s/%s", DetrendAltDB[n], image[i].filename);
+      sprintf (line, "rm %s", output);
+      fprintf (stderr, "%s\n", line);
+      status = system (line);
+      if (status) {
+	fprintf (stderr, "warning: can't delete %s\n", output);
+      }
+    }
+  }
+
+  update_db (list, Nlist);
+  close_db ();
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+
+int ckpathname (char *newpath) {
+  
+  int status;
+  char *path;
+  struct stat statbuf;
+  
+  path = pathname (newpath);
+  
+  status = stat (path, &statbuf);
+  if (status == -1) {
+    if (errno == ENOENT) {
+      if (mkdirhier (path) == -1) {
+	fprintf (stderr, "ERROR: can't create path %s\n", path);
+	return (FALSE);
+      }
+    } else {
+      fprintf (stderr, "ERROR: problem with path %s\n", path);
+      return (FALSE);
+    }
+  }
+  free (path);
+  return (TRUE);
+}
Index: /trunk/Ohana/src/imregister/imreg/FifoOps.c
===================================================================
--- /trunk/Ohana/src/imregister/imreg/FifoOps.c	(revision 76)
+++ /trunk/Ohana/src/imregister/imreg/FifoOps.c	(revision 76)
@@ -0,0 +1,97 @@
+# include "imregister.h"
+# include "imreg.h"
+
+int InitFifo (Fifo *fifo, int Nalloc, int Nextra) {
+
+  if (Nextra >= Nalloc) {
+    fprintf (stderr, "absurd fifo definition\n");
+    return (FALSE);
+  }
+
+  fifo[0].Nalloc = Nalloc;
+  fifo[0].Nextra = Nextra;
+  fifo[0].Nmaxread = Nalloc - Nextra;
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  ALLOCATE (fifo[0].buffer, char, fifo[0].Nalloc);
+
+  return (TRUE);
+
+}
+
+int FlushFifo (Fifo *fifo) {
+
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  return (TRUE);
+
+}
+
+/* after a shift, we can always read 
+   fifo[0].Nmaxread 
+   bytes into 
+   &fifo[0].buffer[Nbuffer] 
+   which is the byte after then end of existing data */
+
+int ShiftFifo (Fifo *fifo) {
+
+  int Nextra, Nshift;
+
+  Nextra = fifo[0].Nextra;
+  Nshift = fifo[0].Nbuffer - fifo[0].Nextra;
+  if (Nshift <= 0) return (TRUE);
+
+  memcpy (fifo[0].buffer, &fifo[0].buffer[Nshift], Nextra);
+  fifo[0].Nbuffer = Nextra;
+  fifo[0].Nlast = Nextra;
+
+  return (TRUE);
+}
+
+/* like a standard read, ReadtoFifo returns Nbytes read,
+   -1 for sock busy, or 0 for sock closed */
+
+int ReadtoFifo (Fifo *fifo, int sock) {
+
+  int Nread;
+  int Nbuffer, Nmaxread;
+
+  if (sock == 0) {
+    fprintf (stderr, "error with socket?\n");
+    return (0);
+  }
+
+  fifo[0].Nlast = fifo[0].Nbuffer;
+
+  Nbuffer = fifo[0].Nbuffer;
+  Nmaxread = fifo[0].Nmaxread;
+  Nread = read (sock, &fifo[0].buffer[Nbuffer], Nmaxread);
+
+  if (Nread > 0) fifo[0].Nbuffer += Nread;
+
+  if (Nread == -1) {
+    /* check for possible errors.  anything other than EAGAIN
+       is bad and should indicate the connection is down */
+    switch (errno) {
+    case EAGAIN:
+    case EIO:
+      Nread = -1;
+      break;
+    default:
+      fprintf (stderr, "read error: %d\n", errno);
+      Nread = 0;
+      break;
+    }
+  }
+
+  return (Nread);
+}
+
+void FreeFifo (Fifo *fifo) {
+
+  if (fifo[0].buffer != (char *) NULL) {
+    free (fifo[0].buffer);
+  }
+}
Index: /trunk/Ohana/src/imregister/imreg/SockScan.c
===================================================================
--- /trunk/Ohana/src/imregister/imreg/SockScan.c	(revision 76)
+++ /trunk/Ohana/src/imregister/imreg/SockScan.c	(revision 76)
@@ -0,0 +1,54 @@
+# include "imregister.h"
+# include "imreg.h"
+# include <errno.h>
+# define MAXTIME 10
+
+int SockScan (char *string, Fifo *fifo, int sock) {
+  
+  int i, done, status;
+
+  done = 0;
+  for (i = 0; (i < MAXTIME) && !done; i++) {
+    ShiftFifo (fifo);
+    status = ReadtoFifo (fifo, sock);
+    switch (status) {
+    case 0:
+      break;
+    case -1:
+      usleep (1000);
+      break;
+    default:
+      done = memstr (fifo[0].buffer, string, fifo[0].Nbuffer);
+      break;
+    }
+  }
+  return (status);
+}
+
+/* returns (offset to m2) + 1, or 0 if failure */ 
+int memstr (char *m1, char *m2, int n) {
+
+  int i, N;
+
+  N = strlen (m2);
+  for (i = 0; (i < n - N + 1) && memcmp (m1, m2, N); i++, m1++);
+  if (memcmp (m1, m2, N)) {
+    return (0);
+  }
+  else {
+    return (i+1);
+  }
+
+}
+ 
+/* SockScan reads from the given socket looking for the given string
+   SockScan stores data read from socket in the fifo buffer to ensure 
+   it catches the given string.  a single invocation of SockScan will 
+   wait for up to 10 msec for data to come down the pipe before giving up.
+   SockScan can only search for one string in the output stream.
+   */
+
+
+/* need a way of signalling that the socket has closed...
+   maybe change the sock entry to 0?
+*/
Index: /trunk/Ohana/src/imregister/imreg/rconnect.c
===================================================================
--- /trunk/Ohana/src/imregister/imreg/rconnect.c	(revision 76)
+++ /trunk/Ohana/src/imregister/imreg/rconnect.c	(revision 76)
@@ -0,0 +1,99 @@
+# include "imregister.h"
+# include "imreg.h"
+
+/* rconnect opens a remote shell on hostname and returns two file descriptors:
+   one for read, one for write */
+
+int rconnect (char *hostname, char *command, int *rsock, int *wsock) {
+
+  int i, rfd[2], wfd[2], status;
+  pid_t pid;
+  char buffer[0x4000];
+  char *file;
+  Fifo fifo;
+
+  InitFifo (&fifo, 0x4000, 0x1000);
+
+  status = pipe (rfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+  status = pipe (wfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+
+  file = filebasename (command);
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    fprintf (stderr, "starting remote connection to %s...", hostname);
+    /* close the excess sockets */
+    close (wfd[1]);
+    close (rfd[0]);
+    dup2 (wfd[0], STDIN_FILENO);
+    dup2 (rfd[1], STDOUT_FILENO);
+    dup2 (rfd[1], STDERR_FILENO);
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execl (command, file, hostname, "/bin/csh", 0); 
+    fprintf (stderr, "error starting remote shell process\n");
+    Shutdown (1);
+  }
+  *wsock = wfd[1];
+  *rsock = rfd[0];
+  close (wfd[0]);
+  close (rfd[1]);
+  
+  fcntl (*rsock, F_SETFL, O_NONBLOCK);
+  fcntl (*wsock, F_SETFL, O_NONBLOCK);
+
+  sprintf (buffer, "echo PTOLEMY STARTED\n");
+  status = write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  /* try to get evidence connection is alive - wait upto a few seconds */
+  status = -1;
+  for (i = 0; (i < 100) && (status == -1); i++) {
+    fcntl (*rsock, F_SETFL, O_NONBLOCK);
+    status = SockScan ("PTOLEMY STARTED", &fifo, *rsock);
+    if (status == 0) {
+      fprintf (stderr, "socket closed unexpectedly\n");
+      close (*wsock);
+      close (*rsock);
+      return (FALSE);
+    }
+  }
+  if (i == 100) {
+    fprintf (stderr, "timeout while connecting\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+  fprintf (stderr, "Connected\n");
+
+  /* the onintr command works with csh/tcsh type shells to
+     prevent trapping of SIGTERM, used to kill hung jobs.
+     for bash/sh type shells, you can use SIGQUIT instead
+     without setting onintr */
+  sprintf (buffer, "onintr\n");
+  write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  FreeFifo (&fifo);
+  return (pid);
+
+}
Index: /trunk/Ohana/src/imregister/include/mosaics.h
===================================================================
--- /trunk/Ohana/src/imregister/include/mosaics.h	(revision 76)
+++ /trunk/Ohana/src/imregister/include/mosaics.h	(revision 76)
@@ -0,0 +1,63 @@
+
+MosaicLayout *CreateCFH12K () {
+
+  MosaicLayout *layout;
+
+  ALLOCATE (layout, MosaicLayout, 1);
+
+  layout[0].center.Nccd = 4;
+  ALLOCATE (layout[0].center.ccd, int, layout[0].center.Nccd);
+  layout[0].center.ccd[0] = 2;
+  layout[0].center.ccd[1] = 3;
+  layout[0].center.ccd[2] = 8;
+  layout[0].center.ccd[3] = 9;
+
+  layout[0].outer.Nccd = 8;
+  ALLOCATE (layout[0].outer.ccd, int, layout[0].outer.Nccd);
+  layout[0].outer.ccd[0] = 0;
+  layout[0].outer.ccd[1] = 1;
+  layout[0].outer.ccd[2] = 4;
+  layout[0].outer.ccd[3] = 5;
+  layout[0].outer.ccd[4] = 6;
+  layout[0].outer.ccd[5] = 7;
+  layout[0].outer.ccd[6] = 10;
+  layout[0].outer.ccd[7] = 11;
+
+  layout[0].top.Nccd = 6;
+  ALLOCATE (layout[0].top.ccd, int, layout[0].top.Nccd);
+  layout[0].top.ccd[0] = 0;
+  layout[0].top.ccd[1] = 1;
+  layout[0].top.ccd[2] = 2;
+  layout[0].top.ccd[3] = 3;
+  layout[0].top.ccd[4] = 4;
+  layout[0].top.ccd[5] = 5;
+
+  layout[0].bottom.Nccd = 6;
+  ALLOCATE (layout[0].bottom.ccd, int, layout[0].bottom.Nccd);
+  layout[0].bottom.ccd[0] = 6;
+  layout[0].bottom.ccd[1] = 7;
+  layout[0].bottom.ccd[2] = 8;
+  layout[0].bottom.ccd[3] = 9;
+  layout[0].bottom.ccd[4] = 10;
+  layout[0].bottom.ccd[5] = 11;
+
+  layout[0].left.Nccd = 6;
+  ALLOCATE (layout[0].left.ccd, int, layout[0].left.Nccd);
+  layout[0].left.ccd[0] = 0;
+  layout[0].left.ccd[1] = 1;
+  layout[0].left.ccd[2] = 2;
+  layout[0].left.ccd[3] = 6;
+  layout[0].left.ccd[4] = 7;
+  layout[0].left.ccd[5] = 8;
+
+  layout[0].right.Nccd = 6;
+  ALLOCATE (layout[0].right.ccd, int, layout[0].right.Nccd);
+  layout[0].right.ccd[0] = 3;
+  layout[0].right.ccd[1] = 4;
+  layout[0].right.ccd[2] = 5;
+  layout[0].right.ccd[3] = 9;
+  layout[0].right.ccd[4] = 10;
+  layout[0].right.ccd[5] = 11;
+
+  return (layout);
+}
