[comp.sys.apollo] DM editor as a process

murphy@hao.ucar.edu (Graham Murphy) (11/23/89)

[ The following item is posted on behalf of a friend in Australia whose
news articles have been disappearing in transit and who feels he has
been yelling himself hoarse with nobody able to hear ... please reply
directly to him at the address below, or post a follow-up if of general 
interest. ]

Is there a way of using the DM editor from within a process, for example,
in place of EDITOR=/ucb/bin/vi for editing from within mail, etc?

Note that

	xdmc ce filename

is *not* suitable, because the xdmc command returns immediately instead of
waiting for you to exit from the edit pad.

I seem to remember this question being asked in the bad old days of SR9,
and there being no known answer.  Have things improved with SR10?  Maybe
some sort of trick with "crpad -i" would do it, but I haven't been able
to work one out.

Note that this would also be useful for when you are logged in as yourself
but su'd to someone else in a window: you could edit their files via the
DM editor even though you yourself do not have access.

Thanks in advance for any suggestions.
--
Jim Richardson
Department of Pure Mathematics, University of Sydney, NSW 2006, Australia
Internet: jimr@summer.su.oz.au	ACSNET: jimr@summer.su.oz
UUCP: ...!uunet!munnari!summer.su.oz.au!jimr

achille@cernvax.UUCP (achille petrilli) (11/23/89)

Hi, I wrote a program some times ago that does what you want, I called
it dmed and use it to replace vi in mail (we all have the same ideas it
seems :-). This is not particularly difficult.

About using it when you're su'd, sorry, no way. As the program calls 
pad_$xxxx, the editor is still owned by DM and the person logged into
the DM.
I would be interested to know if Apollo has any plan to make this work.

If you want a copy send me mail (only works at sr10 and later).

Achille Petrilli
Cray & PWS Operations

janick@crk56.bnr.ca (Janick Bergeron) (11/24/89)

In article <5431@ncar.ucar.edu> jimr@summer.su.oz.au (Jim Richardson) writes:
>
>Is there a way of using the DM editor from within a process, for example,
>in place of EDITOR=/ucb/bin/vi for editing from within mail, etc?
>
>Note that
>
>	xdmc ce filename
>
>is *not* suitable, because the xdmc command returns immediately instead of
>waiting for you to exit from the edit pad.
>

Here is a small C program (I called it dmvi) that will pop-up an edit pad
and wait for it to be close before exiting.

I use it with rn (I am writing this with it) and its perfect.
I am running SR10 so I don't know if it'll work under SR9.

