[net.emacs] Emacs 17.49

rms@prep.AI.MIT.EDU (02/13/86)

From: rms@prep.AI.MIT.EDU (Richard M. Stallman)
Emacs 17.49 is now available in the usual places.
The differences are small, so here they are.
Note that if you copied 17.49 on Tuesday afternoon or evening,
it might have been missing one change, the addition of the semicolon
after the asm in crt0.c.  Please check.


Differences for GNU Emacs 17.49, from 17.48.

This set of diffs contains one complete replacement file, followed by
a small amount of differences for files in subdirectories etc, lisp
and src.  Remember that Lisp files must be recompiled with M-x
byte-recompile-directory in order for changes to take effect.

========================================Replacement file etc/fakemail.c
/* sendmail-like interface to /bin/mail for system V,
   Copyright (C) 1985 Free Software Foundation, Inc.

This file is part of GNU Emacs.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.  No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing.  Refer to the GNU Emacs General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
GNU Emacs, but only under the conditions described in the
GNU Emacs General Public License.   A copy of this license is
supposed to have been given to you along with GNU Emacs so you
can know your rights and responsibilities.  It should be in a
file named COPYING.  Among other things, the copyright notice
and this notice must be preserved on all copies.  */


#define NO_SHORTNAMES
#include "../src/config.h"

#ifdef BSD
/* This program isnot used in BSD, so just avoid loader complaints.  */
main ()
{
}
#else /* not BSD */
/* This conditional contains all the rest of the file.  */

/* These are defined in config in some versions. */

#ifdef static
#undef static
#endif

#ifdef read
#undef read
#undef write
#undef open
#endif

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <pwd.h>

/* Type definitions */

#define boolean int
#define true 1
#define false 0

/* Various lists */

struct line_record
{
  char *string;
  struct line_record *continuation;
};
typedef struct line_record *line_list;

struct header_record
{
  line_list text;
  struct header_record *next;
  struct header_record *previous;
};
typedef struct header_record *header;
			
struct stream_record
{
  FILE *handle;
  int (*action)();
  struct stream_record *rest_streams;
};
typedef struct stream_record *stream_list;

/* A `struct linebuffer' is a structure which holds a line of text.
 * `readline' reads a line from a stream into a linebuffer
 * and works regardless of the length of the line.
 */

struct linebuffer
{
  long size;
  char *buffer;
};

struct linebuffer lb;

#define alloc_a_list()					\
  ((line_list) xmalloc (sizeof (struct line_record)))
#define alloc_a_header()				\
  ((header) xmalloc (sizeof (struct header_record)))
#define alloc_a_stream()				\
  ((stream_list) xmalloc (sizeof (struct stream_record)))
#define alloc_a_string(nchars)				\
  ((char *) xmalloc ((nchars) + 1))

/* Global declarations */

#define BUFLEN 1024
#define KEYWORD_SIZE 256
#define PROGRAM_NAME "/bin/mail"
#define FROM_PREFIX "From"
#define MY_NAME "fakemail"
#define NIL ((line_list) NULL)
#define INITIAL_LINE_SIZE 200

static char *my_name;
static char *the_date;
static char *the_user;
static line_list file_preface;
static stream_list the_streams;
static boolean no_problems = true;

extern FILE *popen ();
extern int fclose (), pclose ();
extern char *malloc (), *realloc ();

#ifdef CURRENT_USER
extern struct passwd *getpwuid ();
extern unsigned short geteuid ();
static struct passwd *my_entry;
#define cuserid(s)				\
(my_entry = getpwuid (((int) geteuid ())),	\
 my_entry->pw_name)
#endif

/* Utilities */

/* Print error message.  `s1' is printf control string, `s2' is arg for it. */

static void
error (s1, s2)
     char *s1, *s2;
{
  printf ("%s: ", my_name);
  printf (s1, s2);
  printf ("\n");
  no_problems = false;
}

/* Print error message and exit.  */

static void
fatal (s1, s2)
     char *s1, *s2;
{
  error (s1, s2);
  exit (1);
}

/* Like malloc but get fatal error if memory is exhausted.  */

static char *
xmalloc (size)
     int size;
{
  char *result = malloc (((unsigned) size));
  if (result == ((char *) NULL))
    fatal ("virtual memory exhausted", 0);
  return result;
}

static char *
xrealloc (ptr, size)
     char *ptr;
     int size;
{
  char *result = realloc (ptr, ((unsigned) size));
  if (result == ((char *) NULL))
    fatal ("virtual memory exhausted");
  return result;
}

