[net.sources] Simple 'input' editor...

taylor@hplabsc.UUCP (Dave Taylor) (09/17/86)

The following *very* simple program is a simple front end to programs
that invoke editors all over the place.  It's very fast and for probably
99% of what people use editors for, sufficiently powerful.

The main idea is to use this from within programs like PicoSpan and
various mail programs.  Again, speed is of the essence.

The program has been tested on BSD and System V machines, and, no
great suprise, works fine on both of them.  If you're on a BSD
machine you should compile it with the "-DBSD" option to have it
act friendly about job control interruptions.

	Feedback to me or to net.sources.d

						-- Dave Taylor
						taylor@hplabs.HP.COM

--
# Shell Archive created by hpldat!taylor at Tue Sep 16 16:52:18 1986

# To unpack the enclosed files, please use this file as input to the
# Bourne (sh) shell.  This can be most easily done by the command;
#     sh < thisfilename

# This archive contains;
#  src/editor.c     man/editor.1


if [ ! -d src ]
then
  echo creating directory src
  mkdir src
fi

# ---------- file src/editor.c ----------

filename="src/editor.c"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file src/editor.c...
fi

cat << 'END-OF-FILE' > $filename
/**				editor.c			**/

/** This is a very simple editor designed for general purpose use.
    
    This program is a sorta subset of the 'editor=none' option in the
    Elm program & the Berkeley mailer, etc, etc.

   (C) Copyright 1986, Dave Taylor
**/

#include <stdio.h>

#define  SLEN	100		/* length of a line of input */

#define  temp	"/tmp/pe"	/* temp file for pipe stuff  */
#define  SHELL	"sh"		/* default shell    	     */

#ifdef BSD
# include <signal.h>
#endif

char shell[SLEN]; 
char *getenv(), *strcpy();

main(argc, argv)
int argc;
char *argv[];
{
	/** assume we're invoked as "<editor> <filename>" **/
	FILE *fd;
	char buffer[SLEN];
#ifdef BSD
	int  dumb_continue();	/* says "(continue)" when return from ^Z */
#endif

	if (argc == 1) {
	  printf("Usage: %s filename\n", argv[0]);
	  exit(1);
	}

	if (access(argv[1], 00) != -1) {
	  printf("Refuse to edit an existing file!  Try a \"real\" editor!!\n");
	  exit(1);
	}

	if ((fd = fopen(argv[1], "w")) == NULL) {
	  printf("Can't open %s as the temp file!\n", argv[1]);
	  exit(1);
	}

	if (getenv("SHELL") != NULL)
	  strcpy(shell, getenv("SHELL"));
	else
	  strcpy(shell, SHELL);

	printf("Enter message, '^D' to end, or ~? for help;\n");

#ifdef BSD
	signal(SIGCONT, dumb_continue);
#endif

	while (gets(buffer) != NULL) {
	  if (strcmp(buffer, ".") == 0) break;	/* outta here! */
	  else if (buffer[0] == '~') {
	    switch (buffer[1]) {
	      case '\0' : printf("(Huh?  Try \"~?\" for help!)\n");	break;
	      case '?'  : help();					break;
	      case 'v'  : invoke("vi", fd, argv[1]);			break;
	      case 'e'  : invoke("emacs", fd, argv[1]);			break;
	      case 'o'  : invoke("", fd, argv[1]);			break;
	      case 'r'  : read_in(buffer, fd);         			break;
	      case 'w'  : write_out(buffer, fd, argv[1]);		break;
	      case 'p'  : fclose(fd);
		          fd = fopen(argv[1], "r");
			  while (fgets(buffer, SLEN, fd) != NULL)
	                    printf("%s", buffer);
		   	  printf("(continue)\n");
			  fd = fopen(argv[1], "a");			break;
	      case '!'  : if (strlen(buffer) > 2) 
			    system((char *) buffer + 2);
			  else
			    system(shell);				break;
	      case '|'  : pipe_it(buffer, fd, argv[1]);			break;
	      default   : printf("(don't know what \"~%c\" means!)\n", 
			  buffer[1]);
			  break;
	    }
	  }
	  else
	    fprintf(fd, "%s\n", buffer);
	}

	fclose(fd);
	
	exit(0);
}

