[405] in Release_7.7_team

home help back first fref pref prev next nref lref last post

patches for emacs19 to coexist with emacs18

daemon@ATHENA.MIT.EDU (brlewis@MIT.EDU)
Sat Dec 30 15:31:22 1995

From: brlewis@MIT.EDU
Date: Sat, 30 Dec 95 15:31:10 -0500
To: release-team@MIT.EDU, rel-eng@MIT.EDU

There are no internal references to emacsclient; it is only invoked by
the user.  We will need to tell people that when they try emacs19, they
will need to set EDITOR to emacs19client in .environment and .mh_profile
instead of emacsclient.

The ctags/etags programs are forward/backward compatible, except that
etags from emacs19 has fewer bugs.

On Solaris, emacsclient wouldn't work in 19.28, so I upgraded
emacsclient.c and emacsserver.c to 19.30.  I changed the Makefile to
install emacs19client and, if no emacsclient exists, make it a symlink.
This should allow coexistence with emacs18 if 18 is compiled first.

I tested on rsaix, decmips, sun4 and sgi that emacs started up, and
emacsclient worked.

The patches below can be applied in /source/third/supported/emacs-19.28
_______________________________________________________________________________

*** 1.1	1995/12/27 20:30:42
--- lib-src/Makefile.in.in	1995/12/30 15:16:41
***************
*** 84,90 ****
  
  # Things that a user might actually run,
  # which should be installed in bindir.
! INSTALLABLES = etags ctags emacsclient b2m
  INSTALLABLE_SCRIPTS = rcs-checkin
  
  # Things that Emacs runs internally, or during the build process,
--- 84,91 ----
  
  # Things that a user might actually run,
  # which should be installed in bindir.
! EMACSCLIENT = emacs19client
! INSTALLABLES = etags ctags ${EMACSCLIENT} b2m
  INSTALLABLE_SCRIPTS = rcs-checkin
  
  # Things that Emacs runs internally, or during the build process,
***************
*** 215,220 ****
--- 216,224 ----
  	for file in ${INSTALLABLES} ; do \
  	  (cd ..; $(INSTALL_PROGRAM) lib-src/$${file} ${DESTDIR}${bindir}/$${file}) ; \
  	done
+ 	if [ ! -f ${DESTDIR}${bindir}/emacsclient ]; then \
+ 	  (cd ${DESTDIR}${bindir}; ln -s ${EMACSCLIENT} emacsclient) ; \
+ 	fi
  	for file in ${INSTALLABLE_SCRIPTS} ; do \
  	  (cd ..; $(INSTALL_PROGRAM) ${srcdir}/$${file} ${DESTDIR}${bindir}/$${file}) ; \
  	done
***************
*** 312,319 ****
  emacsserver: ${srcdir}/emacsserver.c ../src/config.h
  	$(CC) ${ALL_CFLAGS} ${srcdir}/emacsserver.c $(LOADLIBES) -o emacsserver
  
