All the changes between the last released version 0.1.1 and the most recent
code from sand.cvs.sourceforge.net.
--- ChangeLog.orig	2001-05-05 07:40:38.000000000 -0500
+++ ChangeLog	2001-12-25 14:43:10.000000000 -0600
@@ -1,3 +1,7 @@
+2001-12-25  Per Jonsson  <poj@users.sourceforge.net>
+
+	* sand: Fixed bug #232977
+
 2001-03-17  Per Jonsson	 <poj@users.sourceforge.net>
 
 	* sand: Fixed bug 
--- configure.in.orig	2001-05-05 07:40:39.000000000 -0500
+++ configure.in	2002-03-31 11:47:53.000000000 -0600
@@ -2,7 +2,7 @@
 
 AC_INIT(src/sand.c)
 dnl Every other copy of the package version number gets its value from here
-AM_INIT_AUTOMAKE(sand, 0.1.1)
+AM_INIT_AUTOMAKE(sand, 0.3)
 
 AC_SUBST(VERSION)
 
@@ -25,8 +25,11 @@
 
 dnl Checks for library functions.
 AC_REPLACE_FUNCS(getline)
-AC_CHECK_FUNCS(fgetln)
 
 AC_REPLACE_FUNCS(error)
 
+AC_REPLACE_FUNCS(strndup)
+
+AC_REPLACE_FUNCS(asprintf)
+
 AC_OUTPUT(Makefile src/Makefile doc/Makefile sand.lsm sand.spec)
--- doc/sand.1.orig	2001-05-05 08:09:10.000000000 -0500
+++ doc/sand.1	2002-10-16 13:44:14.000000000 -0500
@@ -13,7 +13,7 @@
 .\" along with this program; see the file COPYING.  If not, write to
 .\" the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 .\"
-.TH SAND 1 "May 5, 2001"
+.TH SAND 1 "June 14, 2002"
 .\" Please update the above date whenever this man page is modified.
 .\"
 .\" Some roff macros, for reference:
@@ -45,6 +45,10 @@
 .TP
 .B  \-n \fIID\fB, \-\-note\fR=\fIID
 Choose what note to output.
+This option implies \-\-output-text.
+.TP
+.B  \-l, \-\-list
+Lists all the notes in the diary for use with the \fB-n\fP option. 
 .TP
 .B  \-v, \-\-verbose
 Print more information.
--- doc/sand.texinfo.orig	2001-05-05 08:12:15.000000000 -0500
+++ doc/sand.texinfo	2002-10-16 13:44:15.000000000 -0500
@@ -6,12 +6,12 @@
 @setchapternewpage odd
 @c %**end of header
 
-@set VERSION 0.1.1
+@set VERSION 0.3.0
 
 @ifinfo
 This file documents the @code{sand} command which helps you keep your diary
 
-Copyright (C) 2001 Per Jonsson
+Copyright (C) 2001, 2002 Per Jonsson
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -44,7 +44,7 @@
 
 @page
 @vskip 0pt plus 1filll
-Copyright @copyright{} 2001 Per Jonsson
+Copyright @copyright{} 2001, 2002 Per Jonsson
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -58,7 +58,7 @@
 Permission is granted to copy and distribute translations of this manual
 into another language, under the above conditions for modified versions,
 except that this permission notice may be stated in a translation approved
-by the Foundation.
+by the Free Software Foundation.
 @end titlepage
 
 @c All the nodes can be updated using the EMACS command
@@ -135,6 +135,8 @@
                              only affects output modes
                              zero based
 
+  -l, --list                 displays a list of all notes in the diary
+
   -v, --verbose              print more information
   -h, --help                 display this help and exit
   -V, --version              output version information and exit
@@ -170,6 +172,11 @@
 @itemx -n @var{id}
 Choose note with number @var{id} as the note to output with
 @code{--output-text}
+This option also implies the @code{--output-text} option.
+
+@item --list
+@itemx -l
+Lists all the notes in the diary. 
 
 @item --verbose
 @itemx -V
@@ -188,8 +195,7 @@
 @node Known Problems, Problems, Invoking sand, Top
 @chapter Known Problems
 @cindex problems, known
-At the moment @code{sand} doesn't produce very much useful output,
-it just takes input and stores it.
+No great ones at the moment
 
 
 @node Problems, Concept Index, Known Problems, Top
--- src/Makefile.am.orig	2001-05-05 07:43:20.000000000 -0500
+++ src/Makefile.am	2002-02-08 14:44:23.000000000 -0600
@@ -1,10 +1,11 @@
 INCLUDES = -I$(top_srcdir)
 
+CFLAGS= @CFLAGS@ -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
+
 LDADD = @LIBOBJS@
 
 
 bin_PROGRAMS=sand