Usage:  dmvi [-w] [-l #] fname

        -w : Do not wait for window to close
        -l : Goto specified line number


---------8<------8<-------8<------ Cut here ----8<------8<------
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
#include <apollo/base.h>
#include <apollo/pad.h>

/***************************************************************************\
**                                                                         **
**   Function name: getopt()                                               **
**   Author:        Henry Spencer, UofT                                    **
**   Coding date:   84/04/28                                               **
**                                                                         **
**   Description:                                                          **
**                                                                         **
**   Parses argv[] for arguments.                                          **
**   Works with Whitesmith's C compiler.                                   **
**                                                                         **
**   Inputs   - The number of arguments                                    **
**            - The base address of the array of arguments                 **
**            - A string listing the valid options (':' indicates an       **
**              argument to the preceding option is required, a ';'        **
**              indicates an argument to the preceding option is optional) **
**                                                                         **
**   Outputs  - Returns the next option character,                         **
**              '?' for non '-' arguments                                  **
**              or ':' when there is no more arguments.                    **
**                                                                         **
**   Side Effects + The argument to an option is pointed to by 'optarg'    **
**                                                                         **
*****************************************************************************
**                                                                         **
**   REVISION HISTORY:                                                     **
**                                                                         **
**     DATE           NAME                        DESCRIPTION              **
**   YY/MM/DD  ------------------   ------------------------------------   **
**   88/10/20  Janick Bergeron      Returns '?' on unamed arguments        **
**                                  returns '!' on unknown options         **
**                                  and 'EOF' only when exhausted.         **
**   88/11/18  Janick Bergeron      Return ':' when no more arguments      **
**   89/08/11  Janick Bergeron      Optional optarg when ';' in optstring  **
**                                                                         **
\***************************************************************************/

char * optarg;          /* Global argument pointer. */

char  getopt( argc, argv, optstring)
int     argc;
char ** argv;
char  * optstring;
{
  register int    c;
  register char * place;
  extern   char * index();
  static   int    optind = 0;
  static   char * scan   = NULL;

  optarg = NULL;

  if ( scan == NULL || *scan == '\0') {

    if ( optind == 0 ) optind++;
    if ( optind >= argc ) return ':';

    optarg = place = argv[ optind++ ];
    if ( place[ 0 ] != '-' || place[ 1 ] == '\0' ) return '?';
    if ( place[ 1 ] == '-' && place[ 2 ] == '\0' ) return '?';
    scan = place + 1;
  }

  c = *scan++;
  place = index( optstring, c );
  if ( place == NULL || c == ':' || c == ';' ) {

    (void) fprintf( stderr, "%s: unknown option %c\n", argv[ 0 ], c );
    scan = NULL;
    return '!';
  }
  if ( *++place == ':' ) {

    if ( *scan != '\0') {

      optarg = scan;
      scan = NULL;

    } else {

      if ( optind >= argc ) {

        (void) fprintf( stderr, "%s: %c requires an argument\n",
                        argv[ 0 ], c );
        return '!';
      }
      optarg = argv[ optind ];
      optind++;
    }
  } else if ( *place == ';' ) {

    if ( *scan != '\0' ) {

      optarg = scan;
      scan = NULL;

    } else {

      if ( optind >= argc || *argv[ optind ] == '-' ) optarg = NULL;
      else {
        optarg = argv[ optind ];
        optind++;
      }
    }
  }
  return c;
}

int  main(
           int     argc,
           char ** argv
         )
{
  char                 opt;
  char               * fname = NULL;
  char               * lineno = NULL;
  char               * p;
  int                  wait = 1;
  int                  usage = 0;
  pad_$window_desc_t   window;
  ios_$id_t            stream;
  status_$t            status;
  
  while( ( opt = getopt( argc, argv, "l:w" ) ) != ':' ) {

    switch ( opt ) {
  
    case 'l':
      if ( lineno != NULL ) {
        fprintf( stderr, "%s: Option -l : only one line number can be specified.\n", argv[ 0 ] );
        usage = 1;
      } else {
        for( p = optarg; *p != '\0'; p++ ) {
          if ( !isdigit( *p ) ) {
            fprintf( stderr, "%s: Option -l : Invalid character '%c'.\n", argv[ 0 ], *p );
            usage = 1;
            break;
          }
        }
        if ( *p == '\0' ) lineno = optarg;
      }
      break;

    case 'w':
      wait = 0;
      break;

    case '?':
      if ( fname != NULL ) {
        fprintf( stderr, "%s: Only one file to edit can be specified.\n", argv[ 0 ] );
        usage = 1;
      } else fname = optarg;
      break;

    default:
      usage = 1;
      break;
    }

  }
  if ( fname == NULL ) {
    fprintf( stderr, "%s: No file to edit were specified.\n", argv[ 0 ] );
    usage = 1;
  }
  if ( usage ) {
    fprintf( stderr, "Usage: %s [-l lineno] [-w] fname\n", argv[ 0 ] );
    exit( -1 );
  }
  
  /* Create the window in the next DM default region */
  window.width = window.height = 0;
  
  pad_$create_window( fname, strlen( fname ), pad_$edit, 1, window, &stream, &status );
  if ( lineno != NULL ) {
    pad_$dm_cmd( stream, lineno, strlen( lineno ), &status );
  }
  if ( wait ) pad_$edit_wait( stream, &status );
  exit( 0 );
}

-- 
Janick Bergeron
Bell-Northern Research
(613) 763-5457
janick@crk56.bnr.ca

-- 
Janick Bergeron
Bell-Northern Research
(613) 763-5457
janick@crk56.bnr.ca

andrews@sdipl.oz (Andrew Schonberger) (11/28/89)

In article <109@crk56.bnr.com> janick@crk56.bnr.ca writes:
>Here is a small C program (I called it dmvi) that will pop-up an edit pad
>and wait for it to be close before exiting.
>
>I use it with rn (I am writing this with it) and its perfect.
>I am running SR10 so I don't know if it'll work under SR9.


I wrote a similar program, and it is really nice to set the VISUAL variable 
and then use it from rn or mail. The only difference from 'dmvi' is the use of  
return code.

When editing a new letter, my mailer (mailx) is testing the return code from 
the editor. If the editor ended abnormally, the mailer does not replace the
old message. This is usefull, since I can change my mind while editing, 
and after pressing the ABORT key I still have the original version.

As another small difference, my editor returns abnormally if it could 
not open the file. Also, I took some extra care to have the pad closed
when the program ends. On the other hand, there are no options recognized.

I append the source for this editor. I'm using the same variable
names as in the  'dmvi'  posted before, so people can compose their own
flavour. 
 
Andrew Schonberger               -these are only my private opinions-
                              
Software Developments Int'l   ACSNET: andrews@sdipl.sdi.oz
845 Pacific Hwy, NSW 2067     UUNET:..!uunet!munnari!sdipl.sdi.oz.au!andrews
Australia  +61-(2)-411-7200   INTERNET: andrews@sdipl.sdi.oz.au
                             or munnari!sdipl.sdi.oz.au!andrews@uunet.uu.net
---------------------- cut here ----------------------------------
                            
/* Apollo file editor (Andrew Schonberger)
   Does not use the parent's window. Thus it is more general 
   than "xdmc cv filename".  
   Use this program as:
		  cred filename
*/

#include <apollo/base.h>
#include <apollo/pad.h>
#include <apollo/error.h>
#include <apollo/pgm.h>
#include <apollo/ios.h>
#include <stdio.h>

pad_$window_desc_t	window;
ios_$id_t		stream_id;
status_$t		status;

int main (int argc, char *argv[], char *envp[])
{          
	if (argc!=2)
	{
		fprintf(stderr, "usage:   cred filename\n");
		exit(2);
	};
	pad_$create_window (
		argv[1]     	   	,
		strlen (argv[1])	,
		pad_$edit		,
		1			,
		window                  ,
		&stream_id		,
		&status		);
	if (status_$ok != status.all)
	{
		fprintf (stderr, "could not open:  %s\n" , argv[1]) ;
		exit(1);
	}              
	pad_$set_auto_close (stream_id, 1, true, &status);
	pad_$edit_wait (stream_id, &status);
	if (status_$ok != status.all)
	{
         	fprintf (stderr, "editing aborted on %s\n", argv[1]);
		ios_$close (stream_id, &status);
		exit(2);
	}                                        
	ios_$close (stream_id, &status);
	exit(0);
}                                       

zeleznik@cs.utah.edu (Mike Zeleznik) (11/29/89)

In article <1149@cernvax.UUCP> achille@cernvax.UUCP (achille petrilli) writes:
>Hi, I wrote a program some times ago that does what you want, I called
>it dmed and use it to replace vi in mail (we all have the same ideas it
>seems :-). This is not particularly difficult.
>
>About using it when you're su'd, sorry, no way. As the program calls 
>pad_$xxxx, the editor is still owned by DM and the person logged into
>the DM.

We got around this problem of DM owning the editor in the past with a
small shell script wrapped around the "dmed" program.  

The script simply copied the desired file into /tmp with world write
access, and edited it there.  On exit, it moved the original file to a .bak
version (thus keeping original ACLs), copied the /tmp file back to the
original location, and then set the ACLs on this new file from the .bak
file.  It also had lots of checks to make sure you didn't lose things on
abort or error.

**** Obviously this is NOT secure **** but it does serve the purpose if
security of that sort is not a primary issue.

Mike

  Michael Zeleznik              Computer Science Dept.
                                University of Utah
  zeleznik@cs.utah.edu          Salt Lake City, UT  84112
                                (801) 581-5617

troy@mr_plod.cbme.unsw.oz (Troy Rollo) (12/03/89)

From article <109@crk56.bnr.com>, by janick@crk56.bnr.ca (Janick Bergeron):
janick>     pad_$dm_cmd( stream, lineno, strlen( lineno ), &status );
janick>   }
janick>   if ( wait ) pad_$edit_wait( stream, &status );
janick>   exit( 0 );
janick> }