! emacsclient: ${srcdir}/emacsclient.c ../src/config.h
! 	$(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c $(LOADLIBES) -o emacsclient
  
  hexl: ${srcdir}/hexl.c
  	$(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o hexl
--- 316,323 ----
  emacsserver: ${srcdir}/emacsserver.c ../src/config.h
  	$(CC) ${ALL_CFLAGS} ${srcdir}/emacsserver.c $(LOADLIBES) -o emacsserver
  
! ${EMACSCLIENT}: ${srcdir}/emacsclient.c ../src/config.h
! 	$(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c $(LOADLIBES) -o ${EMACSCLIENT}
  
  hexl: ${srcdir}/hexl.c
  	$(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o hexl
_______________________________________________________________________________

*** 1.1	1995/12/27 16:53:29
--- lib-src/emacsclient.c	1995/12/30 15:07:28
***************
*** 26,39 ****
  #undef close
  #undef signal
  
- #ifdef sun
- #undef SERVER_HOME_DIR
- #else
- #undef HAVE_SYSVIPC
- #define HAVE_SOCKETS
- #endif
  
! #if !defined(HAVE_SOCKETS) && !defined(HAVE_SYSVIPC)
  #include <stdio.h>
  
  main (argc, argv)
--- 26,33 ----
  #undef close
  #undef signal
  
  
! #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
  #include <stdio.h>
  
  main (argc, argv)
***************
*** 48,54 ****
  
  #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
  
! #if ! defined (HAVE_SYSVIPC)
  /* BSD code is very different from SYSV IPC code */
  
  #include <sys/types.h>
--- 42,48 ----
  
  #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
  
! #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
  /* BSD code is very different from SYSV IPC code */
  
  #include <sys/types.h>
***************
*** 61,66 ****
--- 55,61 ----
  extern char *strerror ();
  extern int errno;
  
+ int
  main (argc, argv)
       int argc;
       char **argv;
***************
*** 73,78 ****
--- 68,74 ----
    char string[BUFSIZ];
  
    char *getenv (), *getwd ();
+   char *getcwd ();
    int geteuid ();
  
    if (argc < 2)
***************
*** 97,116 ****
      struct stat statbfr;
  
      gethostname (system_name, sizeof (system_name));
!     sprintf (server.sun_path, "/tmp/esrv%d", geteuid ());
  
      if (stat (server.sun_path, &statbfr) == -1)
        {
  	if (errno == ENOENT)
  	  fprintf (stderr,
! 		   "Can't find socket; have you started the server?\n");
  	else
! 	  perror ("stat");
  	exit (1);
        }
!     if (statbfr.st_uid != geteuid())
        {
! 	fprintf (stderr, "Illegal socket owner\n");
  	exit (1);
        }
    }
--- 93,114 ----
      struct stat statbfr;
  
      gethostname (system_name, sizeof (system_name));
!     sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
  
      if (stat (server.sun_path, &statbfr) == -1)
        {
  	if (errno == ENOENT)
  	  fprintf (stderr,
! 		   "%s: can't find socket; have you started the server?\n",
! 		   argv[0]);
  	else
! 	  fprintf (stderr, "%s: can't stat %s: %s\n",
! 		   argv[0], server.sun_path, strerror (errno));
  	exit (1);
        }
!     if (statbfr.st_uid != geteuid ())
        {
! 	fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
  	exit (1);
        }
    }
***************
*** 121,127 ****
        exit (1);
      }
    strcpy (server.sun_path, homedir);
!   strcat (server.sun_path, "/.emacs_server");
  #endif
  
    if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
--- 119,127 ----
        exit (1);
      }
    strcpy (server.sun_path, homedir);
!   strcat (server.sun_path, "/.emacs-server-");
!   gethostname (system_name, sizeof (system_name));
!   strcat (server.sun_path, system_name);
  #endif
  
    if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
***************
*** 138,144 ****
--- 138,148 ----
        exit (1);
      }
  
+ #ifdef BSD
    cwd = getwd (string);
+ #else
+   cwd = getcwd (string, sizeof string);
+ #endif
    if (cwd == 0)
      {
        /* getwd puts message in STRING if it fails.  */
***************
*** 173,179 ****
    while (str = fgets (string, BUFSIZ, out))
      printf ("%s", str);
    
!   exit (0);
  }
  
  #else /* This is the SYSV IPC section */
--- 177,183 ----
    while (str = fgets (string, BUFSIZ, out))
      printf ("%s", str);
    
!   return 0;
  }
  
  #else /* This is the SYSV IPC section */
***************
*** 181,194 ****
  #include <sys/types.h>
  #include <sys/ipc.h>
  #include <sys/msg.h>
  #include <stdio.h>
  
- #ifndef SERVER_HOME_DIR
- #include <sys/stat.h>
- #include <errno.h>
- #endif
- 
  char *getwd (), *getcwd (), *getenv ();
  
  main (argc, argv)
       int argc;
--- 185,195 ----
  #include <sys/types.h>
  #include <sys/ipc.h>
  #include <sys/msg.h>