+sand_SOURCES=sand.c sand.h cli.c cli.h xmalloc.c system.h getopt.c getopt1.c getopt.h ddecode.c ddecode.h dencode.c output-diary.c output-text.c output.h repl_func.h extra.c mdiary.c mdiary.h
 
-sand_SOURCES=sand.c sand.h cli.c cli.h xmalloc.c system.h getopt.c getopt1.c getopt.h ddecode.c ddecode.h dencode.c output-diary.c output-text.c output.h repl_func.h extra.c
-
-EXTRA_DIST = getline.c error.c
+EXTRA_DIST = getline.c error.c strndup.c asprintf.c
--- src/asprintf.c.orig	1969-12-31 18:00:00.000000000 -0600
+++ src/asprintf.c	2002-07-12 15:27:10.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2001 Federico Di Gregorio <fog@debian.org> 
+ * Copyright (C) 1991, 1994-1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This code has been derived from an example in the glibc2 documentation.
+ * This file is part of the psycopg module.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * asprintf.c -- asprintf() implementation for braindamaged operating systems
+ * $Id: asprintf.c,v 1.1 2002/07/12 20:27:10 poj Exp $
+ */
+
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+int
+asprintf(char **buffer, char *fmt, ...)
+{
+    /* Guess we need no more than 200 chars of space. */
+    int size = 200;
+    int nchars;
+    va_list ap;
+    
+    *buffer = (char*)malloc(size);
+    if (*buffer == NULL) return -1;
+          
+    /* Try to print in the allocated space. */
+    va_start(ap, fmt);
+    nchars = vsnprintf(*buffer, size, fmt, ap);
+    va_end(ap);
+
+    if (nchars >= size)
+    {
+        char *tmpbuff;
+        /* Reallocate buffer now that we know how much space is needed. */
+        size = nchars+1;
+        tmpbuff = (char*)realloc(*buffer, size);
+        
+          
+        if (tmpbuff == NULL) { /* we need to free it*/
+            free(*buffer);
+            return -1;
+        }
+        
+        *buffer=tmpbuff;
+        /* Try again. */
+        va_start(ap, fmt);
+        nchars = vsnprintf(*buffer, size, fmt, ap);
+        va_end(ap);
+    }
+
+    if (nchars < 0) return nchars;
+    return size;
+}
--- src/cli.c.orig	2001-03-16 09:47:58.000000000 -0600
+++ src/cli.c	2002-07-12 15:27:10.000000000 -0500
@@ -29,26 +29,18 @@
 #include "output.h"
 #include "sand.h"
 
+
 /* cli_output - output of a text in cli mode*/
+/* MDIARY */
 void cli_output()
 {
+  mdiary d;
   dnote note;
-  dinfo diary;
 
-  /* Set it up for output */
-  input_diary(&diary);
-  if (ddecode_init(&diary)!= DIARY_IS)
-    {
-      message_err("Diary-file isn't a diary");
-      exit (EXIT_FAILURE);
-    }
-  note = ddecode_note(&diary, note_number);
+  d = init_mdiary_file(get_diary_file_name());
+  note = mdiary_note(&d, note_number);
   switch (note.length)
     {
-    case ERR_INV_FORMAT:
-      message_err("Your Diary is in a corrupt format.\nExiting...\n");
-      exit(EXIT_FAILURE);
-      break;
     case ERR_NO_SUCH_NOTE:
       message_err("The Note you request from the diary isn't available\n");
       message_err("Please try another\n");
@@ -59,44 +51,60 @@
     }
   out_text_fputnote(note, stdout);
   
-  free(diary.text);
 }
 
 /* cli_dump - handles the dumping in case of cli mode */
+/* MDIARY */
 void cli_dump()
 {
-  int j;
+  mdiary d;
   dnote note;
-  dinfo diary;
+  int nmbr = 0;
+  int cont = 1;
+
+  d = init_mdiary_file(get_diary_file_name());
 
-  /*  Set it up for dumping */
-  input_diary(&diary);
-  if (ddecode_init(&diary)!= DIARY_IS)
-    {
-      message_err("Diary-file isn't a diary");
-      exit (EXIT_FAILURE);
-    }
-  
-  j = 0;
   do {
-    note = ddecode_note_next(&diary);
+    note = mdiary_note(&d, nmbr);
     switch (note.length)
       {
-      case ERR_INV_FORMAT:
-	message_err("Your Diary is in a corrupt format.\nExiting...\n");
-	exit(EXIT_FAILURE);
-	break;
       case ERR_NO_SUCH_NOTE:
-	j = ERR_NO_SUCH_NOTE;
+	cont = 0;
 	break;
       default:
 	out_text_fputnote(note, stdout);
 	break;
       }
-  } while (j != ERR_NO_SUCH_NOTE);
-  
-  free(diary.text);
-  
+    nmbr++;
+  } while (cont == 1);
+
+}
+
+/* cli_list - lists the notes in the diary */
+/* MDIARY */
+void cli_list()
+{
+  mdiary d;
+  dnote note;
+  int nmbr = 0;
+  int cont = 1;
+
+  d = init_mdiary_file(get_diary_file_name());
+
+  do {
+    note = mdiary_note(&d, nmbr);
+    switch (note.length)
+      {
+      case ERR_NO_SUCH_NOTE:
+	cont = 0;
+	break;
+      default:
+        out_text_fputsummary(note, stdout, nmbr);
+	break;
+      }
+    nmbr++;
+  } while (cont == 1);
+
 }
 
 /* cli_input - handles the input case of cli mode*/