/* Initialize a linebuffer for use */

void
init_linebuffer (linebuffer)
     struct linebuffer *linebuffer;
{
  linebuffer->size = INITIAL_LINE_SIZE;
  linebuffer->buffer = ((char *) xmalloc (INITIAL_LINE_SIZE));
}

/* Read a line of text from `stream' into `linebuffer'.
 * Return the length of the line.  
 */

long
readline (linebuffer, stream)
     struct linebuffer *linebuffer;
     FILE *stream;
{
  char *buffer = linebuffer->buffer;
  char *p = linebuffer->buffer;
  char *end = p + linebuffer->size;

  while (true)
    {
      int c = getc (stream);
      if (p == end)
	{
	  linebuffer->size *= 2;
	  buffer = ((char *) xrealloc (buffer, linebuffer->size));
	  p += buffer - linebuffer->buffer;
	  end += buffer - linebuffer->buffer;
	  linebuffer->buffer = buffer;
	}
      if (c < 0 || c == '\n')
	{
	  *p = 0;
	  break;
	}
      *p++ = c;
    }

  return p - buffer;
}

char *
get_keyword (field, rest)
     register char *field;
     char **rest;
{
  static char keyword[KEYWORD_SIZE];
  register char *ptr;
  register char c;

  ptr = &keyword[0];
  c = *field++;
  if ((isspace (c)) || (c == ':'))
    return ((char *) NULL);
  *ptr++ = ((islower (c)) ? (toupper (c)) : c);
  while (((c = *field++) != ':') && (!(isspace (c))))
    *ptr++ = ((islower (c)) ? (toupper (c)) : c);
  *ptr++ = '\0';
  while (isspace (c)) c = *field++;
  if (c != ':') return ((char *) NULL);
  *rest = field;
  return &keyword[0];
}

boolean
has_keyword (field)
     char *field;
{
  char *ignored;
  return (get_keyword (field, &ignored) != ((char *) NULL));
}

char *
add_field (the_list, field, where)
     line_list the_list;
     register char *field, *where;
{
  register char c;
  while (true)
    {
      *where++ = ' ';
      while ((c = *field++) != '\0')
	*where++ = ((c == ',') ? ' ' : c);
      if (the_list == NIL) break;
      field = the_list->string;
      the_list = the_list->continuation;
    }
  return where;
}

line_list
make_file_preface ()
{
  char *the_string, *temp;
  long idiotic_interface;
  long prefix_length;
  long user_length;
  long date_length;
  line_list result;

  prefix_length = strlen (FROM_PREFIX);
  time (&idiotic_interface);
  the_date = ctime (&idiotic_interface);
  /* the_date has an unwanted newline at the end */
  date_length = strlen (the_date) - 1;
  the_date[date_length] = '\0';
  temp = cuserid ((char *) NULL);
  user_length = strlen (temp);
  the_user = alloc_a_string (user_length + 1);
  strcpy (the_user, temp);
  the_string = alloc_a_string (3 + prefix_length +
			      user_length +
			      date_length);
  temp = the_string;
  strcpy (temp, FROM_PREFIX);
  temp = &temp[prefix_length];
  *temp++ = ' ';
  strcpy (temp, the_user);
  temp = &temp[user_length];
  *temp++ = ' ';
  strcpy (temp, the_date);
  result = alloc_a_list ();
  result->string = the_string;
  result->continuation = ((line_list) NULL);
  return result;
}

void
write_line_list (the_list, the_stream)
     register line_list the_list;
     FILE *the_stream;
{
  for ( ;
      the_list != ((line_list) NULL) ;
      the_list = the_list->continuation)
    {
      fputs (the_list->string, the_stream);
      putc ('\n', the_stream);
    }
  return;
}

int
close_the_streams ()
{
  register stream_list rem;
  for (rem = the_streams;
       rem != ((stream_list) NULL);
       rem = rem->rest_streams)
    no_problems = (no_problems &&
		   (rem->action (rem->handle) == 0));
  the_streams = ((stream_list) NULL);
  return (no_problems ? 0 : 1);
}

void
add_a_stream (the_stream, closing_action)
     FILE *the_stream;
     int (*closing_action)();
{
  stream_list old = the_streams;
  the_streams = alloc_a_stream ();
  the_streams->handle = the_stream;
  the_streams->action = closing_action;
  the_streams->rest_streams = old;
  return;
}

