File: marsden.html

package info (click to toggle)
lg-issue29 3-4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,840 kB
  • ctags: 365
  • sloc: java: 758; makefile: 36; sh: 4
file content (325 lines) | stat: -rw-r--r-- 13,365 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
<!--startcut ==========================================================-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<head>
<title>EMACSulation LG #29</title>
<link rev="made" href="mailto:emarsden@mail.dotcom.fr">
<meta name="keywords"
      content="emacs, emacsclient, gnuserv, gnuclient, gnudoit, remote invocation"
<meta name="description"
      content="Emacsclient/gnuserv provide a remote invocation mechanism
for Emacs, allowing programs to send commands to an Emacs process on the
local machine or across the network.">
<meta name="author" content="Eric Marsden">            
<meta name="generator" content="Emacs">
</head>

<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#A000A0"
ALINK="#FF0000">
<!--endcut ============================================================-->

<H4>
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>

<P> <HR> <P> 
<!--===================================================================-->


<center>
<H1><font color="maroon">EMACSulation</font></H1>
<h4>by <a href="mailto:emarsden@mail.dotcom.fr">Eric Marsden</a>
</h4>
</center>


<blockquote><small>

   This column is devoted to making the best use of Emacs, text editor
   extraordinaire. Each issue I plan to present an Emacs extension
   which can improve your productivity, make the sun shine more brightly
   and the grass greener.

</small></blockquote>

<p><HR> <P> 

<h1>Emacs as a server</h1>

<p> Many people meet Emacs as the default program launched by Elm to edit
    an email message. Starting up Emacs in this way is a bit of a pain,
    because of the delay and memory use, but also because the fresh Emacs
    doesn't share buffers and a kill ring (storage for cut/copied text)
    with other invocations. Rather than starting up a new Emacs for each
    letter, you can set the environment variable <tt>EDITOR</tt> to
    <tt>emacsclient</tt>.

<p> The Emacs server mechanism allows one Emacs process to service editing
    requests from other applications. To enable it you need to add a line
    like <tt>(server-start)</tt> in <tt>~/.emacs</tt>. When you say
    <tt>emacsclient filename</tt>, the program searches for an Emacs
    process (launching one if necessary) and sends it a message asking it
    to edit <tt>filename</tt>. The caller process (the shell for example)
    is blocked while the file is being edited. When you're finished type
    <tt>C-x #</tt> and the client will be unblocked.

    
<h2>Gnuserv</h2>

<p> Gnuserv is a more sophisticated remote invocation mechanism for Emacs,
    written by <a href="http://hplbwww.hpl.hp.com/people/ange/">Andy
    Norman</a> (also the author of <a
    href="http://www.linuxgazette.com/issue26/marsden.html">ange-ftp</a>).
    It allows arbitrary Emacs Lisp commands to be sent to an Emacs process
    running either on the local machine or on another machine on the
    network.

<ol>
<li> If you're using XEmacs everything is already set up; you will only
     need to add a <tt>(gnuserv-start)</tt> to your <tt>~/.emacs</tt>.
     
<li> Obtain the gnuserv-2.1alpha RPM from Red Hat contrib, or <a
     href="http://cgi.debian.org/www-master/debian.org/Packages/unstable/editors/gnuserv.html">
     the .deb</a> for Debian Hamm and skip to 6&nbsp;;

<li> Download the <a
     href="http://hplbwww.hpl.hp.com/people/ange/gnuserv/">source</a>&nbsp;;

<li> Edit <tt>config.h</tt> (I suggest using <tt>#define
     DONT_USE_LITOUT</tt>) and <tt>gnuserv.h</tt>, where you choose the
     communication method (the default is Internet domain <a
     href="http://www.lowtek.com/sockets/">sockets</a>, which is necessary
     if you want to be able to do the remote stuff)&nbsp;;

<li> Put the file <tt>gnuserv.el</tt> somewhere in Emacs' load path. Let's
     assume you have an <tt>~/elisp/</tt> directory where you put your
     favorite Emacs Lisp extensions; an alternative is to copy gnuserv.el
     to a site-wide Emacs Lisp directory such as
     <tt>/usr/lib/emacs/site-lisp</tt> (type <tt>C-h v load-path</tt> in
     Emacs to see a list of possiblities)&nbsp;;

<li> Add something like this to your <tt>~/.emacs</tt>&nbsp;:

<pre>
    (setq load-path (cons (expand-file-name "~/elisp") load-path))
    (autoload 'gnuserv-start "gnuserv" "Better Emacs server support")
    (setq gnuserv-frame (current-frame))
    (gnuserv-start)
</pre>

<p> The second line tells Emacs that the function <tt>gnuserv-start</tt> is
    defined in a file called gnuserv.el, which Emacs will load on demand.
    The third line inhibits the default behaviour of opeing a new frame for
    each new file edited (leave this out if you prefer). The last line
    fires up the server.

</ol>    


<p> To check that everything is working, type

<pre><tt>
    ~$ gnuclient &lt;filename&gt;
</tt></pre>

<p> which asks Emacs to open <tt>&lt;filename&gt;</tt>, just like
    emacsclient. If this doesn't work (with a message like ``Refused
    connection'' or ``Broken pipe''), skip down to the <a
    href="#security">Security section</a>. You can also send off an
    arbitrary bit of Emacs Lisp&nbsp;:

<pre>    
    ~$ gnudoit '(message "Hi there, %s!" (user-full-name))'

</pre>


<h2>Applications</h2>

<p> Now you can do all sorts of silly things. You could get two Emacsen on
    networked machines to play ping pong, echoing messages back and forth.
    You could use Emacs as a CGI script server, profiting from its powerful
    library without incurring the overhead of launching an interpreter for
    each script (a little like the <a
    href="http://www.FastCGI.com/">FastCGI</a> mechanism). For example,
    let's hack together an external interface to Emacs' builtin
    psychologist&nbsp;:

    
<pre>
     (defun eliza-start ()
       "Fire up the doctor."
       (interactive)
       (doctor)
       ;; We only have to type return once under this interface.
       (re-search-backward " twice" nil t)
       (replace-match "")
       (goto-char (point-max))
       (buffer-substring (point-min) (point-max)))

     (defun eliza-continue (str)
       "Send a string to the doctor and return her response."
       (interactive)
       (switch-to-buffer "*doctor*")
       (insert "\n" str "\n")
       (doctor-read-print)
       (save-excursion
         (re-search-backward "\n\n\\(\\(.+\n?\\)+\\)\n\n")
         (match-string 1)))

     (defun eliza-cleanup ()
       "Pay the bill and leave."
       (interactive)
       (let ((buf (get-buffer "*doctor*")))
          (if buf (kill-buffer buf))))
</pre>

<p> This can be used from the command line (for CGI use you'd have to
    think about the trickier question of concurrent accesses) with a script
    such as

<pre>
     #! /bin/sh
     
     gnudoit '(eliza-start)'
     while read line
     do
         gnudoit "(eliza-continue \"$line\")"
     done
     gnudoit '(eliza-cleanup)'
</pre>

<p> You might even find constructive uses for the gnuserv technology, like
    starting <a href="http://www.Gnus.org/">Gnus</a> (an Emacs news/email
    client) and ange-ftp transfers from a ``network Emacs'', so that your
    primary Emacs isn't affected by networking delays. You could also
    communicate with Emacs from a crontab, telling it to fetch some web
    pages with Emacs/w3, or send someone an email. You could use
    Netscape's third party <a
    href="http://developer.netscape.com/software/sdks/index.html?content=mailnews.html">
    email/news API</a> to invoke Emacs instead of the builtin mail and news
    clients. It might also be useful for sending commands to Emacs from a
    <a href="http://www.plig.org/xwinman/">window manager</a> menu.


<h2>Security considerations<a name="security"></A></h2>

<p> More and more Linux distributions use good <a
    href="http://ciac.llnl.gov/ciac/documents/ciac2316.html">X security</a>
    as set up out of the box. You will notice for example that when you su
    to root on a modern system, you will no longer be able to launch X
    clients, because the X server is protected by an <a
    href="http://www.xs4all.nl/~zweije/xauth.html">xauth</a> cookie.

<p> While allowing access to your X display is bad enough (someone could
    capture all your keystrokes, for example), giving remote access to your
    Emacs process is much more worrying, since Emacs can execute arbitrary
    commands under your id, delete files, send insulting email to the
    President of the United States, etc.

<p> Since release 2.1, gnuserv is able to use MIT-MAGIC-COOKIE-1
    authentication for remote requests. This protocol uses the contents of
    your <tt>~/.Xauthority</tt> file, as described in the xauth(1) man page.
    Gnuserv requires a cookie for display number 999, which you can create
    as follows (blade is the name of the machine)&nbsp;:

<pre>    
      ~$ xauth add blade:999 . `cat /etc/passwd | md5sum` 
      ~$ xauth list
      blade/unix:0  MIT-MAGIC-COOKIE-1  bc1d627babdbabe9d1f288d2b57c348f
      blade:999  MIT-MAGIC-COOKIE-1  d89570b20925d401c05a79be67159cae