@@ -246,7 +254,7 @@
 
 }
 
-
+/* cli_getline - specialized getline variant */
 ssize_t cli_getline(char **LINEPTR, size_t *N, FILE *STREAM)
 {
   ssize_t char_read;
@@ -272,3 +280,37 @@
   return char_read;
 }
 
+/* cli_main - main when compiled in cli mode */
+int cli_main(int argc, char **argv)
+{
+  int i,j;
+  unsigned char status;
+
+  program_name = argv[0];
+
+  i = decode_switches (argc, argv);
+
+  /* Set up some configuration parsing */
+  status = sand_config();
+
+  if (want_output_text){
+    cli_output();
+  } else if (want_dump_text){
+    cli_dump();
+  } else if (want_list) {
+    cli_list();
+  } else if (want_note) {
+    message_ver("Got note parameter but no output option. Defaulting to output-text\n",1);
+    cli_output();
+  } else {
+    /* Normal input loop */
+    cli_input(status);
+  }
+
+  exit (0);
+
+}
+
+
+
+
--- src/cli.h.orig	2001-03-11 13:38:24.000000000 -0600
+++ src/cli.h	2001-12-17 13:21:56.000000000 -0600
@@ -28,4 +28,6 @@
 void cli_dump();
 void cli_input(int status);
 
+int cli_main(int argc, char **argv);
+
 #endif
--- src/ddecode.c.orig	2001-05-05 07:40:42.000000000 -0500
+++ src/ddecode.c	2001-12-17 13:21:56.000000000 -0600
@@ -56,20 +56,20 @@
 }
 
 /* ddecode_find_tag searches for a tag in the diary */
-int ddecode_find_tag(const dinfo d, const char * t)
+int ddecode_find_tag(dinfo * d, const char * t)
 {
   int i,j,f;
 
   f = strlen(t);
 
   /* Loop to find <note> */
-  for (i = 0; i < (d.length - d.position - f); i++)
+  for (i = 0; i < (d->length - d->position - f); i++)
     {
       j=-1;
-      if (strncasecmp ((d.text + (d.position+i)), t ,f ) == 0)
+      if (strncasecmp ((d->text + (d->position+i)), t ,f ) == 0)
 	{
 	  j = i;
-	  i = d.length;
+	  i = d->length;
 	}
     }
   return j;
@@ -97,7 +97,7 @@
   /* Search for the note:th <note> tag */
   for (i=0; i <= note; i++)
     {
-      j=ddecode_find_tag(*d, "<note>");
+      j=ddecode_find_tag(d, "<note>");
       d->position += ((j>0)?(j+6):(0));
     }
 
@@ -110,7 +110,7 @@
     }
   
   /* Find the date */
-  date_pos = ddecode_find_tag(*d,"<date>");
+  date_pos = ddecode_find_tag(d,"<date>");
   if ( date_pos == -1)
     {
       d_note.length = ERR_INV_FORMAT;
@@ -119,7 +119,7 @@
     }
 
   /* Find end of date information */
-  j = ddecode_find_tag(*d,"</date>");
+  j = ddecode_find_tag(d,"</date>");
   if ( j == -1)
     {
       d_note.length = ERR_INV_FORMAT;
@@ -128,7 +128,7 @@
     }
 
   /* Decode the date */
-  if (ddecode_date(*d, &d_note, date_pos, j - date_pos)== -1)
+  if (ddecode_date(d, &d_note, date_pos, j - date_pos)!= DATE_OK)
     {
       d_note.length = ERR_INV_FORMAT;
       d->position = pos;
@@ -136,11 +136,11 @@
     }
 
   /* Locate the title of the not if there is one */
