xref: /openbsd-src/gnu/usr.bin/cvs/doc/cvsclient.info-3 (revision 2f9d2fd98e61b35652c22b933385d2e16ba1780c)
1This is cvsclient.info, produced by Makeinfo version 3.12f from
2./cvsclient.texi.
3
4
5File: cvsclient.info,  Node: Responses,  Next: Text tags,  Prev: Response pathnames,  Up: Protocol
6
7Responses
8=========
9
10   Here are the responses:
11
12`Valid-requests REQUEST-LIST \n'
13     Indicate what requests the server will accept.  REQUEST-LIST is a
14     space separated list of tokens.  If the server supports sending
15     patches, it will include `update-patches' in this list.  The
16     `update-patches' request does not actually do anything.
17
18`Checked-in PATHNAME \n'
19     Additional data: New Entries line, \n.  This means a file PATHNAME
20     has been successfully operated on (checked in, added, etc.).  name
21     in the Entries line is the same as the last component of PATHNAME.
22
23`New-entry PATHNAME \n'
24     Additional data: New Entries line, \n.  Like `Checked-in', but the
25     file is not up to date.
26
27`Updated PATHNAME \n'
28     Additional data: New Entries line, \n, mode, \n, file
29     transmission.  A new copy of the file is enclosed.  This is used
30     for a new revision of an existing file, or for a new file, or for
31     any other case in which the local (client-side) copy of the file
32     needs to be updated, and after being updated it will be up to
33     date.  If any directory in pathname does not exist, create it.
34     This response is not used if `Created' and `Update-existing' are
35     supported.
36
37`Created PATHNAME \n'
38     This is just like `Updated' and takes the same additional data, but
39     is used only if no `Entry', `Modified', or `Unchanged' request has
40     been sent for the file in question.  The distinction between
41     `Created' and `Update-existing' is so that the client can give an
42     error message in several cases: (1) there is a file in the working
43     directory, but not one for which `Entry', `Modified', or
44     `Unchanged' was sent (for example, a file which was ignored, or a
45     file for which `Questionable' was sent), (2) there is a file in
46     the working directory whose name differs from the one mentioned in
47     `Created' in ways that the client is unable to use to distinguish
48     files.  For example, the client is case-insensitive and the names
49     differ only in case.
50
51`Update-existing PATHNAME \n'
52     This is just like `Updated' and takes the same additional data, but
53     is used only if a `Entry', `Modified', or `Unchanged' request has
54     been sent for the file in question.
55
56     This response, or `Merged', indicates that the server has
57     determined that it is OK to overwrite the previous contents of the
58     file specified by PATHNAME.  Provided that the client has correctly
59     sent `Modified' or `Is-modified' requests for a modified file, and
60     the file was not modified while CVS was running, the server can
61     ensure that a user's modifications are not lost.
62
63`Merged PATHNAME \n'
64     This is just like `Updated' and takes the same additional data,
65     with the one difference that after the new copy of the file is
66     enclosed, it will still not be up to date.  Used for the results
67     of a merge, with or without conflicts.
68
69     It is useful to preserve an copy of what the file looked like
70     before the merge.  This is basically handled by the server; before
71     sending `Merged' it will send a `Copy-file' response.  For
72     example, if the file is `aa' and it derives from revision 1.3, the
73     `Copy-file' response will tell the client to copy `aa' to
74     `.#aa.1.3'.  It is up to the client to decide how long to keep this
75     file around; traditionally clients have left it around forever,
76     thus letting the user clean it up as desired.  But another answer,
77     such as until the next commit, might be preferable.
78
79`Rcs-diff PATHNAME \n'
80     This is just like `Updated' and takes the same additional data,
81     with the one difference that instead of sending a new copy of the
82     file, the server sends an RCS change text.  This change text is
83     produced by `diff -n' (the GNU diff `-a' option may also be used).
84     The client must apply this change text to the existing file.
85     This will only be used when the client has an exact copy of an
86     earlier revision of a file.  This response is only used if the
87     `update' command is given the `-u' argument.
88
89`Patched PATHNAME \n'
90     This is just like `Rcs-diff' and takes the same additional data,
91     except that it sends a standard patch rather than an RCS change
92     text.  The patch is produced by `diff -c' for CVS 1.6 and later
93     (see POSIX.2 for a description of this format), or `diff -u' for
94     previous versions of CVS; clients are encouraged to accept either
95     format.  Like `Rcs-diff', this response is only used if the
96     `update' command is given the `-u' argument.
97
98     The `Patched' response is deprecated in favor of the `Rcs-diff'
99     response.  However, older clients (CVS 1.9 and earlier) only
100     support `Patched'.
101
102`Mode MODE \n'
103     This MODE applies to the next file mentioned in `Checked-in'.
104     `Mode' is a file update modifying response as described in *Note
105     Response intro::.
106
107`Mod-time TIME \n'
108     Set the modification time of the next file sent to TIME.
109     `Mod-time' is a file update modifying response as described in
110     *Note Response intro::.  The TIME is in the format specified by
111     RFC822 as modified by RFC1123.  The server may specify any
112     timezone it chooses; clients will want to convert that to their
113     own timezone as appropriate.  An example of this format is:
114
115          26 May 1997 13:01:40 -0400
116
117     There is no requirement that the client and server clocks be
118     synchronized.  The server just sends its recommendation for a
119     timestamp (based on its own clock, presumably), and the client
120     should just believe it (this means that the time might be in the
121     future, for example).
122
123     If the server does not send `Mod-time' for a given file, the client
124     should pick a modification time in the usual way (usually, just
125     let the operating system set the modification time to the time
126     that the CVS command is running).
127
128`Checksum CHECKSUM\n'
129     The CHECKSUM applies to the next file sent (that is, `Checksum' is
130     a file update modifying response as described in *Note Response
131     intro::).  In the case of `Patched', the checksum applies to the
132     file after being patched, not to the patch itself.  The client
133     should compute the checksum itself, after receiving the file or
134     patch, and signal an error if the checksums do not match.  The
135     checksum is the 128 bit MD5 checksum represented as 32 hex digits
136     (MD5 is described in RFC1321).  This response is optional, and is
137     only used if the client supports it (as judged by the
138     `Valid-responses' request).
139
140`Copy-file PATHNAME \n'
141     Additional data: NEWNAME \n.  Copy file PATHNAME to NEWNAME in the
142     same directory where it already is.  This does not affect
143     `CVS/Entries'.
144
145     This can optionally be implemented as a rename instead of a copy.
146     The only use for it which currently has been identified is prior
147     to a `Merged' response as described under `Merged'.  Clients can
148     probably assume that is how it is being used, if they want to worry
149     about things like how long to keep the NEWNAME file around.
150
151`Removed PATHNAME \n'
152     The file has been removed from the repository (this is the case
153     where cvs prints `file foobar.c is no longer pertinent').
154
155`Remove-entry PATHNAME \n'
156     The file needs its entry removed from `CVS/Entries', but the file
157     itself is already gone (this happens in response to a `ci' request
158     which involves committing the removal of a file).
159
160`Set-static-directory PATHNAME \n'
161     This instructs the client to set the `Entries.Static' flag, which
162     it should then send back to the server in a `Static-directory'
163     request whenever the directory is operated on.  PATHNAME ends in a
164     slash; its purpose is to specify a directory, not a file within a
165     directory.
166
167`Clear-static-directory PATHNAME \n'
168     Like `Set-static-directory', but clear, not set, the flag.
169
170`Set-sticky PATHNAME \n'
171     Additional data: TAGSPEC \n.  Tell the client to set a sticky tag
172     or date, which should be supplied with the `Sticky' request for
173     future operations.  PATHNAME ends in a slash; its purpose is to
174     specify a directory, not a file within a directory.  The client
175     should store TAGSPEC and pass it back to the server as-is, to
176     allow for future expansion.  The first character of TAGSPEC is `T'
177     for a tag, `D' for a date, or something else for future expansion.
178     The remainder of TAGSPEC contains the actual tag or date.
179
180`Clear-sticky PATHNAME \n'
181     Clear any sticky tag or date set by `Set-sticky'.
182
183`Template PATHNAME \n'
184     Additional data: file transmission (note: compressed file
185     transmissions are not supported).  PATHNAME ends in a slash; its
186     purpose is to specify a directory, not a file within a directory.
187     Tell the client to store the file transmission as the template log
188     message, and then use that template in the future when prompting
189     the user for a log message.
190
191`Set-checkin-prog DIR \n'
192     Additional data: PROG \n.  Tell the client to set a checkin
193     program, which should be supplied with the `Checkin-prog' request
194     for future operations.
195
196`Set-update-prog DIR \n'
197     Additional data: PROG \n.  Tell the client to set an update
198     program, which should be supplied with the `Update-prog' request
199     for future operations.
200
201`Notified PATHNAME \n'
202     Indicate to the client that the notification for PATHNAME has been
203     done.  There should be one such response for every `Notify'
204     request; if there are several `Notify' requests for a single file,
205     the requests should be processed in order; the first `Notified'
206     response pertains to the first `Notify' request, etc.
207
208`Module-expansion PATHNAME \n'
209     Return a file or directory which is included in a particular
210     module.  PATHNAME is relative to cvsroot, unlike most pathnames in
211     responses.  PATHNAME should be used to look and see whether some
212     or all of the module exists on the client side; it is not
213     necessarily suitable for passing as an argument to a `co' request
214     (for example, if the modules file contains the `-d' option, it
215     will be the directory specified with `-d', not the name of the
216     module).
217
218`Wrapper-rcsOption PATTERN -k 'OPTION' \n'
219     Transmit to the client a filename pattern which implies a certain
220     keyword expansion mode.  The PATTERN is a wildcard pattern (for
221     example, `*.exe'.  The OPTION is `b' for binary, and so on.  Note
222     that although the syntax happens to resemble the syntax in certain
223     CVS configuration files, it is more constrained; there must be
224     exactly one space between PATTERN and `-k' and exactly one space
225     between `-k' and `'', and no string is permitted in place of `-k'
226     (extensions should be done with new responses, not by extending
227     this one, for graceful handling of `Valid-responses').
228
229`M TEXT \n'
230     A one-line message for the user.  Note that the format of TEXT is
231     not designed for machine parsing.  Although sometimes scripts and
232     clients will have little choice, the exact text which is output is
233     subject to vary at the discretion of the server and the example
234     output given in this document is just that, example output.
235     Servers are encouraged to use the `MT' response, and future
236     versions of this document will hopefully standardize more of the
237     `MT' tags; see *Note Text tags::.
238
239`Mbinary \n'
240     Additional data: file transmission (note: compressed file
241     transmissions are not supported).  This is like `M', except the
242     contents of the file transmission are binary and should be copied
243     to standard output without translation to local text file
244     conventions.  To transmit a text file to standard output, servers
245     should use a series of `M' requests.
246
247`E TEXT \n'
248     Same as `M' but send to stderr not stdout.
249
250`F \n'
251     Flush stderr.  That is, make it possible for the user to see what
252     has been written to stderr (it is up to the implementation to
253     decide exactly how far it should go to ensure this).
254
255`MT TAGNAME DATA \n'
256     This response provides for tagged text.  It is similar to
257     SGML/HTML/XML in that the data is structured and a naive
258     application can also make some sense of it without understanding
259     the structure.  The syntax is not SGML-like, however, in order to
260     fit into the CVS protocol better and (more importantly) to make it
261     easier to parse, especially in a language like perl or awk.
262
263     The TAGNAME can have several forms.  If it starts with `a' to `z'
264     or `A' to `Z', then it represents tagged text.  If the
265     implementation recognizes TAGNAME, then it may interpret DATA in
266     some particular fashion.  If the implementation does not recognize
267     TAGNAME, then it should simply treat DATA as text to be sent to
268     the user (similar to an `M' response).  There are two tags which
269     are general purpose.  The `text' tag is similar to an unrecognized
270     tag in that it provides text which will ordinarily be sent to the
271     user.  The `newline' tag is used without DATA and indicates that a
272     newline will ordinarily be sent to the user (there is no provision
273     for embedding newlines in the DATA of other tagged text responses).
274
275     If TAGNAME starts with `+' it indicates a start tag and if it
276     starts with `-' it indicates an end tag.  The remainder of TAGNAME
277     should be the same for matching start and end tags, and tags
278     should be nested (for example one could have tags in the following
279     order `+bold' `+italic' `text' `-italic' `-bold' but not `+bold'
280     `+italic' `text' `-bold' `-italic').  A particular start and end
281     tag may be documented to constrain the tagged text responses which
282     are valid between them.
283
284     Note that if DATA is present there will always be exactly one
285     space between TAGNAME and DATA; if there is more than one space,
286     then the spaces beyond the first are part of DATA.
287
288     Here is an example of some tagged text responses.  Note that there
289     is a trailing space after `Checking in' and `initial revision:'
290     and there are two trailing spaces after `<--'.  Such trailing
291     spaces are, of course, part of DATA.
292
293          MT +checking-in
294          MT text Checking in
295          MT fname gz.tst
296          MT text ;
297          MT newline
298          MT rcsfile /home/kingdon/zwork/cvsroot/foo/gz.tst,v
299          MT text   <--
300          MT fname gz.tst
301          MT newline
302          MT text initial revision:
303          MT init-rev 1.1
304          MT newline
305          MT text done
306          MT newline
307          MT -checking-in
308
309     If the client does not support the `MT' response, the same
310     responses might be sent as:
311
312          M Checking in gz.tst;
313          M /home/kingdon/zwork/cvsroot/foo/gz.tst,v  <--  gz.tst
314          M initial revision: 1.1
315          M done
316
317     For a list of specific tags, see *Note Text tags::.
318
319`error ERRNO-CODE ` ' TEXT \n'
320     The command completed with an error.  ERRNO-CODE is a symbolic
321     error code (e.g. `ENOENT'); if the server doesn't support this
322     feature, or if it's not appropriate for this particular message,
323     it just omits the errno-code (in that case there are two spaces
324     after `error').  Text is an error message such as that provided by
325     strerror(), or any other message the server wants to use.  The
326     TEXT is like the `M' response, in the sense that it is not
327     particularly intended to be machine-parsed; servers may wish to
328     print an error message with `MT' responses, and then issue a
329     `error' response without TEXT (although it should be noted that
330     `MT' currently has no way of flagging the output as intended for
331     standard error, the way that the `E' response does).
332
333`ok \n'
334     The command completed successfully.
335
336
337File: cvsclient.info,  Node: Text tags,  Next: Example,  Prev: Responses,  Up: Protocol
338
339Tags for the MT tagged text response
340====================================
341
342   The `MT' response, as described in *Note Responses::, offers a way
343for the server to send tagged text to the client.  This section
344describes specific tags.  The intention is to update this section as
345servers add new tags.
346
347   In the following descriptions, `text' and `newline' tags are
348omitted.  Such tags contain information which is intended for users (or
349to be discarded), and are subject to change at the whim of the server.
350To avoid being vulnerable to such whim, clients should look for the tags
351listed here, not `text', `newline', or other tags.
352
353   The following tag means to indicate to the user that a file has been
354updated.  It is more or less redundant with the `Created' and
355`Update-existing' responses, but we don't try to specify here whether
356it occurs in exactly the same circumstances as `Created' and
357`Update-existing'.  The NAME is the pathname of the file being updated
358relative to the directory in which the command is occurring (that is,
359the last `Directory' request which is sent before the command).
360
361     MT +updated
362     MT fname NAME
363     MT -updated
364
365   The `importmergecmd' tag is used when doing an import which has
366conflicts.  The client can use it to report how to merge in the newly
367imported changes.  The COUNT is the number of conflicts.  The newly
368imported changes can be merged by running the following command:
369     cvs checkout -j TAG1 -j TAG2 REPOSITORY
370
371     MT +importmergecmd
372     MT conflicts COUNT
373     MT mergetag1 TAG1
374     MT mergetag2 TAG2
375     MT repository REPOSITORY
376     MT -importmergecmd
377
378
379File: cvsclient.info,  Node: Example,  Next: Requirements,  Prev: Text tags,  Up: Protocol
380
381Example
382=======
383
384   Here is an example; lines are prefixed by `C: ' to indicate the
385client sends them or `S: ' to indicate the server sends them.
386
387   The client starts by connecting, sending the root, and completing the
388protocol negotiation.  In actual practice the lists of valid responses
389and requests would be longer.
390
391     C: Root /u/cvsroot
392     C: Valid-responses ok error Checked-in M E
393     C: valid-requests
394     S: Valid-requests Root Directory Entry Modified Argument Argumentx ci co
395     S: ok
396     C: UseUnchanged
397
398   The client wants to check out the `supermunger' module into a fresh
399working directory.  Therefore it first expands the `supermunger'
400module; this step would be omitted if the client was operating on a
401directory rather than a module.
402
403     C: Argument supermunger
404     C: Directory .
405     C: /u/cvsroot
406     C: expand-modules
407
408   The server replies that the `supermunger' module expands to the
409directory `supermunger' (the simplest case):
410
411     S: Module-expansion supermunger
412     S: ok
413
414   The client then proceeds to check out the directory.  The fact that
415it sends only a single `Directory' request which specifies `.' for the
416working directory means that there is not already a `supermunger'
417directory on the client.
418
419     C: Argument -N
420     C: Argument supermunger
421     C: Directory .
422     C: /u/cvsroot
423     C: co
424
425   The server replies with the requested files.  In this example, there
426is only one file, `mungeall.c'.  The `Clear-sticky' and
427`Clear-static-directory' requests are sent by the current
428implementation but they have no effect because the default is for those
429settings to be clear when a directory is newly created.
430
431     S: Clear-sticky supermunger/
432     S: /u/cvsroot/supermunger/
433     S: Clear-static-directory supermunger/
434     S: /u/cvsroot/supermunger/
435     S: E cvs server: Updating supermunger
436     S: M U supermunger/mungeall.c
437     S: Created supermunger/
438     S: /u/cvsroot/supermunger/mungeall.c
439     S: /mungeall.c/1.1///
440     S: u=rw,g=r,o=r
441     S: 26
442     S: int mein () { abort (); }
443     S: ok
444
445   The current client implementation would break the connection here
446and make a new connection for the next command.  However, the protocol
447allows it to keep the connection open and continue, which is what we
448show here.
449
450   After the user modifies the file and instructs the client to check it
451back in.  The client sends arguments to specify the log message and file
452to check in:
453
454     C: Argument -m
455     C: Argument Well, you see, it took me hours and hours to find
456     C: Argumentx this typo and I searched and searched and eventually
457     C: Argumentx had to ask John for help.
458     C: Argument mungeall.c
459
460   It also sends information about the contents of the working
461directory, including the new contents of the modified file.  Note that
462the user has changed into the `supermunger' directory before executing
463this command; the top level directory is a user-visible concept because
464the server should print filenames in `M' and `E' responses relative to
465that directory.
466
467     C: Directory .
468     C: /u/cvsroot/supermunger
469     C: Entry /mungeall.c/1.1///
470     C: Modified mungeall.c
471     C: u=rw,g=r,o=r
472     C: 26
473     C: int main () { abort (); }
474
475   And finally, the client issues the checkin command (which makes use
476of the data just sent):
477
478     C: ci
479
480   And the server tells the client that the checkin succeeded:
481
482     S: M Checking in mungeall.c;
483     S: E /u/cvsroot/supermunger/mungeall.c,v  <--  mungeall.c
484     S: E new revision: 1.2; previous revision: 1.1
485     S: E done
486     S: Mode u=rw,g=r,o=r
487     S: Checked-in ./
488     S: /u/cvsroot/supermunger/mungeall.c
489     S: /mungeall.c/1.2///
490     S: ok
491
492
493File: cvsclient.info,  Node: Requirements,  Next: Obsolete,  Prev: Example,  Up: Protocol
494
495Required versus optional parts of the protocol
496==============================================
497
498   The following are part of every known implementation of the CVS
499protocol (except obsolete, pre-1.5, versions of CVS) and it is
500considered reasonable behavior to completely fail to work if you are
501connected with an implementation which attempts to not support them.
502Requests: `Root', `Valid-responses', `valid-requests', `Directory',
503`Entry', `Modified', `Unchanged', `Argument', `Argumentx', `ci', `co',
504`update'.  Responses: `ok', `error', `Valid-requests', `Checked-in',
505`Updated', `Merged', `Removed', `M', `E'.
506
507   A server need not implement `Repository', but in order to
508interoperate with CVS 1.5 through 1.9 it must claim to implement it (in
509`Valid-requests').  The client will not actually send the request.
510
511
512File: cvsclient.info,  Node: Obsolete,  Prev: Requirements,  Up: Protocol
513
514Obsolete protocol elements
515==========================
516
517   This section briefly describes protocol elements which are obsolete.
518There is no attempt to document them in full detail.
519
520   There was a `Repository' request which was like `Directory' except
521it only provided REPOSITORY, and the local directory was assumed to be
522similarly named.
523
524   If the `UseUnchanged' request was not sent, there was a `Lost'
525request which was sent to indicate that a file did not exist in the
526working directory, and the meaning of sending `Entries' without `Lost'
527or `Modified' was different.  All current clients (CVS 1.5 and later)
528will send `UseUnchanged' if it is supported.
529
530
531File: cvsclient.info,  Node: Protocol Notes,  Prev: Protocol,  Up: Top
532
533Notes on the Protocol
534*********************
535
536   A number of enhancements are possible.  Also see the file TODO in
537the CVS source distribution, which has further ideas concerning various
538aspects of CVS, some of which impact the protocol.  Similarly, the
539`http://www.cyclic.com' site, in particular the `Development of CVS'
540page.
541
542   * The `Modified' request could be speeded up by sending diffs rather
543     than entire files.  The client would need some way to keep the
544     version of the file which was originally checked out; probably
545     requiring the use of "cvs edit" in this case is the most sensible
546     course (the "cvs edit" could be handled by a package like VC for
547     emacs).  This would also allow local operation of `cvs diff'
548     without arguments.
549
550   * The fact that `pserver' requires an extra network turnaround in
551     order to perform authentication would be nice to avoid.  This
552     relates to the issue of reporting errors; probably the clean
553     solution is to defer the error until the client has issued a
554     request which expects a response.  To some extent this might
555     relate to the next item (in terms of how easy it is to skip a
556     whole bunch of requests until we get to one that expects a
557     response).  I know that the kerberos code doesn't wait in this
558     fashion, but that probably can cause network deadlocks and perhaps
559     future problems running over a transport which is more transaction
560     oriented than TCP.  On the other hand I'm not sure it is wise to
561     make the client conduct a lengthy upload only to find there is an
562     authentication failure.
563
564   * The protocol uses an extra network turnaround for protocol
565     negotiation (`valid-requests').  It might be nice to avoid this by
566     having the client be able to send requests and tell the server to
567     ignore them if they are unrecognized (different requests could
568     produce a fatal error if unrecognized).  To do this there should
569     be a standard syntax for requests.  For example, perhaps all
570     future requests should be a single line, with mechanisms analogous
571     to `Argumentx', or several requests working together, to provide
572     greater amounts of information.  Or there might be a standard
573     mechanism for counted data (analogous to that used by `Modified')
574     or continuation lines (like a generalized `Argumentx').  It would
575     be useful to compare what HTTP is planning in this area; last I
576     looked they were contemplating something called Protocol Extension
577     Protocol but I haven't looked at the relevant IETF documents in
578     any detail.  Obviously, we want something as simple as possible
579     (but no simpler).
580
581   * The scrambling algorithm in the CVS client and server actually
582     support more characters than those documented in *Note Password
583     scrambling::.  Someday we are going to either have to document
584     them all (but this is not as easy as it may look, see below), or
585     (gradually and with adequate process) phase out the support for
586     other characters in the CVS implementation.  This business of
587     having the feature partly undocumented isn't a desirable state
588     long-term.
589
590     The problem with documenting other characters is that unless we
591     know what character set is in use, there is no way to make a
592     password portable from one system to another.  For example, a with
593     a circle on top might have different encodings in different
594     character sets.
595
596     It _almost_ works to say that the client picks an arbitrary,
597     unknown character set (indeed, having the CVS client know what
598     character set the user has in mind is a hard problem otherwise),
599     and scrambles according to a certain octet<->octet mapping.  There
600     are two problems with this.  One is that the protocol has no way
601     to transmit character 10 decimal (linefeed), and the current
602     server and clients have no way to handle 0 decimal (NUL).  This
603     may cause problems with certain multibyte character sets, in which
604     octets 10 and 0 will appear in the middle of other characters.
605     The other problem, which is more minor and possibly not worth
606     worrying about, is that someone can type a password on one system
607     and then go to another system which uses a different encoding for
608     the same characters, and have their password not work.
609
610     The restriction to the ISO646 invariant subset is the best
611     approach for strings which are not particularly significant to
612     users.  Passwords are visible enough that this is somewhat
613     doubtful as applied here.  ISO646 does, however, have the virtue
614     (!?) of offending everyone.  It is easy to say "But the $ is right
615     on people's keyboards!  Surely we can't forbid that".  From a
616     human factors point of view, that makes quite a bit of sense.  The
617     contrary argument, of course, is that a with a circle on top, or
618     some of the characters poorly handled by Unicode, are on
619     _someone_'s keyboard.
620
621
622
623