diff --git a/Makefile b/Makefile
index 9fbc98c7..47943097 100644
--- a/Makefile
+++ b/Makefile
@@ -11,12 +11,13 @@ BINDIR       = ${PREFIX}/bin
 MANDIR       = ${PREFIX}/man/man1
 MANUAL       = avrprog.1
 DOCDIR       = ${PREFIX}/share/doc/avrprog
+CONFIGDIR    = ${PREFIX}/etc
 
-DIRS         = ${BINDIR} ${MANDIR} ${DOCDIR}
+DIRS         = ${BINDIR} ${MANDIR} ${DOCDIR} ${CONFIGDIR}
 
 INSTALL      = /usr/bin/install -c -o root -g wheel
 
-CFLAGS      += -Wall --pedantic
+CFLAGS      = -g -Wall --pedantic -DCONFIG_DIR=\"${CONFIGDIR}\"
 
 LDFLAGS      =  
 
@@ -39,7 +40,11 @@ ${TARGET} : ${OBJS}
 clean :
 	rm -f *~ *.core ${TARGET} *.o
 
-install : dirs ${BINDIR}/${TARGET} ${MANDIR}/${MANUAL} ${DOCDIR}/AVRprog.pdf
+install : dirs                  \
+	  ${BINDIR}/${TARGET}   \
+	  ${MANDIR}/${MANUAL}   \
+	  ${DOCDIR}/avrprog.pdf \
+	  ${CONFIGDIR}/avrprog.conf.sample
 
 
 dirs :
@@ -51,11 +56,14 @@ dirs :
 	done
 
 ${BINDIR}/${TARGET} : ${TARGET}
-	${INSTALL_PROGRAM} ${TARGET} ${BINDIR}
+	${INSTALL_PROGRAM} ${TARGET} $@
 
 ${MANDIR}/${MANUAL} : ${MANUAL}
-	${INSTALL_MANUAL} ${MANUAL} ${MANDIR}
+	${INSTALL_MANUAL} ${MANUAL} $@
 
-${DOCDIR}/AVRprog.pdf : AVRprog.pdf
-	${INSTALL_DATA} AVRprog.pdf ${DOCDIR}/AVRprog.pdf
+${DOCDIR}/avrprog.pdf : avrprog.pdf
+	${INSTALL_DATA} avrprog.pdf $@
+
+${CONFIGDIR}/avrprog.conf.sample : avrprog.conf.sample
+	${INSTALL_DATA} avrprog.conf.sample $@
 
diff --git a/avr.c b/avr.c
index 0936dd6f..10965ad0 100644
--- a/avr.c
+++ b/avr.c
@@ -114,16 +114,16 @@ int avr_txrx_bit ( int fd, int bit )
    * read the result bit (it is either valid from a previous clock
    * pulse or it is ignored in the current context)
    */
-  r = ppi_getpin(fd, PIN_AVR_MISO);
+  r = ppi_getpin(fd, pinno[PIN_AVR_MISO]);
 
   /* set the data input line as desired */
-  ppi_setpin(fd, PIN_AVR_MOSI, bit);
+  ppi_setpin(fd, pinno[PIN_AVR_MOSI], bit);
 
   /* 
    * pulse the clock line, clocking in the MOSI data, and clocking out
    * the next result bit
    */
-  ppi_pulsepin(fd, PIN_AVR_SCK);
+  ppi_pulsepin(fd, pinno[PIN_AVR_SCK]);
 
   return r;
 }