-  title_start = ddecode_find_tag(*d,"<title>");
+  title_start = ddecode_find_tag(d,"<title>");
   if ( title_start != -1)
     {
       /* If the title is opened, an end is required. */
-      title_end = ddecode_find_tag(*d,"</title>");
+      title_end = ddecode_find_tag(d,"</title>");
       if ( title_end == -1)
 	{
 	  d_note.length = ERR_INV_FORMAT;
@@ -153,7 +153,7 @@
     }
 
   /* Find the position of the body */
-  j = ddecode_find_tag(*d,"<body>");
+  j = ddecode_find_tag(d,"<body>");
   if ( j == -1)
     {
       d_note.length = ERR_INV_FORMAT;
@@ -163,7 +163,7 @@
   d->position += j + 6;
 
   /* Find the end of the body */
-  d_note.length = ddecode_find_tag(*d,"</body>");
+  d_note.length = ddecode_find_tag(d,"</body>");
   if ( d_note.length == -1)
     {
       d_note.length == ERR_INV_FORMAT;
@@ -172,7 +172,7 @@
     }
 
   /* Find the end of note tag */
-  j = ddecode_find_tag(*d,"</note>");
+  j = ddecode_find_tag(d,"</note>");
   if ( j == -1)
     {
       d_note.length = ERR_INV_FORMAT;
@@ -187,7 +187,7 @@
   if ((d->position > title_start) && (title_end > 0))
     {
       /* Now, Lets take care of the title */
-      d_note.title = strndup((d->text + title_start + strlen("<title>")), 
+      d_note.title = (char*)strndup((d->text + title_start + strlen("<title>")), 
 			     title_end);
     } else {
       d_note.title = (char *) NULL;
@@ -198,23 +198,26 @@
 
 
 /* ddecode_date decodes the date */
-int ddecode_date(const dinfo d, dnote * n, int p, int e)
+int ddecode_date(dinfo * d, dnote * n, int p, int e)
 {
   char bck[5];
   char * temp;
+  char * ltemp;
   int p_org = p;
   int i = 0;
 
-  while (isspace (d.text[p + d.position + 6]))
+  ltemp = (char *)strndup((d->text + d->position), (e + 1));
+
+  while (isspace (ltemp[p + 6]))
       p++;
 
-  bck[0] = d.text[p_org + d.position + e];
-  d.text[p_org + d.position + e] = '\0';
-  bck[1] = d.text[p_org + d.position + e - 1];
+  bck[0] = ltemp[p_org + e];
+  ltemp[p_org + e] = '\0';
+  bck[1] = ltemp[p_org + e - 1];
   if (!isdigit(bck[1]))
-    d.text[p_org + d.position + e - 1] = '\0';
+    ltemp[p_org + e - 1] = '\0';
 
-  temp = d.text + p + d.position + 6;
+  temp = ltemp + p + 6;
 
   /* YEAR */
   if (isdigit(temp[0]) && isdigit(temp[1]) &&
@@ -223,8 +226,7 @@
       bck[2] = temp[4];
       temp[4] = '\0';
     } else {
-      d.text[p_org + d.position + e] = bck[0];
-      d.text[p_org + d.position + e - 1] = bck[1];
+      free (ltemp);
       return ERR_INV_FORMAT;
     }
 
@@ -240,8 +242,7 @@
       bck[2] = temp[2];
       temp[2] = '\0';
     } else {
-      d.text[p_org + d.position + e] = bck[0];
-      d.text[p_org + d.position + e - 1] = bck[1];
+      free (ltemp);
       return ERR_INV_FORMAT;
     }
   
@@ -260,8 +261,7 @@
       bck[2] = temp[2];
       temp[2] = '\0';
     } else {
-      d.text[p_org + d.position + e] = bck[0];
-      d.text[p_org + d.position + e - 1] = bck[1];
+      free (ltemp);
       return ERR_INV_FORMAT;
     }
   
@@ -292,8 +292,7 @@
       temp[5] = '\0';
       temp[8] = '\0';
     } else {
-      d.text[p_org + d.position + e] = bck[0];
-      d.text[p_org + d.position + e - 1] = bck[1];
+      free (ltemp);
       return ERR_INV_FORMAT;
     }
   
@@ -318,9 +317,8 @@
   temp[5] = bck[3];
   temp[8] = bck[4];
 
-  d.text[p_org + d.position + e] = bck[0];
-  d.text[p_org + d.position + e - 1] = bck[1];
 
+  free (ltemp);
   return DATE_OK;
 }
 
--- src/ddecode.h.orig	2001-05-05 07:40:42.000000000 -0500
+++ src/ddecode.h	2001-12-17 13:21:56.000000000 -0600
@@ -26,6 +26,7 @@
 
 typedef struct diary_base{
   size_t length;
+  int fd;
   int position;
   char * text;
 } dinfo;
@@ -61,7 +62,7 @@
 dnote ddecode_note(dinfo * d, int note);
 dnote ddecode_note_next(dinfo * d);
 int ddecode_init(dinfo * diary);
-int ddecode_date(const dinfo  d, dnote * n, int p, int e);
+int ddecode_date(dinfo * d, dnote * n, int p, int e);
 
 dtime time_t2dtime(time_t t);
 
--- src/getline.c.orig	2001-03-17 12:48:34.000000000 -0600
+++ src/getline.c	2002-02-08 14:44:23.000000000 -0600
@@ -1,50 +1,143 @@
-/* 
-   getline.c - Replacement for getline 
+/* getline.c -- Replacement for GNU C library function getline
 
-   Copyright (C) 2001 Per Jonsson
+Copyright (C) 1993 Free Software Foundation, Inc.
 
-   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.
-
-   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.  
-*/
+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.
 
-#include <stdio.h>
-#include "repl_func.h"
+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.  */
+
+/* Written by Jan Brittenson, bson@gnu.ai.mit.edu.  */
 
-char *xmalloc ();
-char *xrealloc ();
-char *xstrdup ();
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
-ssize_t
-getline_fgetln (char **lineptr, size_t *n, FILE *stream)
+#include <sys/types.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#else
+char *malloc (), *realloc ();
+#endif
+
+/* Always add at least this many bytes when extending the buffer.  */
+#define MIN_CHUNK 64
+
+/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
+   + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from
+   malloc (or NULL), pointing to *N characters of space.  It is realloc'd
+   as necessary.  Return the number of characters read (not including the
+   null terminator), or -1 on error or EOF.  On a -1 return, the caller
+   should check feof(), if not then errno has been set to indicate
+   the error.  */
+
+int getstr (lineptr, n, stream, terminator, offset)
+     char **lineptr;
+     size_t *n;
+     FILE *stream;
+     char terminator;
+     int offset;
 {
-  char *line;
-  size_t len;
-  
-  line = fgetln(stream, &len);
-  if (!line)
-    return -1;
-  if (len >= *n) {
-    char *tmp;
-    
-    /* XXX some realloc() implementations don`t set errno */
-    tmp = realloc(*lineptr, len + 1);
-    if (!tmp)
+  int nchars_avail;		/* Allocated but unused chars in *LINEPTR.  */
+  char *read_pos;		/* Where we're reading into *LINEPTR. */
+  int ret;
+
+  if (!lineptr || !n || !stream)
+    {
+      errno = EINVAL;
       return -1;
-    *lineptr = tmp;
-    *n = len + 1;
-  }
-  memcpy(*lineptr, line, len);
-  (*lineptr)[len] = 0;
-  return len;
+    }
+
+  if (!*lineptr)
+    {
+      *n = MIN_CHUNK;
+      *lineptr = malloc (*n);
+      if (!*lineptr)
+	{
+	  errno = ENOMEM;
+	  return -1;
+	}
+    }
+
+  nchars_avail = *n - offset;
+  read_pos = *lineptr + offset;
+
+  for (;;)
+    {
+      int save_errno;
+      register int c = getc (stream);
+
+      save_errno = errno;
+
+      /* We always want at least one char left in the buffer, since we
+	 always (unless we get an error while reading the first char)
+	 NUL-terminate the line buffer.  */
+
+      assert((*lineptr + *n) == (read_pos + nchars_avail));
+      if (nchars_avail < 2)
+	{
+	  if (*n > MIN_CHUNK)
+	    *n *= 2;
+	  else
+	    *n += MIN_CHUNK;
+
+	  nchars_avail = *n + *lineptr - read_pos;
+	  *lineptr = realloc (*lineptr, *n);
+	  if (!*lineptr)
+	    {
+	      errno = ENOMEM;
+	      return -1;
+	    }
+	  read_pos = *n - nchars_avail + *lineptr;
+	  assert((*lineptr + *n) == (read_pos + nchars_avail));
+	}
+
+      if (ferror (stream))
+	{
+	  /* Might like to return partial line, but there is no
+	     place for us to store errno.  And we don't want to just
+	     lose errno.  */
+	  errno = save_errno;
+	  return -1;
+	}
+
+      if (c == EOF)
+	{
+	  /* Return partial line, if any.  */
+	  if (read_pos == *lineptr)
+	    return -1;
+	  else
+	    break;
+	}
+
+      *read_pos++ = c;
+      nchars_avail--;
+
+      if (c == terminator)
+	/* Return the line.  */
+	break;
+    }
+
+  /* Done - NUL terminate and return the number of chars read.  */
+  *read_pos = '\0';
+
+  ret = read_pos - (*lineptr + offset);
+  return ret;
+}
+
+int getline (lineptr, n, stream)
+     char **lineptr;
+     size_t *n;
+     FILE *stream;
+{
+  return getstr (lineptr, n, stream, '\n', 0);
 }
--- src/mdiary.c.orig	1969-12-31 18:00:00.000000000 -0600
+++ src/mdiary.c	2002-03-31 11:47:53.000000000 -0600
@@ -0,0 +1,192 @@
+/* 
+   sand - helps you keep your diary
+   
+   mdiary.c - handles diary in memory 
+
+   Copyright (C) 2001 Per Jonsson
+
+   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.
+
+   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.  
+
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include "system.h"
+#include "ddecode.h"
+#include "output.h"
+#include "sand.h"
+#include "mdiary.h"
+
+/* input_diary_generic - reads an entire diary into memory */
+dinfo * input_diary_generic(dinfo * diary_ret, char * s)
+{
+  int diary = 0; /* fd to  diary */
+  char * diary_p = (char *)NULL; /* PATH to diary */
+  char * temp = (char *)NULL;
+  int diarylen = 0;              /* Misc uses concerning length of diary */
+  ssize_t nc = (ssize_t) 0;
+  size_t length = 0;
+  size_t diary_size = (size_t) 0;
+  struct stat dstat;
+ 
+  diary_ret->text = (char*) NULL;
+  diary_ret->length = 0;
+  diary_ret->position = 0;
+
+  /* Open the file for reading */
+  diary = open(s, O_RDONLY);
+
+  diary_ret->fd = diary;
+  /* Do some error checking on the FILE * */ 
+  if (diary == (int)NULL)
+    {
+
+      if (errno == EINVAL){
+	/* The system isn't handling my mode, exiting */
+	perror("sand");
+	exit (EXIT_FAILURE);
+      }
+      
+      /* Something else is wrong, exit */
+      perror("sand");
+      exit(EXIT_FAILURE);
+    }
+
+  if (fstat(diary, &dstat) == -1)
+    {
+      message_err("BAAAD failure when doing fstat on diary\n");
+      perror("sand");
+      exit(EXIT_FAILURE);
+    }
+
+  diary_ret->text = mmap (NULL, dstat.st_size, PROT_READ,  MAP_SHARED, diary,0);
+
+  length = dstat.st_size;
+  if (diary_ret->text == (char *)-1)
+    {
+      /* Oops, the memorymapping failed */
+      message_err("BAAD failure when mmaping\n");
+      perror("sand");
+      exit(EXIT_FAILURE);
+    }
+
+  diary_ret->length = length;
+
+  return diary_ret;
+}
+
+/* init_mdiary_file - initializes a mdiary from a file, populates node list */
+mdiary init_mdiary_file(char * s)
+{
+  mdiary ret;
+  mnote_list * cur;
+  mnote_list * latest;
+  FILE * d;
+  dinfo t_diary;
+  int dsize = 0;
+  int nc = 0;
+  int cont = 1;
+
+  input_diary_generic(&t_diary, s); 
+
+  if ( ddecode_init(&t_diary) != DIARY_IS)
+    {
+      message_err("I haven't got a diary.\nExiting\n");
+      fclose (d);
+      exit (EXIT_FAILURE); /* Escape from the program */
+    }
+
+  ret.first = (mnote_list*)xmalloc(sizeof(mnote_list));
+  ret.first->next = (mnote_list*)NULL;
+  
+  cur = ret.first;
+  cur->next = ret.first;
+
+  latest = cur;
+
+  do {
+    cur->next->d = ddecode_note(&t_diary, DIARY_NEXT_NOTE);
+    latest = cur;
+    cur = cur->next;
+    
+    cur->next =  (mnote_list*)xmalloc(sizeof(mnote_list));
+    cur->next->next = (mnote_list*)NULL;
+    if(cur->d.length == ERR_NO_SUCH_NOTE) {
+      cont = 0;
+    } else if (cur->d.length == ERR_INV_FORMAT) {
+      message_err("Invalid diary format\n");
+      fclose (d);
+      exit (EXIT_FAILURE); /* Escape from the program */
+    }
+  } while (cont);
+
+  free(cur->next);
+  if (cur != latest )
+    free(latest->next);
+  latest->next = (mnote_list*)NULL;
+
+  /*close_diary(&t_diary); */
+
+  return ret;
+}
+
+/* close_diary - close a dinfo diary */
+void close_diary (dinfo * d)
+{
+  munmap(d->text, d->length);
+  close(d->fd);
+
+  memset(&d, '\0', sizeof(dinfo));
+} 
+
+/* mdiary_note - returns a specific note in the mdiary */
+dnote mdiary_note(mdiary * d, int number)
+{
+  dnote n;
+  mnote_list * cur;
+
+  memset(&n, '\0', sizeof(n));
+
+  cur = d->first;
+  
+  do {
+    if((number == 0) || (cur->next == (mnote_list *)NULL))
+      {
+	if (number == 0)
+	  {
+	    n = cur->d;
+	  } else {
+	    n.length = ERR_NO_SUCH_NOTE;
+	    number = 0;
+	  }
+      } else {
+	cur = cur->next;
+      }
+    number--;
+  } while ( number  >= 0); 
+      
+
+  return n;
+}
+
+
+
+
+
--- src/mdiary.h.orig	1969-12-31 18:00:00.000000000 -0600
+++ src/mdiary.h	2001-12-25 07:09:42.000000000 -0600
@@ -0,0 +1,46 @@
+/* 
+   sand - helps you keep your diary
+   
+   mdiary.h - handles diary in memory 
+
+   Copyright (C) 2001 Per Jonsson
+
+   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.
+
+   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.  
+
+*/
+
+#ifndef __SAND__MDIARY_H__
+#define __SAND__MDIARY_H__
+#include "ddecode.h"
+
+typedef struct diary_note_list{
+  dnote d;
+  struct diary_note_list * next;
+} mnote_list;
+  
+typedef struct diary_mem{
+  FILE * fd;
+  mnote_list * first;
+} mdiary;
+
+
+dinfo * input_diary_generic(dinfo * diary_ret, char * s);
+mdiary init_mdiary_file(char * s);
+dnote mdiary_note(mdiary * d, int number);
+
+
+#endif
+
+
--- src/output-text.c.orig	2001-05-05 07:40:44.000000000 -0500
+++ src/output-text.c	2001-12-25 12:59:32.000000000 -0600
@@ -63,3 +63,27 @@
   fprintf(to, "\n\n");
 
 }
+
+
+/* out_text_fputsummary - outputs note summary in plain text format to file */ 
+int out_text_fputsummary(dnote d, FILE * to, int id)
+{
+  int j;
+  char * date;
+  
+  date = dencode_date(d);
+  j = strlen(date);
+
+  fprintf(to, "%5i ", id); 
+
+  fprintf(to, "%s   ",date);
+
+  if (d.title != (char *) NULL)
+    {
+      j = strlen(d.title);
+      fprintf(to, "%s",d.title);
+    }
+
+  fprintf(to, "\n");
+
+}
--- src/output.h.orig	2001-05-05 07:32:03.000000000 -0500
+++ src/output.h	2001-12-25 12:59:32.000000000 -0600
@@ -29,5 +29,6 @@
 int out_diary_special_fputnote(dnote d, FILE * to, FILE * source);
 
 int out_text_fputnote(dnote d, FILE * to);
+int out_text_fputsummary(dnote d, FILE * to, int id);
 
 #endif
--- src/repl_func.h.orig	2001-03-17 12:48:34.000000000 -0600
+++ src/repl_func.h	2002-02-08 14:44:23.000000000 -0600
@@ -24,10 +24,7 @@
 
 /* getline */
 #ifndef HAVE_GETLINE
-#ifdef HAVE_FGETLN
-#define getline_fgetln getline 
-ssize_t getline_fgetln (char **lineptr, size_t *n, FILE *stream);
-#endif
+int getline (char **lineptr, size_t n, FILE * stream);
 #endif
 
 /* error */
@@ -37,4 +34,9 @@
 #include <error.h>
 #endif
 
+
+/* strndup */
+#ifndef HAVE_STRNDUP
+char * strndup(const char * s, size_t n);
+#endif
 #endif
--- src/sand.c.orig	2001-05-05 07:40:47.000000000 -0500
+++ src/sand.c	2001-12-25 12:59:32.000000000 -0600
@@ -25,6 +25,7 @@
 */
 
 #define __SAND_C__SAND__
+#define SAND_CLI
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -71,37 +72,19 @@
   {NULL, 0, NULL, 0}
 };
 