It is more effiient to use pad_$create_window. There is one thing to be
careful about with this sort of setup - the edit_wait function sometimes 
returns before the file has been unlocked and made available to other programs.
Sometimes the process will return before the file is unlocked too, resulting
in a file which  cannot be reopened by the calling process. This can be cured
by placeing a sleep(2) in front of the exit(0).
___________________________________________________________
troy@mr_plod.cbme.unsw.oz.au	Make our greenies useful!
The Resident Fascist		Put them in the army!

troy@mr_plod.cbme.unsw.oz (Troy Rollo) (12/03/89)

From article <1989Nov29.094555.24366@hellgate.utah.edu>, by zeleznik@cs.utah.edu (Mike Zeleznik):

zeleznik> We got around this problem of DM owning the editor in the past with a
zeleznik> small shell script wrapped around the "dmed" program.  

zeleznik> The script simply copied the desired file into /tmp with world write
zeleznik> access, and edited it there.  On exit, it moved the original file to a .bak
zeleznik> version (thus keeping original ACLs), copied the /tmp file back to the
zeleznik> original location, and then set the ACLs on this new file from the .bak
zeleznik> file.  It also had lots of checks to make sure you didn't lose things on
zeleznik> abort or error.

zeleznik> **** Obviously this is NOT secure **** but it does serve the purpose if
zeleznik> security of that sort is not a primary issue.

It could be made to be secure with a slight modification. If each user has 
their own group ID, the editor could change the group owner of the temp file
to the owner of the DM process. Apollo have kindly created an extra ID which
can be used for similar things, the organization ID, so there's really no
excuse for leaving a security hole like that.

Of course it gets better - with extended ACLs you can simply grant access to
the user who owns the display to the file in question... with:

chacl user.%.%=rw file

and remove with:

chacl user.%.%= file 

___________________________________________________________
troy@mr_plod.cbme.unsw.oz.au	Make our greenies useful!
The Resident Fascist		Put them in the army!