@@ -176,8 +176,8 @@ unsigned char avr_read_byte ( int fd, struct avrpart * p,
   /* order here is very important, AVR_EEPROM, AVR_FLASH, AVR_FLASH+1 */
   static unsigned char cmdbyte[3] = { 0xa0, 0x20, 0x28 };
 
-  LED_ON(fd, PIN_LED_PGM);
-  LED_OFF(fd, PIN_LED_ERR);
+  LED_ON(fd, pinno[PIN_LED_PGM]);
+  LED_OFF(fd, pinno[PIN_LED_ERR]);
 
   offset = 0;
 
@@ -193,7 +193,7 @@ unsigned char avr_read_byte ( int fd, struct avrpart * p,
 
   avr_cmd(fd, cmd, res);
 
-  LED_OFF(fd, PIN_LED_PGM);
+  LED_OFF(fd, pinno[PIN_LED_PGM]);
 
   return res[3];
 }
@@ -253,8 +253,8 @@ int avr_write_byte ( int fd, struct avrpart * p, AVRMEM memtype,
     return 0;
   }
 
-  LED_ON(fd, PIN_LED_PGM);
-  LED_OFF(fd, PIN_LED_ERR);
+  LED_ON(fd, pinno[PIN_LED_PGM]);
+  LED_OFF(fd, pinno[PIN_LED_ERR]);
 
   offset = 0;
 
@@ -297,13 +297,14 @@ int avr_write_byte ( int fd, struct avrpart * p, AVRMEM memtype,
        * we couldn't write the data, indicate our displeasure by
        * returning an error code 
        */
-      LED_OFF(fd, PIN_LED_PGM);
-      LED_ON(fd, PIN_LED_ERR);
+      LED_OFF(fd, pinno[PIN_LED_PGM]);
+      LED_ON(fd, pinno[PIN_LED_ERR]);
+
       return -1;
     }
   }
 
-  LED_OFF(fd, PIN_LED_PGM);
+  LED_OFF(fd, pinno[PIN_LED_PGM]);
   return 0;
 }
 
@@ -326,7 +327,7 @@ int avr_write ( int fd, struct avrpart * p, AVRMEM memtype, int size )
   unsigned char    data;
   int              werror;
 
-  LED_OFF(fd, PIN_LED_ERR);
+  LED_OFF(fd, pinno[PIN_LED_ERR]);
 
   werror = 0;
 
@@ -351,7 +352,7 @@ int avr_write ( int fd, struct avrpart * p, AVRMEM memtype, int size )
     if (rc) {
       fprintf(stderr, " ***failed;  ");
       fprintf(stderr, "\n");
-      LED_ON(fd, PIN_LED_ERR);
+      LED_ON(fd, pinno[PIN_LED_ERR]);
       werror = 1;
     }
     if (werror) {
@@ -359,7 +360,7 @@ int avr_write ( int fd, struct avrpart * p, AVRMEM memtype, int size )
        * make sure the error led stay on if there was a previous write
        * error, otherwise it gets cleared in avr_write_byte() 
        */
-      LED_ON(fd, PIN_LED_ERR);
+      LED_ON(fd, pinno[PIN_LED_ERR]);
     }
   }
 
@@ -394,13 +395,13 @@ int avr_chip_erase ( int fd, struct avrpart * p )
   unsigned char data[4] = {0xac, 0x80, 0x00, 0x00};
   unsigned char res[4];
 
-  LED_ON(fd, PIN_LED_PGM);
+  LED_ON(fd, pinno[PIN_LED_PGM]);
 
   avr_cmd(fd, data, res);
   usleep(p->chip_erase_delay);
   avr_initialize(fd, p);
 
-  LED_OFF(fd, PIN_LED_PGM);
+  LED_OFF(fd, pinno[PIN_LED_PGM]);
 
   return 0;
 }
@@ -455,9 +456,9 @@ int avr_initialize ( int fd, struct avrpart * p )
   avr_powerup(fd);
 
 
-  ppi_setpin(fd, PIN_AVR_SCK, 0);
-  ppi_setpin(fd, PIN_AVR_RESET, 0);
-  ppi_pulsepin(fd, PIN_AVR_RESET);
+  ppi_setpin(fd, pinno[PIN_AVR_SCK], 0);
+  ppi_setpin(fd, pinno[PIN_AVR_RESET], 0);
+  ppi_pulsepin(fd, pinno[PIN_AVR_RESET]);
 
   usleep(20000); /* 20 ms XXX should be a per-chip parameter */
 
@@ -478,7 +479,7 @@ int avr_initialize ( int fd, struct avrpart * p )
       rc = avr_program_enable ( fd );
       if (rc == 0)
         break;
-      ppi_pulsepin(fd, PIN_AVR_SCK);
+      ppi_pulsepin(fd, pinno[PIN_AVR_SCK]);
       tries++;
     } while (tries < 32);
 
diff --git a/avrdude.1 b/avrdude.1
index b732690c..0dc3934d 100644
--- a/avrdude.1
+++ b/avrdude.1
@@ -113,6 +113,31 @@ ll.
 8515	AT90S8515
 8535	AT90S8535
 .TE