-static int decode_switches (int argc, char **argv);
 
 int
 main (int argc, char **argv)
 {
-  int i,j;
-  unsigned char status;
-
-  program_name = argv[0];
-
-  i = decode_switches (argc, argv);
-
-  /* Set up some configuration parsing */
-  status = sand_config();
-
-  if (want_output_text){
-    cli_output();
-  } else if (want_dump_text){
-    cli_dump();
-  } else {
-    /* Normal input loop */
-    cli_input(status);
-  }
-
-  exit (0);
+#ifdef SAND_CLI
+  cli_main(argc, argv);
+#endif
 }
 
 /* Set all the option flags according to the switches specified.
    Return the index of the first non-option argument.  */
 
-static int
+int
 decode_switches (int argc, char **argv)
 {
   int c;
@@ -167,6 +150,8 @@
                              only affects output modes\n\
                              zero based\n\
 \n\
+  -l, --list                 displays a list of all notes in the diary\n\
+\n\
   -v, --verbose              print more information\n\
   -h, --help                 display this help and exit\n\
   -V, --version              output version information and exit\n\
@@ -185,74 +170,6 @@
   return 0;
 }
 
-
-/* input_diary - reads an entire diary into memory */
-dinfo * input_diary(dinfo * diary_ret)
-{
-  FILE * diary = (FILE *) NULL;  /* FILE * to diary */
-  char * diary_p = (char *)NULL; /* PATH to diary */
-  char * temp = (char *)NULL;
-  int diarylen = 0;              /* Misc uses concerning length of diary */
-  ssize_t nc = (ssize_t) 0;
-  size_t length = 0;
-  size_t diary_size = (size_t) 0;
- 
-  diary_ret->text = (char*) NULL;
-  diary_ret->length = 0;
-  diary_ret->position = 0;
-
-  /* Open the file for reading */
-  diary = fopen(get_diary_file_name(), "r");
-
-  /* Do some error checking on the FILE * */ 
-  if (diary == NULL)
-    {
-
-      if (errno == EINVAL){
-	/* The system isn't handling my mode, exiting */
-	perror("sand");
-	exit (EXIT_FAILURE);
-      }
-      
-      /* Something else is wrong, exit */
-      perror("sand");
-      exit(EXIT_FAILURE);
-    }
-
-  /* Loop until the whole diary is read */
-  do {
-
-    /* Read the line */
-    nc = getline( &diary_p, &diary_size, diary);
-    
-    /* If char_read == -1 then we probabably have read until EOF */
-    if (nc == -1)
-      {
-	if (!feof(diary))         /* Everything that is error except */
-	  {                       /* EOF is evil */
-	    message_err("Evil input from diary file\nExiting....\n");
-	    fclose (diary);
-	    exit (EXIT_FAILURE); /* Escape from the program */
-	  } 
-      } else {
-	temp = xrealloc(temp, length + nc + 1);
-	diary_ret->text = temp;
-
-	temp = temp + length;
-	memcpy(temp, diary_p, nc);
-
-	length += nc;
-	temp = diary_ret->text;
-      }
-  } while ( nc != -1 );
-  
-  diary_ret->length = length;
-
-  fclose(diary);
-  return diary_ret;
-}
-
-
 /* get_diary_file_name - returns the filename of the diary */
 char * get_diary_file_name()
 {
--- src/sand.h.orig	2001-03-16 09:52:07.000000000 -0600
+++ src/sand.h	2002-02-08 14:44:23.000000000 -0600
@@ -32,6 +32,7 @@
 #include "ddecode.h"
 #include "output.h"
 #include "cli.h"
+#include "mdiary.h"
 
 #define EXIT_OK 0
 #define EXIT_FAILURE 1
@@ -48,6 +49,7 @@
 
 void message_ver (char * msg, int msg_mode);
 static void message (char * msg) { message_ver(msg, 0);}
+static void vmessage (char * msg) { message_ver(msg, 1);}
 void message_err (char * msg);
 
 unsigned char sand_config();
@@ -56,9 +58,17 @@
 void   get_create_rc_dir();
 char * get_diary_file_name();
 
-dinfo * input_diary(dinfo *diary_ret);
 FILE * open_diary(int mode);
 int dump_file(FILE * from, FILE * to);
+void close_diary (dinfo * d);
+
+int decode_switches (int argc, char **argv);
+
+/* input_diary - wrapper to handle old style behaviour of input_diary */
+static inline dinfo * input_diary(dinfo * diary_ret)
+{
+  return input_diary_generic(diary_ret, get_diary_file_name());
+}
 
 #ifndef __SAND_C__SAND__
 /* The name the program was run with, stripped of any leading path. */
@@ -70,10 +80,11 @@
 /* The program home dir */
 extern char *program_home;
 
-extern int want_verbose;		/* --verbose */
+extern int want_verbose;	       /* --verbose */
 extern int want_output_text;           /* --output-text */
 extern int want_dump_text;             /* --dump-text */
 extern int want_note;                  /* --note */
+extern int want_list;                  /* --list */
 extern int note_number;
 #endif
 
--- src/strndup.c.orig	1969-12-31 18:00:00.000000000 -0600
+++ src/strndup.c	2002-02-08 14:44:23.000000000 -0600
@@ -0,0 +1,42 @@
+/* 
+   strndup.c - Replacement for strndup 
+
+   Copyright (C) 2001 Stefan Kost
+   Copyright (C) 2001 Per Jonsson
+
+   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.
+
+   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.  
+*/
+
+#include <stdio.h>
+#include "repl_func.h"
+
+char *xmalloc ();
+char *xrealloc ();
+char *xstrdup ();
+
+char * strndup(const char * s, size_t n)
+{
+  char *d;
+  if(strlen(s)<n)
+    {
+      d=xstrdup(s);
+    } else {
+      d=xmalloc(n+1);
+      strncpy(d,s,n+1);
+      d[n]='\0';
+    }
+  return(d);
+}
+