#ifdef BSD

dumb_continue()
{
	/** just to make it all look nice.  We don't really DO much here! */

	signal(SIGCONT, dumb_continue);

	printf("(continue)\n");
}

#endif

help()
{
	/** list the possible commands! **/

	printf("(The commands available from here are;\n\
    ~?    list this help menu\n\
    ~!    either give you a shell, or execute the specified command\n\
    ~|    pipe the message written so far through the specified command\n\
    ~e    invoke \"emacs\" on the response so far\n\
    ~o    invoke the specified editor on the response\n\
    ~p    print what we've entered so far\n\
    ~r    read in the specified file\n\
    ~v    invoke \"vi\" on the response so far\n\
    ~w    write out the specified file\n\
\nto end the editor, use <control>-D or a '.' on a line by itself)\n");
}

invoke(editor, file_descriptor, filename)
char *editor, *filename;
FILE *file_descriptor;
{
	/** invokes the specified editor, closing the file and opening it
	    again when we're done.  If editor = NULL ask the user! **/

	char buffer[SLEN];

	if (strlen(editor) == 0) {
	  printf("Enter the name of the editor to use: ");
	  fflush(stdout);
	  gets(editor);
	  if (strlen(editor) == 0) goto end_it;
	}
	else {
	  printf("(invoking %s) ", editor);
	  fflush(stdout);
	}

	fclose(file_descriptor);

	sprintf(buffer, "%s %s", editor, filename);

	system(buffer);

	file_descriptor = fopen(filename, "a");

end_it:
	printf("(continue)\n");

	return;
}

pipe_it(command, file_descriptor, filename)
char *command, *filename;
FILE *file_descriptor;
{
	/** this will either accept a previously entered pipe command,
	    as in "~|fmt", or if none, will prompt for one.  It's really
	    quite a simple routine!
	**/

	char buffer[SLEN];

	fclose(file_descriptor);

	if (strlen(command) > 2) {
	  printf("(piping response through \"%s\")\n", 
		  (char *) command + 2);
	  sprintf(buffer, "cat %s | %s > %s.%d; mv %s.%d %s",
		  filename, (char *) command + 2, temp, getpid(),
		  temp, getpid(), filename);
	}
	else {
	  printf("Pipe message through: ");
	  fflush(stdout);
	  gets(command);
	  if (strlen(command) == 0) goto end_it;
	  sprintf(buffer, "cat %s | %s > %s.%d ; mv %s.%d %s",
		  filename, command, temp, getpid(),
		  temp, getpid(), filename);
	}
	
	system(buffer);

end_it:

	file_descriptor = fopen(filename, "a");

	printf("(continue)\n");

	return;
}

read_in(fname, fd)
char *fname;
FILE *fd;
{
	/** read the specified file in, continuing when done.  **/

	FILE     *newfd;
	register int i, j, lines = 0;
	char     filename[SLEN], buffer[SLEN];

	if (strlen(fname) < 3) {
	  printf("Enter name of file to read in: ");
	  gets(filename);
	  if (strlen(filename) == 0) goto end_it;
	}
	else {
	  for (i=2; fname[i] == ' '; i++) 
	    /* count up! */ ;
	  for (j = 0; i < strlen(fname);)
	    filename[j++] = fname[i++];
	  filename[j] = '\0';
	}

	if ((newfd = fopen(filename, "r")) == NULL) {
	  printf("(can't open file \"%s\" for reading!  Continue...)\n", 
		 filename);
	  return;
	}

	while (fgets(buffer, SLEN, newfd) != NULL) {
	  fprintf(fd, "%s", buffer);
	  lines++;
	}

	fclose(newfd);

	printf("(read in %d line%s from file \"%s\"   Continue...)\n",
		lines, lines == 1? "" : "s", filename);
	return;

end_it:
	printf("(continue)\n");
	return;
}