int
my_fclose (the_file)
     FILE *the_file;
{
  putc ('\n', the_file);
  fflush (the_file);
  return fclose (the_file);
}

boolean
open_a_file (name)
     char *name;
{
  FILE *the_stream = fopen (name, "a");
  if (the_stream != ((FILE *) NULL))
    {
      add_a_stream (the_stream, my_fclose);
      if (the_user == ((char *) NULL))
	file_preface = make_file_preface ();
      write_line_list (file_preface, the_stream);
      return true;
    }
  return false;
}

void
put_string (s)
     char *s;
{
  register stream_list rem;
  for (rem = the_streams;
       rem != ((stream_list) NULL);
       rem = rem->rest_streams)
    fputs (s, rem->handle);
  return;
}

void
put_line (s)
     char *s;
{
  register stream_list rem;
  for (rem = the_streams;
       rem != ((stream_list) NULL);
       rem = rem->rest_streams)
    {
      fputs (s, rem->handle);
      putc ('\n', rem->handle);
    }
  return;
}

#define mail_error error

void
setup_files (the_list, field)
     register line_list the_list;
     register char *field;
{
  register char *start;
  register char c;
  while (true)
    {
      while (((c = *field) != '\0') &&
	     ((c == ' ') ||
	      (c == '\t') ||
	      (c == ',')))
	field += 1;
      if (c != '\0')
	{
	  start = field;
	  while (((c = *field) != '\0') &&
		 (c != ' ') &&
		 (c != '\t') &&
		 (c != ','))
	    field += 1;
	  *field = '\0';
	  if (!open_a_file (start))
	    mail_error ("Could not open file %s", start);
	  *field = c;
	  if (c != '\0') continue;
	}
      if (the_list == ((line_list) NULL)) return;
      field = the_list->string;
      the_list = the_list->continuation;
    }
}

int
args_size (the_header)
     header the_header;
{
  register header old = the_header;
  register line_list rem;
  register int size = 0;
  do
    {
      char *field;
      register char *keyword = get_keyword (the_header->text->string, &field);
      if ((strcmp (keyword, "TO") == 0) ||
	  (strcmp (keyword, "CC") == 0) ||
	  (strcmp (keyword, "BCC") == 0))
	{
	  size += 1 + strlen (field);
	  for (rem = the_header->text->continuation;
	       rem != NIL;
	       rem = rem->continuation)
	    size += 1 + strlen (rem->string);
	}
      the_header = the_header->next;
    } while (the_header != old);
  return size;
}

parse_header (the_header, where)
     header the_header;
     register char *where;
{
  register header old = the_header;
  do
    {
      char *field;
      register char *keyword = get_keyword (the_header->text->string, &field);
      if (strcmp (keyword, "TO") == 0)
	where = add_field (the_header->text->continuation, field, where);
      else if (strcmp (keyword, "CC") == 0)
	where = add_field (the_header->text->continuation, field, where);
      else if (strcmp (keyword, "BCC") == 0)
	{
	  where = add_field (the_header->text->continuation, field, where);
	  the_header->previous->next = the_header->next;
	  the_header->next->previous = the_header->previous;
	}
      else if (strcmp (keyword, "FCC") == 0)
	setup_files (the_header->text->continuation, field);
      the_header = the_header->next;
    } while (the_header != old);
  *where = '\0';
  return;
}
    
header
read_header ()
{
  register header the_header = ((header) NULL);
  register line_list *next_line = ((line_list *) NULL);

  init_linebuffer (&lb);

  do
    {
      long length;
      register char *line;

      readline (&lb, stdin);
      line = lb.buffer;
      length = strlen (line);
      if (length == 0) break;

      if (has_keyword (line))
	{
	  register header old = the_header;
	  the_header = alloc_a_header ();
	  if (old == ((header) NULL))
	    {
	      the_header->next = the_header;
	      the_header->previous = the_header;
	    }
	  else
	    {
	      the_header->previous = old;
	      the_header->next = old->next;
	      old->next = the_header;
	    }
	  next_line = &(the_header->text);
	}

      if (next_line == ((line_list *) NULL))
	{
	  /* Not a valid header */
	  exit (1);
	}
      *next_line = alloc_a_list ();
      (*next_line)->string = alloc_a_string (length);
      strcpy (((*next_line)->string), line);
      next_line = &((*next_line)->continuation);
      *next_line = NIL;

    } while (true);

  return the_header->next;
}