+ #include <sys/utsname.h>
  #include <stdio.h>
  
  char *getwd (), *getcwd (), *getenv ();
+ struct utsname system_name;
  
  main (argc, argv)
       int argc;
***************
*** 214,243 ****
        fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
        exit (1);
      }
- #ifndef SERVER_HOME_DIR
-   {
-     struct stat statbfr;
  
-     sprintf (buf, "/tmp/esrv%d", geteuid ());
- 
-     if (stat (buf, &statbfr) == -1)
-       {
- 	if (errno == ENOENT)
- 	  fprintf (stderr,
- 		   "Can't find socket; have you started the server?\n");
- 	else
- 	  perror ("stat");
- 	exit (1);
-       }
-     if (statbfr.st_uid != geteuid())
-       {
- 	fprintf (stderr, "Illegal socket owner\n");
- 	exit (1);
-       }
-   }
- #else
    /*
!    * Create a message queue using ~/.emacs_server as the path for ftok
     */
    if ((homedir = getenv ("HOME")) == NULL)
      {
--- 215,223 ----
        fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]);
        exit (1);
      }
  
    /*
!    * Create a message queue using ~/.emacs-server as the path for ftok
     */
    if ((homedir = getenv ("HOME")) == NULL)
      {
***************
*** 245,251 ****
        exit (1);
      }
    strcpy (buf, homedir);
!   strcat (buf, "/.emacs_server");
  #endif
    creat (buf, 0600);
    key = ftok (buf, 1);	/* unlikely to be anyone else using it */
--- 225,237 ----
        exit (1);
      }
    strcpy (buf, homedir);
! #ifndef HAVE_LONG_FILE_NAMES
!   /* If file names are short, we can't fit the host name.  */
!   strcat (buf, "/.emacs-server");
! #else
!   strcat (buf, "/.emacs-server-");
!   uname (&system_name);
!   strcat (buf, system_name.nodename);
  #endif
    creat (buf, 0600);
    key = ftok (buf, 1);	/* unlikely to be anyone else using it */
***************
*** 275,281 ****
      }
    else
      {
!       fprintf (stderr, cwd);
        exit (1);
      }
  
--- 261,267 ----
      }
    else
      {
!       fprintf (stderr, "%s: %s\n", argv[0], cwd);
        exit (1);
      }
  
***************
*** 318,324 ****
  #ifdef HPUX /* HPUX has a bug.  */
    if (strlen (msgp->mtext) >= 512)
      {
!       fprintf (stderr, "emacsclient: args too long for msgsnd\n");
        exit (1);
      }
  #endif
--- 304,310 ----
  #ifdef HPUX /* HPUX has a bug.  */
    if (strlen (msgp->mtext) >= 512)
      {
!       fprintf (stderr, "%s: args too long for msgsnd\n", progname);
        exit (1);
      }
  #endif
_______________________________________________________________________________

*** 1.1	1995/12/30 15:07:02
--- lib-src/emacsserver.c	1995/12/30 15:07:29
***************
*** 1,5 ****
  /* Communication subprocess for GNU Emacs acting as server.
!    Copyright (C) 1986, 1987, 1992 Free Software Foundation, Inc.
  
  This file is part of GNU Emacs.
  
--- 1,5 ----
  /* Communication subprocess for GNU Emacs acting as server.
!    Copyright (C) 1986, 1987, 1992, 1994 Free Software Foundation, Inc.
  
  This file is part of GNU Emacs.
  
***************
*** 32,45 ****
  #undef close
  #undef signal
  
! #ifdef sun
! #undef SERVER_HOME_DIR
! #else
! #undef HAVE_SYSVIPC
! #define HAVE_SOCKETS
! #endif
! 
! #if !defined(HAVE_SOCKETS) && !defined(HAVE_SYSVIPC)
  #include <stdio.h>
  
  main ()
--- 32,38 ----
  #undef close
  #undef signal
  
! #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
  #include <stdio.h>
  
  main ()
***************
*** 51,57 ****
  
  #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
  
! #if ! defined (HAVE_SYSVIPC)
  /* BSD code is very different from SYSV IPC code */
  
  #include <sys/types.h>