write_out(fname, fd, base_filename)
char *fname, *base_filename;
FILE *fd;
{
	/** write a copy of the current message to the specified file! **/

	FILE     *newfd;
	register int i, j, lines = 0;
	char     filename[SLEN], buffer[SLEN];

	if (strlen(fname) < 3) {
	  printf("Enter name of file to write to: ");
	  gets(filename);
	  if (strlen(filename) == 0) goto end_it;
	}
	else {
	  for (i=2; fname[i] == ' '; i++) 
	    /* count up! */ ;
	  for (j = 0; i < strlen(fname);)
	    filename[j++] = fname[i++];
	  filename[j] = '\0';
	}

	if ((newfd = fopen(filename, "w")) == NULL) {
	  printf("(Can't open file \"%s\" for writing!  Continue...)\n", 
		 filename);
	  return;
	}

	fclose(fd);	/* close the current file... */

	fd = fopen(base_filename, "r");	/* and open for reading */

	while (fgets(buffer, SLEN, fd) != NULL) {
	  fprintf(newfd, "%s", buffer);
	  lines++;
	}

	fclose(newfd);
	fclose(fd);	/* close the current file... */

	fd = fopen(base_filename, "a");	/* and open back up for appending */

	printf("(saved %d line%s to file \"%s\"   Continue...)\n",
		lines, lines == 1? "" : "s", filename);
	return;

end_it:
	printf("(continue)\n");
	return;
}
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 6839 ]
  then
    echo $filename changed - should be 6839 bytes, not $size bytes
  fi

  chmod 600 $filename
fi

if [ ! -d man ]
then
  echo creating directory man
  mkdir man
fi

# ---------- file man/editor.1 ----------

filename="man/editor.1"

if [ -f $filename ]
then
  echo File \"$filename\" already exists\!  Skipping...
  filename=/dev/null		# throw it away
else
  echo extracting file man/editor.1...
fi

cat << 'END-OF-FILE' > $filename
.TH EDITOR 1L 
.ad b
.SH NAME
editor \- a very simple, very fast input editor
.SH SYNOPSIS
.B editor
[filename] 
.SH HP-UX COMPATIBILITY
.TP 10
Level:
HP-UX/USER CONTRIBUTED
.TP
Origin:
Hewlett-Packard Laboratories
.SH DESCRIPTION
.I Editor
is a simple program suitable for use as the front-end editor for a number 
of programs, especially mail systems and conferencing systems.  It is
designed based on the functionality of the \fIBerkeley Mail\fR input
system and the \fIElm\fR builtin editor.
.sp
The program has a very small number of options, namely;
.nf

  ~?     list the help menu
  ~!     either a shell escape, or execute the specified command
  ~|     pipe the current text through the command
  ~e     invoke Emacs, if available
  ~v     invoke Vi, if available
  ~o     invoke a specified editor
  ~p     print the message entered so far
  ~r     read in the specified file
  ~w     write the message entered so far to the specified file

.fi
To end input, use either the \fIEOF\fR character (usually ^D) or
simply enter a `.' on a line by itself.
.SH AUTHOR
Dave Taylor, Hewlett-Packard Laboratories
.SH "SEE ALSO"
ex(1), ed(1), elm(1L), Mail(1), vi(1), emacs(1L), etc etc
.SH NOTES
Since this is a pretty mindless editor, it won't allow you to 
invoke it with a file that already exists.  Furthermore, the 
program MUST be given a filename to create/edit or it will 
complain.
.sp
Enhancement requests desired, but remember this isn't supposed to
be a real editor!
END-OF-FILE

if [ "$filename" != "/dev/null" ]
then
  size=`wc -c < $filename`

  if [ $size != 1480 ]
  then
    echo $filename changed - should be 1480 bytes, not $size bytes
  fi

  chmod 644 $filename
fi

echo done

exit 0