+.It Fl c Ar Pin-Configuration
+Use the pin configuration specified by the argument.  Pin
+configurations are read from the config file (see the
+.Fl C
+option).  New pin configurations can be easily added or modified
+through the use of a config file to make
+.Nm avrprog
+work with different programmers as long as the programmer supports the
+Atmel AVR serial program method.
+.It Fl C Ar Config-File
+Use the specified config file to locate the desired pin configuration.
+Pin configurations are specified in the config file using a colon
+seperated field format.  The configuration name is the first field,
+the remaining fields are of the form:
+.Ar PIN=VALUE ,
+where
+.Ar PIN
+can be
+.Ar VCC , RESET , SCK , MOSI , MISO , BUFF , PGMLED , RDYLED , VFYLED , ERRLED .
+The value is the pin number of the PC parallel port assigned to that
+function.  The
+.Ar VCC
+pin can take multible values seperated by a comma.  It's value(s) must
+come from pins 2 through 9.  The default configuration file is
+.Pa /usr/local/etc/avrprog.conf .
 .It Fl e
 Causes a chip erase to be executed.  This will reset the contents of the
 flash ROM and EEPROM to the value
@@ -300,6 +325,8 @@ ll.
 .It Pa /dev/ppi0
 default device to be used for communication with the programming
 hardware
+.It Pa /usr/local/etc/avrprog.conf
+default pin configuration file
 .It Pa ~/.inputrc
 Initialization file for the
 .Xr readline 3
diff --git a/avrdude.conf.sample b/avrdude.conf.sample
new file mode 100644
index 00000000..6dd081ca
--- /dev/null
+++ b/avrdude.conf.sample
@@ -0,0 +1,27 @@
+# $Id$
+#
+# Programmer Pin Configurations
+#
+# The format of these entries is as follows:
+#   name:[desc=<description>:][[<pin>=<value>:]...]
+#
+# Example: for a programmer called PGM-1 that uses pin 2 and 3 for
+#   power, pins 4, 5, and 6 for RESET, SCK, and MOSI, and pin 10 for
+#   MISO, we could use the following entry:
+#
+#  pgm-1 : desc=Programmer 1:vcc=2,3:reset=4:sck=5:mosi=6:miso=10
+#
+# Continuation lines are supported, use a backslash (\) as the last
+# character of the line and the next line will included as part of the
+# configuration data.
+#
+
+bsd   : desc=Brian Dean's programmer:vcc=2,3,4,5:reset=7:sck=8:\
+        mosi=9:miso=10
+
+dt006 : desc=Dontronics DT006:reset=4:sck=5:mosi=2:miso=11
+
+alf   : desc=Tony Freibel's programmer:vcc=2,3,4,5:buff=6:\
+        reset=7:sck=8:mosi=9:miso=10:errled=1:rdyled=14:pgmled=16:\
+        vfyled=17
+
diff --git a/AVRprog.pdf b/avrdude.pdf
similarity index 100%
rename from AVRprog.pdf
rename to avrdude.pdf
diff --git a/fileio.c b/fileio.c
index 920fe32c..abb441a7 100644
--- a/fileio.c
+++ b/fileio.c
@@ -42,6 +42,9 @@
 
 #define IHEX_MAXDATA 256
 