--- 44,50 ----
  
  #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
  
! #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
  /* BSD code is very different from SYSV IPC code */
  
  #include <sys/types.h>
***************
*** 64,69 ****
--- 57,84 ----
  
  extern int errno;
  
+ /* Copied from src/process.c */
+ #ifdef FD_SET
+ /* We could get this from param.h, but better not to depend on finding that.
+    And better not to risk that it might define other symbols used in this
+    file.  */
+ #ifdef FD_SETSIZE
+ #define MAXDESC FD_SETSIZE
+ #else
+ #define MAXDESC 64
+ #endif
+ #define SELECT_TYPE fd_set
+ #else /* no FD_SET */
+ #define MAXDESC 32
+ #define SELECT_TYPE int
+ 
+ /* Define the macros to access a single-int bitmap of descriptors.  */
+ #define FD_SET(n, p) (*(p) |= (1 << (n)))
+ #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
+ #define FD_ISSET(n, p) (*(p) & (1 << (n)))
+ #define FD_ZERO(p) (*(p) = 0)
+ #endif /* no FD_SET */
+ 
  main ()
  {
    char system_name[32];
***************
*** 90,123 ****
  
    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
      {
!       perror ("socket");
        exit (1);
      }
    server.sun_family = AF_UNIX;
  #ifndef SERVER_HOME_DIR
    gethostname (system_name, sizeof (system_name));
!   sprintf (server.sun_path, "/tmp/esrv%d", geteuid ());
  
    if (unlink (server.sun_path) == -1 && errno != ENOENT)
      {
!       perror ("unlink");
        exit (1);
      }
  #else  
    if ((homedir = getenv ("HOME")) == NULL)
!     {
!       fprintf (stderr,"No home directory\n");
!       exit (1);
!     }
    strcpy (server.sun_path, homedir);
!   strcat (server.sun_path, "/.emacs_server");
    /* Delete anyone else's old server.  */
    unlink (server.sun_path);
  #endif
  
    if (bind (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) < 0)
      {
!       perror ("bind");
        exit (1);
      }
    /* Only this user can send commands to this Emacs.  */
--- 105,138 ----
  
    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
      {
!       perror_1 ("socket");
        exit (1);
      }
    server.sun_family = AF_UNIX;
  #ifndef SERVER_HOME_DIR
    gethostname (system_name, sizeof (system_name));
!   sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name);
  
    if (unlink (server.sun_path) == -1 && errno != ENOENT)
      {
!       perror_1 ("unlink");
        exit (1);
      }
  #else  
    if ((homedir = getenv ("HOME")) == NULL)
!     fatal_error ("No home directory\n");
! 
    strcpy (server.sun_path, homedir);
!   strcat (server.sun_path, "/.emacs-server-");
!   gethostname (system_name, sizeof (system_name));
!   strcat (server.sun_path, system_name);
    /* Delete anyone else's old server.  */
    unlink (server.sun_path);
  #endif
  
    if (bind (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) < 0)
      {
!       perror_1 ("bind");
        exit (1);
      }
    /* Only this user can send commands to this Emacs.  */
***************
*** 127,133 ****
     */
    if (listen (s, 5) < 0)
      {
!       perror ("listen");
        exit (1);
      }
  
--- 142,148 ----
     */
    if (listen (s, 5) < 0)
      {
!       perror_1 ("listen");
        exit (1);
      }
  