</pre>

<p> (<tt>`cat /etc/passwd | md5sum`</tt> is just a convenient way of
    generating a cookie; on most Linux systems you will be able to use the
    <a
    href="http://hegel.ittc.ukans.edu/topics/linux/man-pages/man1/mcookie.1.html">mcookie</a>
    command, or you can bake a cookie by hand). Now you should be able to
    use gnuclient/gnudoit on the local machine. The next step is to
    transfer the cookie to each remote machine from which you plan to
    access Emacs, with a command such as&nbsp;:

<pre>    
      ~$ xauth extract - blade:999 | rsh remotehost.edu xauth merge -
</pre>

<p> If you don't run X you will have to fall back to a host-based access
    control system&nbsp;: the environment variable <tt>GNU_SECURE</tt> is
    assumed to point to a file which contains a list of machines which are
    authorized to open connections to your Emacs process. Finally, if your
    machine isn't networked, you've probably already skipped to the next
    section.


<h2>How does it work?</h2>

<p> Your command takes a fairly convoluted route to reach Emacs. There are
    four parties involved in a transaction&nbsp;: the ``client'', or
    program which wants a service from Emacs (Elm for example), the
    gnuclient program (which runs on the requesting machine), the gnuserv
    process (which runs on the machine running Emacs), and of course the
    Emacs process itself. They communicate as indicated by the following
    diagram&nbsp;:

<p> <img src="./gx/marsden/gnuserv-arch.gif" alt="Communication diagram (3 kB)">

<p> The fragile aspect of the system is that if the gnuserv program dies
    for some reason, everything grinds to a halt. An alternative
    communication method which would involve fewer working parts could be
    inspired from the Netscape remote invocation protocol. The gnuclient
    capabilities would be added directly to Emacs, and a gnudoit request
    would look something like

<pre>
    emacs -remote -lisp '(message "Hi")'
</pre>

<p> The new Emacs process would search for an existing Emacs process to
    which it could dispatch the request, or service it directly. The
    disadvantage is that each request would be slower, since an Emacs needs
    to be forked each time. The image is most often in the disk cache, so
    this wouldn't be catastrophically slow (it works OK with Mozilla, which
    is <a
    href="http://x5.dejanews.com/getdoc.xp?AN=202452924&CONTEXT=896094230.406519988&hitnum=1">far
    bigger</a> than Emacs).

     
<h2>Next time ...</h2>

<p> I've received a fair bit of email asking how to customize various
    aspects of Emacs, so I'll try to scratch the surface of this vast topic
    next month, and discuss the Customize package. Don't hesitate to
    contact me at <tt>&lt;emarsden@mail.dotcom.fr&gt;</tt> with comments,
    corrections or suggestions (what's <em>your</em> favorite
    couldn't-do-without Emacs extension package?). <code>C-u 1000 M-x
    hail-emacs</code> !

<p> <b>PS</b> : Emacs isn't in any way limited to Linux, since
    implementations exist for many other operating systems (and some
    systems which only halfway operate). However, as one of the leading
    bits of free software, one of the most powerful, complex and
    customizable, I feel it has its place in the <i>Linux Gazette</i>.

<!--===================================================================-->
<P> <hr> <P> 
<A HREF="../issue25/marsden.html">EMACSulation #1, February 1998</A><br>
<A HREF="../issue26/marsden.html">EMACSulation #2, March 1998</A><br>
<A HREF="../issue27/marsden.html">EMACSulation #3, April 1998</A>
<P> <hr> <P>
<center><H5>Copyright &copy; 1998, Eric Marsden <BR> 
Published in Issue 29 of <i>Linux Gazette</i>, June 1998</H5></center>

<!--===================================================================-->
<P> <hr> <P> 
<A HREF="./lg_toc29.html"><IMG ALIGN=BOTTOM SRC="../gx/indexnew.gif" 
ALT="[ TABLE OF CONTENTS ]"></A>
<A HREF="../lg_frontpage.html"><IMG ALIGN=BOTTOM SRC="../gx/homenew.gif"
ALT="[ FRONT PAGE ]"></A>
<A HREF="./hamilton.html"><IMG SRC="../gx/back2.gif"
ALT=" Back "></A>
<A HREF="./prelz.html"><IMG SRC="../gx/fwd.gif" ALT=" Next "></A>
<P> <hr> <P> 
<!--startcut ==========================================================-->
</BODY>
</HTML>
<!--endcut ============================================================-->