void
write_header (the_header)
     header the_header;
{
  register header old = the_header;
  do
    {
      register line_list the_list;
      for (the_list = the_header->text;
	   the_list != NIL;
	   the_list = the_list->continuation)
	put_line (the_list->string);
      the_header = the_header->next;
    } while (the_header != old);
  put_line ("");
  return;
}

void
main (argc, argv)
     int argc;
     char **argv;
{
  char *command_line;
  header the_header;
  long name_length = strlen (PROGRAM_NAME);
  char buf[BUFLEN + 1];
  register int size;
  FILE *the_pipe;

  my_name = MY_NAME;
  the_streams = ((stream_list) NULL);
  the_date = ((char *) NULL);
  the_user = ((char *) NULL);

  the_header = read_header ();
  command_line =
    ((char *) xmalloc (name_length + args_size (the_header)));
  strcpy (command_line, PROGRAM_NAME);
  parse_header (the_header, &command_line[name_length]);
  
  the_pipe = popen (command_line, "w");
  if (the_pipe == ((FILE *) NULL))
    fatal ("cannot open pipe to real mailer");

  add_a_stream (the_pipe, pclose);

  write_header (the_header);

  /* Dump the message itself */

  while (!feof (stdin))
    {
      size = fread (buf, 1, BUFLEN, stdin);
      buf[size] = '\0';
      put_string (buf);
    }

  exit (close_the_streams ());
}

#endif /* not BSD */
======================================================================
diff -rc2 odist48/etc/DISTRIB dist/etc/DISTRIB
*** odist48/etc/DISTRIB	Sun Feb  9 20:38:10 1986
--- dist/etc/DISTRIB	Tue Feb 11 15:38:17 1986
***************
*** 91,95
  			    February 6, 1986
  
! All software and publications are distributed with a permission to
  copy and redistribute.
  

--- 91,95 -----
  			    February 6, 1986
  
! All software and publications are distributed with permission to
  copy and redistribute.
  
diff -rc2 odist48/etc/MACHINES dist/etc/MACHINES
*** odist48/etc/MACHINES	Sun Feb  9 20:38:37 1986
--- dist/etc/MACHINES	Tue Feb 11 15:38:41 1986
***************
*** 66,70
  
    This port has been done but I have not received the diffs yet.
-   I expect that they will be included in 17.47.
  
  Celerity

--- 66,69 -----
  
    This port has been done but I have not received the diffs yet.
  
  Celerity
***************
*** 71,77
  
    17.36 has been ported, but I have not seen the port yet.
-   This distribution is likely to require some work to run.
-   You are advised to wait for the next one, which will probably
-   incorporate the port already done.
  
  Dual running System V (m-dual.h; s-usg5.2.h)

--- 70,73 -----
  
    17.36 has been ported, but I have not seen the port yet.
  
  Dual running System V (m-dual.h; s-usg5.2.h)
***************
*** 78,83
  
    As of 17.46, this works except for a few changes
!   needed in unexec.c.  These changes will be included
!   in 17.47.
  
  Dual running Uniplus (m-dual.h; s-unipl5.2.h)

--- 74,78 -----
  
    As of 17.46, this works except for a few changes
!   needed in unexec.c.
  
  Dual running Uniplus (m-dual.h; s-unipl5.2.h)
***************
*** 92,96
    this port.
  
! HP 9000s200 (m-hp200.h; s-hpux.h)
  
    Works.  This machine is a 68020.

--- 87,91 -----
    this port.
  
! HP 9000s300 (m-hp200.h; s-hpux.h)
  
    Works.  This machine is a 68020.
***************
*** 103,108
  Nu (TI or LMI) (m-nu.h; s-usg5.2.h)
  
!   Works modulo a few bugs that are being likely to be fixed
!   in a few days.
  
  Pyramid (m-pyramid.h; s-bsd4.2.h)

--- 98,102 -----
  Nu (TI or LMI) (m-nu.h; s-usg5.2.h)
  
!   Nearly working; a few bugs remain.
  
  Pyramid (m-pyramid.h; s-bsd4.2.h)
***************
*** 108,112
  Pyramid (m-pyramid.h; s-bsd4.2.h)
  
!   Works.
  
  Sequent Balance (m-sequent.h; s-bsd4.2.h)

--- 102,108 -----
  Pyramid (m-pyramid.h; s-bsd4.2.h)
  
!   Works.  Some versions of the pyramid compiler get fatal
!   errors when the -gx compiler switch is used; if this
!   happens to you, change src/ymakefile to remove that switch.
  
  Sequent Balance (m-sequent.h; s-bsd4.2.h)