***************
*** 135,155 ****
    signal (SIGPIPE, SIG_IGN);
    for (;;)
      {
!       int rmask = (1 << s) + 1;
!       if (select (s + 1, (fd_set *)&rmask, 0, 0, 0) < 0)
! 	perror ("select");
!       if (rmask & (1 << s))	/* client sends list of filenames */
  	{
  	  fromlen = sizeof (fromunix);
  	  fromunix.sun_family = AF_UNIX;
! 	  infd = accept (s, (struct sockaddr *) &fromunix,
! 			 (size_t *) &fromlen);
  	  if (infd < 0)
  	    {
  	      if (errno == EMFILE || errno == ENFILE)
! 		printf ("Too many clients.\n");
  	      else
! 		perror ("accept");
  	      continue;
  	    }
  
--- 150,172 ----
    signal (SIGPIPE, SIG_IGN);
    for (;;)
      {
!       SELECT_TYPE rmask;
!       FD_ZERO (&rmask);
!       FD_SET (0, &rmask);
!       FD_SET (s, &rmask);
!       if (select (s + 1, &rmask, 0, 0, 0) < 0)
! 	perror_1 ("select");
!       if (FD_ISSET (s, &rmask))	/* client sends list of filenames */
  	{
  	  fromlen = sizeof (fromunix);
  	  fromunix.sun_family = AF_UNIX;
! 	  infd = accept (s, (struct sockaddr *) &fromunix, &fromlen);
  	  if (infd < 0)
  	    {
  	      if (errno == EMFILE || errno == ENFILE)
! 		fprintf (stderr, "Error: too many clients.\n");
  	      else
! 		perror_1 ("accept");
  	      continue;
  	    }
  
***************
*** 165,171 ****
  	  infile = fdopen (infd, "r+"); /* open stream */
  	  if (infile == NULL)
  	    {
! 	      printf ("Too many clients.\n");
  	      write (infd, "Too many clients.\n", 18);
  	      close (infd);		/* Prevent descriptor leak.. */
  	      continue;
--- 182,188 ----
  	  infile = fdopen (infd, "r+"); /* open stream */
  	  if (infile == NULL)
  	    {
! 	      fprintf (stderr, "Error: too many clients.\n");
  	      write (infd, "Too many clients.\n", 18);
  	      close (infd);		/* Prevent descriptor leak.. */
  	      continue;
***************
*** 173,179 ****
  	  str = fgets (string, BUFSIZ, infile);
  	  if (str == NULL)
  	    {
! 	      perror ("fgets");
  	      close (infd);		/* Prevent descriptor leak.. */
  	      continue;
  	    }
--- 190,196 ----
  	  str = fgets (string, BUFSIZ, infile);
  	  if (str == NULL)
  	    {
! 	      perror_1 ("fgets");
  	      close (infd);		/* Prevent descriptor leak.. */
  	      continue;
  	    }
***************
*** 192,207 ****
  	  fflush (infile);
  	  continue;
  	}
!       else if (rmask & 1) /* emacs sends codeword, fd, and string message */
  	{
  	  /* Read command codeword and fd */
  	  clearerr (stdin);
  	  scanf ("%s %d%*c", code, &infd);
  	  if (ferror (stdin) || feof (stdin))
! 	    {
! 	      fprintf (stderr, "server: error reading from standard input\n");
! 	      exit (1);
! 	    }
  
  	  /* Transfer text from Emacs to the client, up to a newline.  */
  	  infile = openfiles[infd];
--- 209,221 ----
  	  fflush (infile);
  	  continue;
  	}
!       else if (FD_ISSET (0, &rmask)) /* emacs sends codeword, fd, and string message */
  	{
  	  /* Read command codeword and fd */
  	  clearerr (stdin);
  	  scanf ("%s %d%*c", code, &infd);
  	  if (ferror (stdin) || feof (stdin))
! 	    fatal_error ("server: error reading from standard input\n");
  
  	  /* Transfer text from Emacs to the client, up to a newline.  */
  	  infile = openfiles[infd];
***************
*** 234,242 ****
  #include <sys/ipc.h>
  #include <sys/msg.h>
  #include <setjmp.h>
- 
- #ifndef SERVER_HOME_DIR
  #include <errno.h>
  #endif
  
  jmp_buf msgenv;
--- 248,260 ----
  #include <sys/ipc.h>
  #include <sys/msg.h>
  #include <setjmp.h>
  #include <errno.h>
+ #include <sys/utsname.h>
+ 
+ struct utsname system_name;
+ 
+ #ifndef errno
+ extern int errno;
  #endif
  
  jmp_buf msgenv;
***************
*** 265,296 ****
    char string[BUFSIZ];
    FILE *infile;
  
- #ifndef SERVER_HOME_DIR
-   sprintf (string, "/tmp/esrv%d", geteuid ());
- 
-   if (unlink (string) == -1 && errno != ENOENT)
-     {
-       perror ("unlink");
-       exit (1);
-     }
- #else
    /*
!    * Create a message queue using ~/.emacs_server as the path for ftok
     */
    if ((homedir = getenv ("HOME")) == NULL)
!     {
!       fprintf (stderr,"No home directory\n");
!       exit (1);
!     }
    strcpy (string, homedir);
!   strcat (string, "/.emacs_server");
  #endif
    creat (string, 0600);
    key = ftok (string, 1);	/* unlikely to be anyone else using it */
    s = msgget (key, 0600 | IPC_CREAT);
    if (s == -1)
      {
!       perror ("msgget");
        exit (1);
      }
  
--- 283,309 ----
    char string[BUFSIZ];
    FILE *infile;
  
    /*
!    * Create a message queue using ~/.emacs-server as the path for ftok
     */
    if ((homedir = getenv ("HOME")) == NULL)
!     fatal_error ("No home directory\n");
! 
    strcpy (string, homedir);
! #ifndef HAVE_LONG_FILE_NAMES
!   /* If file names are short, we can't fit the host name.  */
!   strcat (string, "/.emacs-server");
! #else
!   strcat (string, "/.emacs-server-");
!   uname (&system_name);
!   strcat (string, system_name.nodename);
  #endif
    creat (string, 0600);
    key = ftok (string, 1);	/* unlikely to be anyone else using it */
    s = msgget (key, 0600 | IPC_CREAT);
    if (s == -1)
      {
!       perror_1 ("msgget");
        exit (1);
      }
  
***************
*** 299,309 ****
    if (setjmp (msgenv))
      {
        msgctl (s, IPC_RMID, 0);
!       kill (p, SIGKILL);
        exit (0);
      }
    signal (SIGTERM, msgcatch);
    signal (SIGINT, msgcatch);
    if (p > 0)
      {
        /* This is executed in the original process that did the fork above.  */
--- 312,324 ----
    if (setjmp (msgenv))
      {
        msgctl (s, IPC_RMID, 0);
!       if (p > 0)
! 	kill (p, SIGKILL);
        exit (0);
      }
    signal (SIGTERM, msgcatch);
    signal (SIGINT, msgcatch);
+   signal (SIGHUP, msgcatch);
    if (p > 0)
      {
        /* This is executed in the original process that did the fork above.  */
***************
*** 345,351 ****
      {
        if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0)
          {
! 	  perror ("msgrcv");
  	  exit (1);
          }
        else
--- 360,370 ----
      {
        if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0)
          {
! #ifdef EINTR
! 	  if (errno == EINTR)
! 	    continue;
! #endif
! 	  perror_1 ("msgrcv");
  	  exit (1);
          }
        else
***************
*** 382,384 ****
--- 401,425 ----
  #endif /* HAVE_SYSVIPC */
  
  #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
+ 
+ /* This is like perror but puts `Error: ' at the beginning.  */
+ 
+ perror_1 (string)
+      char *string;
+ {
+   char *copy = (char *) malloc (strlen (string) + 8);
+   if (copy == 0)
+     fatal_error ("Virtual memory exhausted");
+ 
+   strcpy (copy, "Error: ");
+   strcat (copy, string);
+   perror (copy);
+ }
+ 
+ fatal_error (string)
+      char *string;
+ {
+   fprintf (stderr, "%s", "Error: ");
+   fprintf (stderr, string);
+   exit (1);
+ }

home help back first fref pref prev next nref lref last post