+#define MAX_LINE_LEN 256  /* max line length for ASCII format input files */
+
+
 struct ihexrec {
   unsigned char    reclen;
   unsigned short   loadofs;
diff --git a/fileio.h b/fileio.h
index 87477bc0..e7edf10b 100644
--- a/fileio.h
+++ b/fileio.h
@@ -52,8 +52,6 @@ enum {
   FIO_WRITE
 };
 
-#define MAX_LINE_LEN 256  /* max line length for ASCII format input files */
-
 char * fmtstr ( FILEFMT format );
 
 int fileio_setparms ( int op, struct fioparms * fp );
diff --git a/main.c b/main.c
index 300cc2d3..6e9246dc 100644
--- a/main.c
+++ b/main.c
@@ -73,12 +73,14 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include "avr.h"
 #include "fileio.h"
@@ -114,6 +116,8 @@ char   progbuf[PATH_MAX]; /* temporary buffer of spaces the same
                              length as progname; used for lining up
                              multiline messages */
 
+unsigned int pinno[N_PINS];
+
 /*
  * usage message
  */
@@ -138,16 +142,18 @@ int getexitspecs ( char *s, int *set, int *clr )
 
   while ((cp = strtok(s, ","))) {
     if (strcmp(cp, "reset") == 0) {
-      *clr |= ppi_getpinmask(PIN_AVR_RESET);
+      *clr |= ppi_getpinmask(pinno[PIN_AVR_RESET]);
     }
     else if (strcmp(cp, "noreset") == 0) {
-      *set |= ppi_getpinmask(PIN_AVR_RESET);
+      *set |= ppi_getpinmask(pinno[PIN_AVR_RESET]);
     }
     else if (strcmp(cp, "vcc") == 0) { 
-      *set |= PPI_AVR_VCC;
+      if (pinno[PPI_AVR_VCC])
+        *set |= pinno[PPI_AVR_VCC];
     }
     else if (strcmp(cp, "novcc") == 0) {
-      *clr |= PPI_AVR_VCC;
+      if (pinno[PPI_AVR_VCC])
+        *clr |= pinno[PPI_AVR_VCC];
     }
     else {
       return -1;
@@ -259,6 +265,329 @@ int print_module_versions ( FILE * outf, char * timestamp )
 
 
 
+#define MAX_LINE_LEN 1024
+#define MAX_PIN_NAME 64
+
+int parse_config(int lineno, char * infile, char * config, char * s, 
+                 unsigned int * pinno, char * desc, int desclen)
+{
+  char pin_name[MAX_PIN_NAME];
+  char * p;
+  int i;
+  int pins;
+  unsigned int value;
+  unsigned int v;
+  char * e;
+
+  pins = 0;
+  p = s;
+
+  while (1) {
+
+    while (*p && isspace(*p))
+      p++;
+
+    if (*p == 0) {
+      if (pins == 0) {
+        fprintf(stderr, 
+                "%s: warning: no pins configured using config entry \"%s\" "
+                "at line %d of %s\n",
+                progname, config, lineno, infile);
+      }
+      return 0;
+    }
+
+    /*
+     * parse the pin name
+     */
+    pin_name[0] = 0;
+    i = 0;
+    while (*p && (i<MAX_PIN_NAME) && !((*p == '=')||isspace(*p))) {
+      pin_name[i++] = *p;
+      p++;
+    }
+
+    if (i == MAX_PIN_NAME) {
+      fprintf(stderr, "%s: pin name too long at line %d of \"%s\"\n",
+              progname, lineno, infile);
+      return -1;
+    }
+    pin_name[i] = 0;
+
+    /* skip over spaces and equals sign */
+    while (*p && (isspace(*p)||(*p == '=')))
+      p++;
+
+    if (strcasecmp(pin_name, "desc") == 0) {
+      i = 0;
+      while (*p && (i<desclen) && (*p != ':')) {
+        desc[i++] = *p;
+        p++;
+      }
+      if (i == desclen) {
+        fprintf(stderr, 
+                "%s: error at line %d of %s: description is too "
+                "long (max = %d chars)\n",
+                progname, lineno, infile, desclen);
+        return -1;
+      }
+      desc[i] = 0;
+    }
+    else {
+      /*
+       * parse pin value
+       */
+      value = 0;
+      while (*p && (*p != ':')) {
+        
+        if (strcasecmp(pin_name, "desc") == 0) {
+          i = 0;
+          while (*p && (i<desclen) && (*p != ':')) {
+            desc[i++] = *p;
+            p++;
+          }
+          if (i == desclen) {
+            fprintf(stderr, 
+                    "%s: error at line %d of %s: description is too "
+                    "long (max = %d chars)\n",
+                    progname, lineno, infile, desclen);
+            return -1;
+          }
+          desc[i] = 0;
+        }
+        else {
+          v = strtoul(p, &e, 0);
+          if (e == p) {
+            fprintf(stderr, 
+                    "%s: can't parse pin value at line %d of \"%s\" "
+                    "starting with \"%s\"\n",
+                    progname, lineno, infile, p);
+            return -1;
+          }
+          
+          if (strcasecmp(pin_name, "VCC")==0) {
+            /*
+             * VCC is a bit mask of pins for the data register, pins 2-9
+             */
+            if ((v < 2) || (v > 9)) {
+              fprintf(stderr, 
+                      "%s: error at line %d of %s: VCC must be one or more "
+                      "pins from the range 2-9\n",
+                      progname, lineno, infile);
+              return -1;
+            }
+            value |= (1 << (v-2));
+          }
+          else {
+            if ((v <= 0) || (v >= 18)) {
+              fprintf(stderr, 
+                      "%s: error at line %d of %s: pin must be in the "
+                      "range 1-17\n",
+                      progname, lineno, infile);
+              return -1;
+            }
+            value = v;
+          }
+          
+          p = e;
+          while (*p && (isspace(*p)||(*p == ',')))
+            p++;
+        }
+        
+        if (strcasecmp(pin_name, "VCC")==0)
+          pinno[PPI_AVR_VCC] = value;
+        else if (strcasecmp(pin_name, "BUFF")==0)
+          pinno[PIN_AVR_BUFF] = value;
+        else if (strcasecmp(pin_name, "RESET")==0)
+          pinno[PIN_AVR_RESET] = value;
+        else if (strcasecmp(pin_name, "SCK")==0)
+          pinno[PIN_AVR_SCK] = value;
+        else if (strcasecmp(pin_name, "MOSI")==0)
+          pinno[PIN_AVR_MOSI] = value;
+        else if (strcasecmp(pin_name, "MISO")==0)
+          pinno[PIN_AVR_MISO] = value;
+        else if (strcasecmp(pin_name, "ERRLED")==0)
+          pinno[PIN_LED_ERR] = value;
+        else if (strcasecmp(pin_name, "RDYLED")==0)
+          pinno[PIN_LED_RDY] = value;
+        else if (strcasecmp(pin_name, "PGMLED")==0)
+          pinno[PIN_LED_PGM] = value;
+        else if (strcasecmp(pin_name, "VFYLED")==0)
+          pinno[PIN_LED_VFY] = value;
+        else {
+          fprintf(stderr, 
+                  "%s: error at line %d of %s: invalid pin name \"%s\"\n",
+                  progname, lineno, infile,  pin_name);
+          return -1;
+        } 
+        
+        pins++;
+      }
+    }
+
+    while (*p && (*p == ':'))
+      p++;
+  }
+
+  return 0;
+}
+
+  
+
+int read_config(char * infile, char * config, unsigned int * pinno, 
+                char * desc, int desclen)
+{
+  FILE * f;
+  char line[MAX_LINE_LEN];
+  char buf[MAX_LINE_LEN];
+  char configname[MAX_PIN_NAME];
+  int len, lineno, rc, cont;
+  char * p, * q;
+  int i;
+
+  for (i=0; i<N_PINS; i++)
+    pinno[i] = 0;
+
+  f = fopen(infile, "r");
+  if (f == NULL) {
+    fprintf(stderr, "%s: can't open config file \"%s\": %s\n",
+            progname, infile, strerror(errno));
+    return -1;
+  }
+
+  lineno = 0;
+  buf[0] = 0;
+  while (fgets(line, MAX_LINE_LEN, f) != NULL) {
+    lineno++;
+
+    p = line;
+    while (isspace(*p))
+      p++;
+
+    if ((*p == '#')||(*p == '\n')||(*p == 0))
+      continue;
+
+    len = strlen(p);
+    if (p[len-1] == '\n') {
+      p[len-1] = 0;
+      len--;
+    }
+
+    cont = 0;
+
+    if (p[len-1] == '\\') {
+      cont = 1;              /* flag that this is a continuation line */
+
+      /* trim trailing white space before continuation character */
+      q = &p[len-2];
+      while (isspace(*q))
+        q--;
+      q++;
+      *q = 0;
+    }
+
+    rc = strlcat(buf, p, MAX_LINE_LEN);
+    if (rc >= MAX_LINE_LEN) {
+      fprintf(stderr, 
+              "%s: buffer length of %d exceed at line %d of \"%s\"\n",
+              progname, MAX_LINE_LEN, lineno, infile);
+      return -2;
+    }
+
+    if (cont)
+      continue;  /* continuation line, keep going */
+
+    /*
+     * read the configuration name from the beginning of the line
+     */
+    p = buf;
+    i = 0;
+    while (*p && (i < MAX_PIN_NAME) && (!(isspace(*p)||(*p == ':')))) {
+      configname[i++] = *p;
+      p++;
+    }
+    if (i == MAX_PIN_NAME) {
+      fprintf(stderr, "%s: configuration name too long at line %d of \"%s\"\n",
+              progname, lineno, infile);
+      return -3;
+    }
+    configname[i] = 0;
+
+    /*
+     * position 'p' to the beginning of the pin information
+     */
+    while (*p && (isspace(*p) || (*p == ':')))
+      p++;
+
+    if (strcasecmp(configname, config) == 0) {
+      rc = parse_config(lineno, infile, config, p, pinno, desc, desclen);
+      if (rc) {
+        fprintf(stderr, "%s: error parsing config file \"%s\" at line %d\n",
+                progname, infile, lineno);
+        return -3;
+      }
+
+      return 0;
+    }
+
+    buf[0] = 0;
+  }
+
+  /*
+   * config entry not found
+   */
+
+  fprintf(stderr, "%s: config entry \"%s\" not found in file \"%s\"\n",
+          progname, config, infile);
+
+  return -5;
+}
+
+
+
+
+void pinconfig_display(char * p, char * config, char * desc)
+{
+  fprintf(stderr, "%sProgrammer Pin Configuration: %s (%s)\n", p, 
+          config ? config : "DEFAULT", desc);
+  fprintf(stderr, 
+          "%s  VCC     = 0x%02x\n"
+          "%s  BUFF    = %d\n"
+          "%s  RESET   = %d\n"
+          "%s  SCK     = %d\n"
+          "%s  MOSI    = %d\n"
+          "%s  MISO    = %d\n"
+          "%s  ERR LED = %d\n"
+          "%s  RDY LED = %d\n"
+          "%s  PGM LED = %d\n"
+          "%s  VFY LED = %d\n",
+          p, pinno[PPI_AVR_VCC],
+          p, pinno[PIN_AVR_BUFF],
+          p, pinno[PIN_AVR_RESET],
+          p, pinno[PIN_AVR_SCK],
+          p, pinno[PIN_AVR_MOSI],
+          p, pinno[PIN_AVR_MISO],
+          p, pinno[PIN_LED_ERR],
+          p, pinno[PIN_LED_RDY],
+          p, pinno[PIN_LED_PGM],
+          p, pinno[PIN_LED_VFY]);
+}
+
+
+
+void verify_pin_assigned(int pin, char * desc)
+{
+  if (pinno[pin] == 0) {
+    fprintf(stderr, "%s: error: no pin has been assigned for %s\n",
+            progname, desc);
+    exit(1);
+  }
+}
+
+    
+
+#define MAX_DESC_LEN 80
+
 /*
  * main routine
  */
@@ -279,6 +608,9 @@ int main ( int argc, char * argv [] )
   int              ppidata;	/* cached value of the ppi data register */
   int              vsize=-1;    /* number of bytes to verify */
   char             timestamp[64];
+  char             configfile[PATH_MAX]; /* pin configuration file */
+  char *           pinconfig;
+  char             desc[MAX_DESC_LEN];
 
   /* options / operating mode variables */
   int     memtype;     /* AVR_FLASH or AVR_EEPROM */
@@ -295,20 +627,46 @@ int main ( int argc, char * argv [] )
   int     ppisetbits;  /* bits to set in ppi data register at exit */
   int     ppiclrbits;  /* bits to clear in ppi data register at exit */
 
-  readorwrite = 0;
-  parallel    = DEFAULT_PARALLEL;
-  outputf     = NULL;
-  inputf      = NULL;
-  doread      = 1;
-  memtype     = AVR_FLASH;
-  erase       = 0;
-  p           = NULL;
-  ovsigck     = 0;
-  terminal = 0;
-  filefmt     = FMT_AUTO;
-  nowrite     = 0;
-  verify      = 1;        /* on by default; XXX can't turn it off */
-  ppisetbits  = ppiclrbits = 0;
+  readorwrite   = 0;
+  parallel      = DEFAULT_PARALLEL;
+  outputf       = NULL;
+  inputf        = NULL;
+  doread        = 1;
+  memtype       = AVR_FLASH;
+  erase         = 0;
+  p             = NULL;
+  ovsigck       = 0;
+  terminal      = 0;
+  filefmt       = FMT_AUTO;
+  nowrite       = 0;
+  verify        = 1;        /* on by default; XXX can't turn it off */
+  ppisetbits    = ppiclrbits = 0;
+  pinconfig     = NULL;
+
+  strcpy(configfile, CONFIG_DIR);
+  i = strlen(configfile);
+  if (i && (configfile[i-1] != '/'))
+    strcat(configfile, "/");
+  strcat(configfile, "avrprog.conf");
+
+  for (i=0; i<N_PINS; i++)
+    pinno[i] = 0;
+
+  /*
+   * default pin configuration
+   */
+  pinno[PPI_AVR_VCC]   = 0x0f;  /* ppi pins 2-5, data reg bits 0-3 */
+  pinno[PIN_AVR_BUFF]  =  0;
+  pinno[PIN_AVR_RESET] =  7;
+  pinno[PIN_AVR_SCK]   =  8;
+  pinno[PIN_AVR_MOSI]  =  9;
+  pinno[PIN_AVR_MISO]  = 10;
+  pinno[PIN_LED_ERR]   =  0;
+  pinno[PIN_LED_RDY]   =  0;
+  pinno[PIN_LED_PGM]   =  0;
+  pinno[PIN_LED_VFY]   =  0;
+
+  strcpy(desc, "compiled in default");
 
   progname = rindex(argv[0],'/');
   if (progname)
@@ -343,9 +701,18 @@ int main ( int argc, char * argv [] )
   /*
    * process command line arguments
    */
-  while ((ch = getopt(argc,argv,"?eE:f:Fi:m:no:p:P:tV")) != -1) {
+  while ((ch = getopt(argc,argv,"?c:C:eE:f:Fi:m:no:p:P:tV")) != -1) {
 
     switch (ch) {
+      case 'c': /* pin configuration */
+        pinconfig = optarg;
+        break;
+
+      case 'C': /* pin configuration file */
+        strncpy(configfile, optarg, PATH_MAX);
+        configfile[PATH_MAX-1] = 0;
+        break;
+
       case 'm': /* select memory type to operate on */
         if ((strcasecmp(optarg,"e")==0)||(strcasecmp(optarg,"eeprom")==0)) {
           memtype = AVR_EEPROM;
@@ -482,6 +849,19 @@ int main ( int argc, char * argv [] )
     return 1;
   }
 
+  /*
+   * read the parallel port pin configuration to use if requested
+   */
+  if (pinconfig != NULL) {
+    rc = read_config(configfile, pinconfig, pinno, desc, MAX_DESC_LEN);
+    if (rc) {
+      fprintf(stderr, "%s: error reading \"%s\" configuration from \"%s\"\n",
+              progname, pinconfig, configfile);
+      exit(1);
+    }
+  }
+
+
   /* 
    * set up seperate instances of the avr part, one for use in
    * programming, one for use in verifying.  These are separate
@@ -497,9 +877,17 @@ int main ( int argc, char * argv [] )
   avr_initmem(v);
 
   avr_display(stderr, p, progbuf);
+#if 1
+  pinconfig_display(progbuf, pinconfig, desc);
+#endif
 
   fprintf(stderr, "\n");
 
+  verify_pin_assigned(PIN_AVR_RESET, "AVR RESET");
+  verify_pin_assigned(PIN_AVR_SCK,   "AVR SCK");
+  verify_pin_assigned(PIN_AVR_MISO,  "AVR MISO");
+  verify_pin_assigned(PIN_AVR_MOSI,  "AVR MOSI");
+
   /*
    * open the parallel port
    */
@@ -529,15 +917,15 @@ int main ( int argc, char * argv [] )
   /* 
    * turn off all the status leds
    */
-  LED_OFF(fd, PIN_LED_RDY);
-  LED_OFF(fd, PIN_LED_ERR);
-  LED_OFF(fd, PIN_LED_PGM);
-  LED_OFF(fd, PIN_LED_VFY);
+  LED_OFF(fd, pinno[PIN_LED_RDY]);
+  LED_OFF(fd, pinno[PIN_LED_ERR]);
+  LED_OFF(fd, pinno[PIN_LED_PGM]);
+  LED_OFF(fd, pinno[PIN_LED_VFY]);
 
   /*
    * enable the 74367 buffer, if connected; this signal is active low
    */
-  ppi_setpin(fd, PIN_AVR_BUFF, 0);
+  ppi_setpin(fd, pinno[PIN_AVR_BUFF], 0);
 
   /*
    * initialize the chip in preperation for accepting commands
@@ -550,7 +938,7 @@ int main ( int argc, char * argv [] )
   }
 
   /* indicate ready */
-  LED_ON(fd, PIN_LED_RDY);
+  LED_ON(fd, pinno[PIN_LED_RDY]);
 
   fprintf ( stderr, 
             "%s: AVR device initialized and ready to accept instructions\n",
@@ -692,7 +1080,7 @@ int main ( int argc, char * argv [] )
      * verify that the in memory file (p->mem[AVR_FLASH|AVR_EEPROM])
      * is the same as what is on the chip 
      */
-    LED_ON(fd, PIN_LED_VFY);
+    LED_ON(fd, pinno[PIN_LED_VFY]);
 
     fprintf(stderr, "%s: verifying %s memory against %s:\n", 
             progname, avr_memtstr(memtype), inputf);
@@ -702,7 +1090,7 @@ int main ( int argc, char * argv [] )
     if (rc < 0) {
       fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", 
               progname, avr_memtstr(memtype), rc);
-      LED_ON(fd, PIN_LED_ERR);
+      LED_ON(fd, pinno[PIN_LED_ERR]);
       exitrc = 1;
       goto main_exit;
     }
@@ -712,7 +1100,7 @@ int main ( int argc, char * argv [] )
     if (rc < 0) {
       fprintf(stderr, "%s: verification error; content mismatch\n", 
               progname);
-      LED_ON(fd, PIN_LED_ERR);
+      LED_ON(fd, pinno[PIN_LED_ERR]);
       exitrc = 1;
       goto main_exit;
     }
@@ -720,7 +1108,7 @@ int main ( int argc, char * argv [] )
     fprintf(stderr, "%s: %d bytes of %s verified\n", 
             progname, rc, avr_memtstr(memtype));
 
-    LED_OFF(fd, PIN_LED_VFY);
+    LED_OFF(fd, pinno[PIN_LED_VFY]);
   }
 
 
@@ -737,9 +1125,9 @@ int main ( int argc, char * argv [] )
   /*
    * disable the 74367 buffer, if connected; this signal is active low 
    */
-  ppi_setpin(fd, PIN_AVR_BUFF, 1);
+  ppi_setpin(fd, pinno[PIN_AVR_BUFF], 1);
 
-  LED_OFF(fd, PIN_LED_RDY);
+  LED_OFF(fd, pinno[PIN_LED_RDY]);
 
   close(fd);
 
diff --git a/pindefs.h b/pindefs.h
index 10c60309..f41e1021 100644
--- a/pindefs.h
+++ b/pindefs.h
@@ -32,6 +32,24 @@
 #ifndef __pindefs_h__
 #define __pindefs_h__
 
+#if 1
+enum {
+  PPI_AVR_VCC=1,
+  PIN_AVR_BUFF,
+  PIN_AVR_RESET,
+  PIN_AVR_SCK,
+  PIN_AVR_MOSI,
+  PIN_AVR_MISO,
+  PIN_LED_ERR,
+  PIN_LED_RDY,
+  PIN_LED_PGM,
+  PIN_LED_VFY,
+  N_PINS
+};
+
+extern unsigned int pinno[N_PINS];
+
+#else
 #define PPI_AVR_VCC    0x0f  /* ppi pins 2-5, data reg bits 0-3 */
 #define PIN_AVR_BUFF   6
 #define PIN_AVR_RESET  7
@@ -42,6 +60,7 @@
 #define PIN_LED_RDY   14
 #define PIN_LED_PGM   16
 #define PIN_LED_VFY   17
+#endif
 
 #define LED_ON(fd,pin)  ppi_setpin(fd,pin,0)
 #define LED_OFF(fd,pin) ppi_setpin(fd,pin,1)
diff --git a/term.c b/term.c
index 80cc8008..b6ae24f4 100644
--- a/term.c
+++ b/term.c
@@ -355,7 +355,7 @@ int cmd_write ( int fd, struct avrpart * p, int argc, char * argv[] )
     }
   }
 
-  LED_OFF(fd, PIN_LED_ERR);
+  LED_OFF(fd, pinno[PIN_LED_ERR]);
   for (werror=0, i=0; i<len; i++) {
     rc = avr_write_byte(fd, p, memtype, addr+i, buf[i]);
     if (rc) {
@@ -364,7 +364,7 @@ int cmd_write ( int fd, struct avrpart * p, int argc, char * argv[] )
       werror = 1;
     }
     if (werror) {
-      LED_ON(fd, PIN_LED_ERR);
+      LED_ON(fd, pinno[PIN_LED_ERR]);
     }
   }