***************
*** 112,119
  Sequent Balance (m-sequent.h; s-bsd4.2.h)
  
!   Emacs 17.47 works in their system (version 2.0)
!   except for their incompatible assembler syntax affecting alloca.s.
!   That problem is believed fixed in 17.48.
! 
    Emacs has not been tried on their system version 1.3.
  

--- 108,112 -----
  Sequent Balance (m-sequent.h; s-bsd4.2.h)
  
!   Emacs 17.48 works in their system version 2.0.
    Emacs has not been tried on their system version 1.3.
  
diff -rc2 odist48/lisp/ChangeLog dist/lisp/ChangeLog
*** odist48/lisp/ChangeLog	Sun Feb  9 02:39:38 1986
--- dist/lisp/ChangeLog	Mon Feb 10 22:17:06 1986
***************
*** 1,2
  Sun Feb  9 02:39:15 1986  Richard M. Stallman  (rms at prep)
  

--- 1,7 -----
+ Mon Feb 10 22:16:57 1986  Richard M. Stallman  (rms at prep)
+ 
+ 	* rmail.el (rmail-quit):
+ 	It was burying the wrong buffer.
+ 
  Sun Feb  9 02:39:15 1986  Richard M. Stallman  (rms at prep)
  
diff -rc2 odist48/lisp/rmail.el dist/lisp/rmail.el
*** odist48/lisp/rmail.el	Sun Feb  2 19:25:48 1986
--- dist/lisp/rmail.el	Mon Feb 10 22:16:52 1986
***************
*** 286,291
    (interactive)
    (rmail-save)
!   (switch-to-buffer (other-buffer))
!   (bury-buffer (current-buffer)))
  
  (defun rmail-input (filename)

--- 286,292 -----
    (interactive)
    (rmail-save)
!   (let ((obuf (current-buffer)))
!     (switch-to-buffer (other-buffer))
!     (bury-buffer obuf)))
  
  (defun rmail-input (filename)
diff -rc2 odist48/lisp/version.el dist/lisp/version.el
*** odist48/lisp/version.el	Sun Feb  9 20:40:25 1986
--- dist/lisp/version.el	Tue Feb 11 16:53:35 1986
***************
*** 22,26
  ;; The following line is modified automatically
  ;; by loading inc-version.el, each time a new Emacs is dumped.
! (defconst emacs-version "17.48.0"
    "Version numbers of this version of Emacs.")
  

--- 22,26 -----
  ;; The following line is modified automatically
  ;; by loading inc-version.el, each time a new Emacs is dumped.
! (defconst emacs-version "17.49.0"
    "Version numbers of this version of Emacs.")
  
diff -rc2 odist48/src/ChangeLog dist/src/ChangeLog
*** odist48/src/ChangeLog	Sun Feb  9 18:28:29 1986
--- dist/src/ChangeLog	Mon Feb 10 22:14:12 1986
***************
*** 1,2
  Fri Feb  7 01:12:35 1986  Richard M. Stallman  (rms at prep)
  

--- 1,6 -----
+ Mon Feb 10 22:13:58 1986  Richard M. Stallman  (rms at prep)
+ 
+ 	* crt0.c: Remove duplicate _start for pyramid.
+ 
  Fri Feb  7 01:12:35 1986  Richard M. Stallman  (rms at prep)
  
diff -rc2 odist48/src/crt0.c dist/src/crt0.c
*** odist48/src/crt0.c	Sun Feb  9 20:37:19 1986
--- dist/src/crt0.c	Tue Feb 11 18:01:07 1986
***************
*** 147,151
  
  /* Define symbol "start": here; some systems want that symbol.  */
! asm("	.text		")
  asm("	.globl start	");
  asm("	start:		");

--- 147,151 -----
  
  /* Define symbol "start": here; some systems want that symbol.  */
! asm("	.text		");
  asm("	.globl start	");
  asm("	start:		");
***************
*** 241,257
  
  #endif /* m68k or m68000 */
- 
- #ifdef pyramid
- 
- _start (argc, argv, envp)
-      int argc;
-      char **argv;
-      char **envp;
- {
-   environ = envp;
-   return main (argc, argv, envp);
- }
- 
- #endif /* pyramid */
  
  #ifdef hp9000s200

--- 241,244 -----
  
  #endif /* m68k or m68000 */
  
  #ifdef hp9000s200