RFC 666

Specification of the Unified User-Level Protocol

๐Ÿ“… published November 1974, from ietf

RFC 666: Specification of the Unified User-Level Protocol ๐Ÿ’–

Okay bestie, this one is by M. Padlipsky from the Network Working Group ๐ŸŽ€ It's RFC 666, with NIC 31396, dated 26 November 1974 ๐ŸŒธ The header doesn't list a category, and it doesn't say what it obsoletes or updates, so there's no drama there โœจ

After lots of chat about my RFC 451, I realized the "Unified User-Level Protocol" I'd pitched there had quietly turned into what it was always secretly about: a common command language ๐Ÿ’… Here's why that version is iconic and also goes way beyond the original goals ๐Ÿงš

  1. User convenience. The NWG has finally admitted that regular users, not just system programmers, deserve a good time on the Network, and the common editor "neted" proved people actually love this ๐Ÿ˜ญ Letting users call the same generic functions, including "batch" jobs, no matter which Server Host they're on is a seriously strong reason to do this ๐Ÿ’œ The goal is generic stuff that "all" Servers do in some form, so it's about the common command subset, not making the language fancy ๐Ÿ™ˆ It's an easy way to get a lot done, not a complicated way to get "everything" done ๐Ÿซถ
  2. "Resource sharing". The NWG is also super into "automatic" or program-driven use of resources on foreign systems right now ๐Ÿ‘‘ To pull that off without falling into the old "n by m problem" of the Telnet Protocol (where n Hosts would have to track m command languages, yikes ๐Ÿ’€), you need a common intermediate representation. Making it human-usable kills two birds with one stone, which I'll explain in the next point ๐Ÿฆ‹
  3. Economy of mechanism. In RFC 451 I argued that one user-level protocol connected via socket 1 and Telnet would save effort, since new responders wouldn't have to service Initial Connection Protocols socket after socket as protocol after protocol popped up ๐ŸŒˆ That still holds, but resource sharing makes the savings even bigger ๐Ÿ”ฅ If the common command language is designed for users to use directly, as this proposal is, then users on terminal-support "mini-Hosts" (like ANTS and TIPs) don't need an intermediary server just to work on a particular Server in the common language ๐Ÿ˜ค This matters even more because many of those users aren't professional programmers and don't know any command language at all ๐Ÿฅบ If resource sharing used an intermediate language that's only good for programs, you'd have to learn Server B's native command language just to avoid paying for Server A only to reach B's generic functions ๐Ÿ’€ And you might still have to learn Server A's native language anyway, even if using two Servers where one would do wasn't an issue ๐Ÿ™ƒ
  4. Front-ending. The common command language here is mostly meant to sit in front of existing commands, which means nobody has to throw out their current implementations ๐ŸŒท The whole approach is about adding a common command language on top of "native" command languages instead of replacing them, because trying to legislate away all the richness of existing command languages would be unworkable and also a bad idea ๐Ÿ™…โ€โ™€๏ธ Since it's a closed environment, there are no naming conflicts with native commands either ๐ŸŽ€
  5. Accounting and authentication. There's been a whole pile of RFCs about the FTP's implications for accounting for Network service use and authenticating users' identities (Bressler's RFC 487, Pogran's RFC 501, my RFC 505, and even 491), and this area is still unresolved ๐Ÿ˜ฉ The generic login command proposed here should help, since it lets the Server attach an appropriate process to the connection and, if it wants, handle accounting and access control too ๐Ÿ’–
  6. Process-process functions. By allowing foreign object programs to be invoked, this proposal gives a framework for process-to-process functions like "parallelism" (see the discussion of the call command below) โญ The UULP isn't a magic fix for everything: the actual transactions probably won't be in the common command language, though some could be ๐Ÿคทโ€โ™€๏ธ What it does give you is a known way to get those special-cased programs running elsewhere ๐Ÿงš It's also a handy place to put new functions we'd like to make generic later, like Day's File Access Protocol ๐Ÿ“

All of which seems like a lot of mileage to get out of being tired of remembering whether you check who's logged in with systat, users, s.who:c, listf tty, or who.... ๐Ÿ˜ญ๐Ÿ’…

Context

Eventually this is supposed to become the general responder to the Initial Connection Protocol ๐Ÿฆ‹ For now, the UULP is going to be a Telnet "negotiated option" ๐ŸŒธ When the option is enabled, the Server Host provides a command environment that supports the common conventions and commands discussed here โœจ

In a way, the UULP is a "selector" ๐Ÿ‘‘ The common command subset includes commands for leaving the common command environment and entering various other environments, similar to CCN's current Telnet Server ๐Ÿ’œ To leave the UULP environment and reach the "native" command processor, you use the UULP command local (see also the discussion of Case, below) ๐Ÿซถ All commands end with Telnet "Newline" (currently cr-lf) unless the eol command changes that, and the internal separator is a space (blank) ๐ŸŽ€ (Entering other environments, like the FTP Server, is discussed below ๐Ÿงš)

There are two reasons for a mechanism other than just de-negotiating the option, even though that seems like the obvious move ๐Ÿ™ˆ First, it's way more convenient for users to type a command than to escape to their User Telnet program to turn the option off ๐Ÿ˜ญ Second, the hope is that the UULP will eventually be made the default environment for any Network login ๐ŸŒˆ If that happens, the natural way to get into the Server's "native" command environment would be a UULP command ๐Ÿ”ฅ

Note: all UULP commands discussed herein are listed in Appendix 1, categorized as to optionality, with brief descriptions given. The appendix may be taken as a first-pass UULP Users' Manual ๐Ÿ“–๐Ÿ’–

Responses

Any optional commands that a particular Server doesn't support have to get a message of the form Not implemented: commandname., where commandname is the name of the command that was requested ๐Ÿ’… Note that throughout this document, all literals must be sent exactly as specified, so that Servers can be driven by programs (including "automata" or "command macros") as well as "live" users ๐Ÿค–๐Ÿซถ

In general, the view here is that a small set of literal, constrained responses beats a huge variety of numerically coded responses where the text can vary ๐ŸŒธ Again, the goal is an economy of mechanism ๐Ÿ’œ With coded responses, someone has to coordinate the code assignments, and that's a headache nobody needs ๐Ÿ™ƒ Also, experience with FTP shows that when there are lots of codes, there are lots of ambiguities ๐Ÿ˜ตโ€๐Ÿ’ซ (The sender may have a perfectly valid case for choosing, say, 452, while the receiver may have an equally good reading of the codes' definitions for expecting, say, 453.) Experience with a related "error table" mechanism on Multics backs this up, since coded responses cause both managerial and technical problems ๐Ÿงš A last objection to numeric codes might seem irrelevant to some, but the aesthetics do deserve some attention ๐ŸŒˆ And when live users are on the common command language, they'd just get distracted by all those numbers flying around ๐Ÿ“ (We can't assume the numbers could be stripped out by their "User UULP", because one of the basic goals is to make it easy enough for a user at a TIP to deal with ๐Ÿฆ‹)

Arguments

During review, it became clear that some global comments on arguments were needed ๐Ÿซถ Two areas in particular seem to have caused confusion: how arguments are specified on the command line, and the question of "control arguments" ๐Ÿ’… On the first point, you have to remember the goal of "front-endability" ๐Ÿ‘‘ Picture two native implementations of one command: one (A) collects its arguments by asking the user, and the other (B) expects to receive them when it's invoked (called as a closed subroutine) ๐Ÿค” It's easy to imagine a "Server UULP" feeding arguments to A as needed without rewriting A ๐ŸŒท But it's really hard to see how B could ask for its arguments without a lot of rewriting ๐Ÿ˜ฉ So a "least common denominator" approach, where arguments are specified in advance, costs the least in reworking existing implementations ๐Ÿ’–

On the second point, I borrowed the "control arguments" idea from the Multics command language's convention, because it's really handy in practice โœจ The key is that some arguments are literals, usually picking a mode or control function for the command, while others are variables, like a particular file name or user identifier ๐ŸŒธ A typical example is a "mail" command, where the variables are the user identifiers and Host identifiers, and the "control argument" is the marker that says user identifiers have ended and Host identifiers have begun ๐Ÿ’œ The convention here is to start the control argument with a hyphen, since that character never seems to be used to start variable arguments ๐ŸŽ€ So in the mail example we use -at ๐Ÿฆ‹ It's not a deep philosophical point, but this approach means argument lists don't depend on order, and honestly, it just feels right to me ๐Ÿซถ๐ŸŒˆ

Case ๐ŸŽ€

Okay so this is giving "legislated out of existence," bc the Telnet Protocol's Network Virtual Terminal keyboard spec was supposed to make upper-case-only terminals a non-issue ๐Ÿ’…. In practice? Still a thorny one ๐Ÿ˜ญ. There are two aspects: the alphabetic case of commands, and the ability to cause "case-mapping" so lower-case input works ๐Ÿฆ‹.

Some Servers have zero local problems with the first aspect, bc they run internally in all upper-case or all lower-case and just map all input appropriately โœจ. (Problems do arise tho when you're using the User FTP on such a system to deal with a mixed-case system, for example ๐Ÿ™ˆ.) Other Servers do attach the normal linguistic meaning to case ๐Ÿ“š. (E.g., Smith's name is Smith -- not SMITH, and not smith.) To minimise superfluous processing for Servers that are indifferent to case ๐ŸŒธ, all UULP commands are to be recognized as such whether they arrive as all upper-case or all lower-case. (They'll be shown here as all lower just for typing convenience ๐Ÿ’œ.) Note that arbitrarily mixed case is not recognized, bc it's an unwarranted assumption about local implementation to suppose that input will necessarily be case-mapped ๐Ÿ™….

On the second aspect, any Server which does distinguish between upper- and lower-case in commands' arguments (a.k.a. parameters) must furnish a UULP "map" command as specified in Appendix 2, in order to support logins from upper-case-only terminals attached to User Hosts which either do not support the Telnet Protocol's dictum that all 128 ASCII codes must be generable, or support it awkwardly ๐Ÿ”ฅ. Honestly this seems simpler and more preferable than legislating that upper-case Network-wide personal identifiers (and maybe even Network Virtual Path Names) be pre-conditions to a usable common command subset ๐Ÿ™„. (As noted below, these latter concepts will fit in smoothly when they're agreed upon. The point, though, is that we don't need to deprive ourselves of the benefits of a UULP until they're agreed upon ๐Ÿ‘‘.)


User Names ๐ŸŒˆ

As implied above, the various Servers have their various ways of expressing users' names ๐Ÿ™ƒ. Clearly, the principle of economy of memory dictates that there should be a common intermediate representation of names in and for the Network ๐Ÿง . It's probably also clear that this representation will be based upon the Network Information Center's "NIC ID's". However, it is unfortunately amply clear that an acceptable mechanism for securing up-to-date information cannot be legislated here ๐Ÿ˜ฉ, much less a mechanism for securely updating the implied data base. Therefore, at this stage the sensible thing to do is specify only the UULP syntax for conveying to the Server the fact that it is to treat a user name as a Network-wide name rather than as a local name, and let the supporting mechanisms evolve as they may ๐Ÿฆ‹.

The prefacing of a name with an asterisk (*) denotes a Network-wide name. (Such names may be either all upper-case or all lower-case, as with UULP commands' names.) The name *free is explicitly reserved to mean that (in the context of logging in) a login is desired on a supported or sampling account, if such an account is available ๐Ÿ†“. The response if no such account is available is to be Invalid ident: *free. When Network-wide names are generally available, Servers will either map them into local names or cause them to be registered as local names, as they prefer ๐Ÿซถ. The point is that a Network-wide name will be "made to work" by the Server in the context of the UULP ๐Ÿ’–.


Special Characters and Signals โญ

Another area where the facts of life have to outweigh the letter of the Telnet Protocol, if users' convenience is going to be served, is that of "erase" and "kill" characters ๐Ÿ˜ญ. It's possible that User Telnets will uniformly facilitate the transmission of the Telnet control codes for generic character erase and generic line kill. It is certain, though, that User Telnets will differ -- and users who use more than one User Telnet will, again, be placed in the uncomfortable position of developing too many sets of reflexes ๐Ÿ’€. Therefore, the UULP will optionally support the following commands: erase char and kill char, where char is a printable ASCII character (to avoid possible conflicts with "control characters" which are recognized in the innermost areas of particular operating systems) ๐Ÿงš. Presumably, unwary users can be instructed not to choose an alphabetic, so they don't end up in a spot where they can't invoke certain commands (erase and kill themselves, for example, in which case they couldn't be changed) ๐Ÿ™ˆ.

These commands are supplements to the related Telnet control codes, and have the same meanings ๐ŸŽ€. The point is that it may be way more convenient for a user to say erase # and get the # recognized as the erase character by the Server, than for them to get their User Telnet to send the Telnet equivalent โœจ. The commands are designated as optional because they may lead to severe implementation problems on some Servers, and because the equivalent functions do, after all, exist in Telnet ๐Ÿ’….

Note: the erasing is assumed to be performed "as early as possible". That is, the sequence erase x erase x should come out equivalent to erase x erase -- the second appearance of x resulting in the erasing of the space in the command line. Presumably, this is a sufficiently uncommon path that anomalous results would be tolerated by the user community, but the intent ought to be clear ๐Ÿ™ˆ.

The Telnet "synch" and "break" mechanisms are, by their very nature, best left to Telnet ๐Ÿ™…. End of line, however, might well be a different story ๐Ÿ’ก. Therefore, as a potential convenience, the UULP optionally supports eol char to ask the Server to treat char as the end of line character thenceforth. To revert to Telnet Newline, use eol (i.e., no argument, current terminator) ๐ŸŒˆ.


Prompts ๐Ÿ’ฌ

Another way Servers vary while being the same is in how they indicate "being at command level" ๐Ÿคท. Some output "ready messages"; others, "prompt characters". For the UULP, where some functions will be performed by means of a command's logging in to another system, the ability to specify a known prompt character is extremely desirable ๐Ÿ”ฅ. The UULP command is prompt char, where char is the character which is to be sent when the user's process (on the Server) is at command level. It is explicitly permitted to prefix char to a line consisting of a "native" prompt or ready message. Also, this command is explicitly acknowledged to be permissible prior to login ๐Ÿซถ. (Again, a heads-up: users must be warned about the bad results which can ensue if an alphabetic character is chosen ๐Ÿ’€.)

Note: "prompt", "eol", "erase", and "kill" may all be re-invoked with a new value of char in order to change the relevant setting; all may be turned off by invocation with no argument.

Login ๐Ÿ”

Perhaps the stickiest wicket of them all is the attempt to specify a generic login, but here we go ๐Ÿ˜ค. The UULP login command is login userident, where userident is either a locally-acceptable user identifier or a Network-wide identifier as discussed above. Note that, for utility in contexts to be discussed later, the locally-acceptable form must not contain spaces ๐Ÿ“. Servers may respond to the login attempt with arbitrary text (such as a "message of the day"), but some line of the response must be one of the following: a prompt (as discussed above; indicating, in the present context, successful login); Password:; or Invalid ident: userident. When passwords are required, it is the Server's responsibility either to send a mask or to successfully negotiate the Hide Your Input option ๐Ÿ™ˆ.

Note that login *free is specifically defined to require no password. (If a "freeloader" has access to a User Telnet and has learned of the *free syntax, it is fruitless to assume that he couldn't have also read the common password ๐Ÿ™ƒ.) If a password must be given, acceptable responses are arbitrary text containing a line beginning either with a prompt or with Login unsuccessful. or with Account:. If an account is requested, the responses must be either the Login unsuccessful message or the text containing a prompt already described. If any errors occur during the login sequence, users are to re-try by starting from the login command. (I.e., it is not required that the Server "remember" idents or passwords.) ๐Ÿง 

It is explicitly acknowledged that an acceptable response to login *free is Limited access only. (followed by a prompt) โœจ. This is intended to warn (human) users that the free account on the Server in question exists only to allow such functions as accepting mail and telling if a particular user happens to be logged in ๐Ÿ“ฌ. (For objections to "loginless" performance of such tasks, see RFC 491. Note also that nothing here says that a Server must do anything other than return a prompt in response to login *free in the event that loginless operation is natural to it.) Given the UULP login discipline and the "prompt" command, it is reasonably straightforward for a program to login on a free account and perform one of these functions, for if the login command succeeded, the program will "see" a guaranteed prompt character ๐Ÿค–.

To make life simpler for those Hosts which normally have some sort of "daemon" process service mail and the like, a further expansion to login is in order ๐Ÿงš. The point is that some Hosts may not know what sort of process to pass an unqualified login *free to, whereas they'd be sure what to do with an explicit request to process mail, do a who command, or set up console to console communications ๐Ÿ’Œ. Therefore, UULP "login" will allow a "control argument" (as discussed above) of either -mail, -who, or -concom, and the respective UULP commands involved must use the respective strings in any login line they transmit. Again, nothing is being said about what a Server has to do with the information, but some Servers need/want it ๐Ÿซถ.

Usage Information ๐Ÿ“šโœจ

Okay bestie, most Servers have some kind of on-line docs, from little calling-sequence cheat sheets all the way up to full users' manuals ๐Ÿ“–๐Ÿ’–. In the UULP world there are two kinds of info that matter: "normal" system info, and info about that particular Server's UULP implementation ๐ŸŽ€. To learn how "native" commands work, the UULP command is help -sys (or just ? for short) ๐Ÿ”. Quick heads-up: -sys counts as a "control argument," so it gets a hyphen (-) in front. That keeps it from getting mixed up with other kinds of names, like command names ๐Ÿ’….

To get the description of the Server's UULP implementation, use help -uulp ๐Ÿงš. For a particular UULP command's implementation, it's help comname ๐ŸŒธ. And if you ever forget how the help command works, just type help ๐Ÿ™ˆ.

Note: just like command names and Network-wide user names, control arguments can be all upper-case or all lower-case โœจ.

It's officially fine to reply "No peculiarities." to help comname if there's nothing interesting to say about how that Server does the UULP command in question ๐Ÿ™Œ. (Honestly, we're saving everyone from reading a dozen users' manuals, so the least they can do is read the UULP command list ๐Ÿ’€.) Hosts who want to be a little chattier can share stuff like which local command gets invoked (if there is one), argument syntax (like a pathname description, or the name of a help file about pathnames), "To be implemented.", or even "Not to be implemented." ๐Ÿ—ฃ๏ธ๐Ÿ’…


"Mail" ๐Ÿ“ฌ

Yes, a separate mail protocol is being cooked up for general purposes ๐Ÿณ, but UULP still has to cover mail. Since it's login-based, it lets systems that do access control and sender authentication on mail make those abilities available to users inside its generic functions ๐Ÿ”. So, to read your mailbox, the UULP command is readmail ๐Ÿ’Œ. To have "live" input collected and sent to a local user, use mail userident. To a remote user, use mail userident -at hostname, where the arguments mean what you'd expect ๐Ÿ’. To send a file you already made, it's mail -f filename userident -at hostname ๐Ÿ“Ž.

You can give several useridents, separated by space (blank) ๐Ÿ‘ฏ. Same deal for hostnames. If both are lists, they should be treated pairwise ๐Ÿ’–. (A fancier syntax could be invented for sending to several users at one host and then other users at other hosts, but it doesn't seem necessary yet, since multiple invocations get the job done โœจ.)

The mail command starts the message with a line identifying the sender (Host and time are desirable, but not mandatory) ๐Ÿ•ฐ๏ธ. For "live" collection, the end of the message is marked by a line with only a period (.), followed by the regnant line terminator (basically whatever is in charge right now, usually the Telnet Newline, but see also the discussion of the eol command) ๐Ÿฆ‹. If remote mail doesn't get sent successfully, it is to be saved in a local file, and that file's name is output as part of the failure message ๐Ÿ“. ("Queueing" for later transmission is admired, but not required ๐Ÿซถ.) The transmission mechanism will follow the general mail protocol.

Heads-up: when you use an -at clause, the mail command will send login *free -mail to the remote Host(s), followed by a mail command with no -at clause ๐Ÿš€.

A desirable, but not required, glow-up for readmail would be accepting a Host name (-at hostname). That would make the local Host go off to the named Host (via login *free -mail) and check for mail there ๐ŸŒˆ. Several hostnames could, of course, be specified. An even bigger embellishment, which would probably be quite expensive, would be accepting -all as a request to check all Hosts (or, perhaps, all Hosts known to have a free account for the purpose) for mail ๐Ÿ’ธ.


Direct Communication ๐Ÿ’ฌ

Many users are obsessed with exchanging messages directly with other logged-in users, and it's honestly iconic ๐Ÿ”ฅ. Even though this function is kind of outside the purview of the UULP, we're going to cover it anyway, after a little digression ๐Ÿซฃ.

Digression, bestie: The UULP assumes there can be straightforward "front ends" at the various Servers that translate generic function calls in a common spelling into calls for specific, pre-existing "native" functions ๐Ÿงฉ. For console to console communications, though, that premise doesn't really hold ๐Ÿ’€. The problem is that both major "native" implementations known to the author are seriously flawed. The TENEX "link" mechanism is both insecure (you've got no business seeing everything I type, even if I'm careless enough to let you ๐Ÿ™…โ€โ™€๏ธ) and inconvenient (why should I be forced to remember that pesky semi-colon? how do I get back into phase after I've forgotten one?). It's also likely to be extremely difficult to simulate on systems that don't force Network I/O through local TTY buffers, even if the user interface weren't subject to criticism. The Multics "send_message" mechanism, on the other hand, has a more sophisticated design, but it's absurdly expensive ๐Ÿค‘. So the UULP mechanism described here assumes that, for this function, new local implementations will be developed to support it ๐Ÿ› ๏ธ.

To permit console to console communications, use concom -on. To refuse them, use concom -off ๐Ÿšซ. Default is off ๐Ÿ’ค. To enter message-sending mode, use concom userident -at hostname (the -at clause is optional) โœ‰๏ธ. To exit message-sending mode, type a line consisting of only a period (cf. Mail, above) ๐Ÿ‘‹. While in message-sending mode, each line will be transmitted as a unit ๐Ÿ“ฆ. The first message sent by concom must be prefaced by an identifying line, beginning From: and containing an appropriate address to reply to ๐Ÿชช. The closing period-only line should be transmitted, so the other concom can close as well ๐ŸŒ™.

The acceptable error response is Not available: userident. That one is so clever, because it neither confirms nor denies that the user exists, which is a big deal on the security front ๐Ÿ›ก๏ธ๐Ÿ”. The command must, of course, do whatever is necessary to transmit the messages. In other words, if it's invoked locally, it accesses the local mechanism, and if it's invoked for remote communications, it accesses the remote Host's concom command (via login *free -concom) ๐Ÿ›ฐ๏ธ. So a user at a TIP would use the local form of concom on the Host of the other party if that's convenient, or would use the remote form on their "usual" Server if direct use is inconvenient for some reason (like having no account there, say) ๐Ÿงš.

The prerequisites for setting up communications are finding out whether the user is logged in, and what "address" to use if so ๐Ÿ‘€. The way to gather that info is an expanded who command. (Note that who is the UULP command that invokes the generic who's-logged-in function, with no constraints on the format of the reply ๐Ÿ—’๏ธ.) The syntax is who userident -at hostname, where both arguments may be multiple ๐ŸŒท. With no -at clause, only the local Host gets checked ๐Ÿ . The response must begin with From hostname: userident:, followed by either an appropriate address (for example, ll if the local concom uses TTY numbers and userident is logged in on TTY ll) or Not available. ๐ŸŽฏ

As with mail, a -all embellishment might be pleasant ๐ŸŒˆ. Heads-up: the search for the specified user(s), whether or not -all is used, still assumes that a login *free -who login will be used on the appropriate remote Host(s), followed by who userident ๐Ÿ”Ž. That's why responses to the expanded who command have to be so rigidly specified ๐Ÿ“. Also, regardless of whether the inquiry is made in terms of a Network-wide or local user name, the response must be appropriate for use in concom ๐Ÿ’….

"Good" concom implementations will presumably run an expanded who command automatically, so the user doesn't have to do it separately ๐Ÿช„. In fact, the -concom control argument to login is defined to imply the ability to do a who as well as a concom, to cater to this possibility ๐Ÿ’ซ. It's tempting to legislate that this approach be the rule, but the implementation implications aren't quite clear enough to do that yet ๐Ÿค”. The implicit who should be viewed as a strong hint to implementers, though ๐Ÿ’œ.

File Creation and Manipulation โœจ

okay so the common command subset has to let you create and manipulate files ๐Ÿ“ creating is needed for sending mail AND for making source files you'll compile later. manipulation (copying, renaming, typing stuff out, etc.) is needed too ๐Ÿ’… it's a convenience for users who only want to stick to the common command language, and it's also how you run batch functions (more on that below). for file manipulation you could enter the File Transfer Protocol environment, but ngl the FTP user interface is super program-drivable and lacks abbreviations ๐Ÿ˜ญ the lack of mnemonicity from limiting command names to four characters is real too. and some valuable stuff, like causing a file to be typed out, isn't covered at all. so the various UULP file manipulation commands live in Appendix 1 ๐ŸŽ€ they don't need a deep dive here, but here's some context:

The file manipulation commands assume that all Servers have some notion roughly matching "the user's working directory" ๐Ÿ—‚๏ธ every file name, whether it's the yet-to-be-invented Network Virtual Pathname or a "local" one, is taken to refer to files in that directory unless you say otherwise. so you shouldn't have to type "dsk:" or anything like it. when you refer to file "x," you mean "the file named 'x' in my current working directory," and the Server just knows that ๐Ÿซถ

At this stage of UULP development, it doesn't seem fruitful to explain the next statement in detail ๐Ÿ™ˆ for now, just know that file manipulation commands that need to do something with a foreign file (copying one, for example) use the FTP, and that's the whole story. as the context and implications of the protocol get more widely understood, detailed implementation notes will be added to the file commands, and the other commands will probably get refined too ๐ŸŒธ in a way, the common file commands can be seen as a kind of "User FTP" with a known human interface when they deal with foreign files. (and of course, until there's a Network virtual pathname, this issue doesn't really come up ๐Ÿ’€)

I expect an "identify" command might be desirable, so that UULP commands which have to access other Servers on behalf of the specific current user have the login information they need ๐Ÿ”‘ one is included in Appendix 1, but it's speculation for now, so don't get too attached ๐Ÿ’œ

Okay, now file creation, which is where things get messy ๐Ÿ˜ฉ it's clear that being able to create files in the UULP environment is extremely desirable. it's also clear that sending mail to a fake address to get the file created, and then renaming the "unsent mail" file, is way too byzantine for anyone to expect of users ๐Ÿ’€ the bad news is it's not clear what the alternative is. it's pretty clear we need a common editor, but it's not at all clear which editor it should be.

Two widely-known editors come to mind: TECO and QED ๐Ÿงš however, not everybody has them. and even if everybody did, the "dialects" problem is going to be a big one ๐Ÿ˜ญ even if all the relevant system programmers agreed, there's still the question of whether the intended user population would bother learning a language as complex as TECO or QED. so an optional UULP command called "neted" is proposed ๐Ÿฆ‹ (see also RFC 569.) it's a line-oriented context editor. no "regular expressions," but also no line numbers ๐ŸŒˆ it's copiously documented in Chapter 4 of the Multics Programmers' Manual, including an annotated listing of the (PL/I) source code ๐Ÿ“š a simple user's guide has been prepared too (see Appendix 3). several implementations already exist, and commitments have been made for more โœจ it may also be repugnant to some of the system programmers who'd have to implement it, which is exactly why it's optional, until and unless higher authority makes it mandatory ๐Ÿ‘‘


Other Protocols ๐ŸŽ€

okay so the nominal starting point for proposing a UULP was letting new Network user protocols be invoked through one common mechanism ๐Ÿ’– the alternative was building a new responding mechanism for a new contact socket for every single protocol, which is a lot. even though this goal got shoved to the background once the true goal of the UULP was admitted, it hasn't been dropped completely ๐Ÿซถ so to enter the FTP Server environment, the UULP command is ftp, and to enter the RJE Server environment, the UULP command is rje. exiting works the way each respective protocol says it does. (where possible, exit should take you back to the UULP environment ๐ŸŒธ)


Invoking Foreign Programs ๐Ÿ”ฅ

there are two broad contexts where you'd want a specific local program invoked from the common command environment ๐Ÿ‘€ in the first, the User side of the connection is itself a program, and the Server side program is one that's specifically cooperating with it. this one is the more sophisticated context, obviously โœจ the less sophisticated context assumes the User side is a "live" user, and they want to invoke a compiler or an object program they've already compiled, all in the common language ๐Ÿ“ again, it's a convenience, so they can operate in a sort of "Server-transparent" mode. (the latter case also covers "batch" use of the Server; see below.) in both contexts, the big job of the UULP is to specify the mechanisms through which the particular programs get invoked, no matter how idiosyncratic the Servers' command languages are ๐Ÿ’…

Programming languages are way too big a problem to tackle here ๐Ÿ˜ญ but let's say a user somehow manages to create a source program. they still want some commonality of spelling when invoking the right compiler, or even the object program ๐Ÿงš so an optional but strongly recommended UULP command is "call name," which should invoke object program name (where the named program may be a "native" command with arguments specified as appropriate) ๐ŸŽ€ the values "pl1," "-basic," "-fortran," "-lisp," etc. should be recognized as requesting invocation of the appropriate language processor. it operates on a named source file, or runs interpretively/interactively if no source file was named, with "reasonable" defaults in effect ๐Ÿ’œ and note that this all implies "native" commands aren't directly invokable from the UULP environment (other than through "call"). that's to avoid potential naming conflicts between system commands and new UULP commands ๐Ÿ™ˆ

Note that the "call" command in the UULP environment constitutes a rubric for "parallel" computation, given any ad hoc convention for the return of completion information. (Writing on the Telnet write socket plus 2 would seem appropriate, provided the initiator has the ability to "listen" for the rfc; but even a response in the data stream as a special-cased program is assumed on the "user"side anyway.)

Other Matters ๐ŸŒˆ

the topic of "batch" mode deserves some attention โญ like with the file manipulation commands, more consultation is needed before there's a firm spec ๐Ÿ˜ญ but I suspect a "-batch" control argument to login should start batch mode processing by the Server ๐Ÿ’– given the call and identify commands, all we'd then need is a convention for designating the output file, so it can be returned via a copy command in the "job" itself (if the output is to be returned rather than stored at the Server) ๐Ÿซถ of course, -batch will probably need some substructure around password and timing matters. more details will come out in this area in future iterations ๐Ÿ”ฎ

here's an admittedly fictionalized scenario ๐Ÿงš

login Me -batch -pw xxx -shift 3
copy *452<me>source.text source.pl2
call -pl2 source
call source input output
identify Me2 yyy
copy output *555>root>Me>output452
logout

so user "Me" wants the Server receiving the commands (either directly from them at a TIP, or from some other Server where they've created a file containing the commands) to set up a batch job, with password "xxx," to run on Shift 3 (whenever that is) ๐Ÿฆ‹ the job first copies file "source.text" from directory "<me>" on Host 452 into local file "source.pl2," then compiles it with the local PL2 compiler, then executes it (assuming a "Not found" response would go into a known file if compilation had failed) with specified arguments (presumably the names of the input and output files). then it copies the "output" file to Host 555's file hierarchy at the indicated place, using the user identifier "Me2" and the password "yyy" ๐Ÿ’… it's not elegant, but it ought to work ๐Ÿ˜‚

and finally, logging out ๐Ÿ‘‹ the UULP command is "logout." the Server must close the Telnet connection after doing whatever's appropriate to effect a logout. to keep the Telnet connection open, use logout -save ๐ŸŒธ having the Server do the closing is a convenience for the user, since it spares them from having to close their User Telnet themselves ๐Ÿซถ it's also great for program-driven applications, so connections don't get left "dangling" and nobody has to do possibly complex negotiations with the User side just to break the connection ๐Ÿ’œ

Appendix 1. The Common Command Subset ๐Ÿ’…โœจ

okay bestie, this appendix is basically the greatest hits list of UULP commands ๐ŸŽง Everything's sorted into five groups: set-up, communications, file stuff, invoking native programs, and on-line docs. The Opt column is copied exactly as it appears in the original, so the X and XX marks stay right where they are ๐Ÿซถ

I. "Set-up" Commands ๐ŸŽ€

Syntax                                                   Opt

login id arg
prompt char
erase char                                                X
kill char                                                 X
eol char                                                  X
local
ftp
rje
logout
logout -save
map
identify id arg                                            X
  • login id arg: the id can be Network-wide or Host-specific ๐ŸŒ *free is reserved, so don't go trying to use it. The arg can be -mail, -who, -concom, or -batch, or you can leave it off entirely. The result is either that you get logged in, or you get passed off to the right daemon ๐Ÿงš
  • prompt char: makes char become the normal prompt message, or sit right in front of it ๐Ÿ’– You can do this before you log in.
  • erase char: sets char as the erase character ๐Ÿงฝ Calling it with no argument brings back the default.
  • kill char: same energy, but for the kill character ๐Ÿ”ช No argument, back to default.
  • eol char: sets char as the newline character โ†ฉ๏ธ No argument, back to default.
  • local: takes you into the local command environment ๐Ÿ 
  • ftp: takes you into the FTP environment ๐Ÿ“‚
  • rje: takes you into the RJE environment ๐Ÿ–จ๏ธ
  • logout: logs you out and severs the Telnet connection, so it's a full exit ๐Ÿ‘‹
  • logout -save: logs you out but keeps the Telnet connection alive ๐Ÿซง
  • map: applies the case-mapping conventions from Appendix 2. It's required on Hosts where case is significant ๐Ÿ” 
  • identify id arg: sets id as your user identifier for any "fanout" logins that are required ๐Ÿชช If you add an arg, it's either the password for those logins or -pw. With -pw, the Server will either furnish a mask or negotiate the Hide Your Input Telnet option ๐Ÿ™ˆ If there's no arg, no password gets furnished on fanout logins. The default id is *free ๐Ÿ’…

II. Communications Commands ๐Ÿ’ฌ

readmail
readmail (id) -at host                                     X
readmail -all                                              XX
mail id
mail -f file id
mail id -at host
mail -f file id -at host
who
who id
who id -at host
concom -on
concom -off
concom id
concom id -at host
  • readmail: types out "mailbox" ๐Ÿ“ฌ
  • readmail (id) -at host: types out "mailbox" on remote Host host ๐ŸŒ You can list several Hosts, separated by spaces (blanks). It implies you can change the working directory at that host to the one implied by your known user identifier, or by id if you give one ๐Ÿ“
  • readmail -all: searches for mail ๐Ÿ” This one is extremely optional, bestie, no pressure ๐Ÿ˜ญ
  • mail id: collects input until a line with only a period (".") shows up, then mails it to the local user id ๐Ÿ’Œ
  • mail -f file id: sends the contents of the specified file to the specified local user ๐Ÿ“Ž
  • mail id -at host: collects input until the lone period line, then mails it to the remote user(s) at the specified Host(s) โœ‰๏ธ Both id and host can be multiple, separated by spaces. If there are multiple ones, they should be taken pairwise ๐Ÿ‘ฏ
  • mail -f file id -at host: sends the file's contents to the remote user(s) ๐Ÿš€
  • who: the generic "who's logged in" command ๐Ÿ‘€
  • who id: asks whether id is logged in. The responses are constrained ๐Ÿค
  • who id -at host: asks whether the specified user is logged in at the specified host. Constrained responses again ๐Ÿค
  • concom -on: enables console to console communications ๐Ÿ–ฅ๏ธ
  • concom -off: disables console to console communications ๐Ÿ›‘
  • concom id: sends messages to the specified local user until a line with only a period (".") shows up ๐Ÿ’ฌ
  • concom id -at host: sends messages to the specified remote user ๐Ÿ“จ

III. File Commands ๐Ÿ—‚๏ธ

type path
listdir
listdir path
rename old new
addname old new                                             X
delete path
copy from to
link from to                                                X
status path st                                              X
changewd path                                               X
typewd
neted path
  • type path: types out the contents of the specified file ๐Ÿ“œ The pathname can be local or Network-wide. It defaults to the current working directory ๐Ÿงญ
  • listdir: lists the contents of the current working directory ๐Ÿ“‹ Local format is acceptable ๐Ÿซถ
  • listdir path: lists the contents of the specified directory ๐Ÿ—ƒ๏ธ
  • rename old new: changes the file's name to the one you indicate โœ๏ธ
  • addname old new: gives the specified file the specified extra name ๐Ÿท๏ธ
  • delete path: gets rid of the specified file ๐Ÿ—‘๏ธ It's "expunge" if necessary ๐Ÿ’€
  • copy from to: makes a copy of the file at the first pathname, at the second pathname ๐Ÿ‘ฏโ€โ™€๏ธ
  • link from to: if your file system has the concept, makes a "link" between the two pathnames ๐Ÿ”— If there's no second argument, it uses the same entry name in the working directory ๐Ÿช„
  • status path st: if your file system has the concept, gives status information about the specified file or directory ๐Ÿ“Š
  • changewd path: if there's no argument, it returns you to the "home" directory ๐Ÿก
  • typewd: types out the pathname of the current working directory ๐Ÿงพ
  • neted path: see Appendix 3 ๐Ÿ”Ž

IV. Invoking "Native" Programs โš™๏ธ

call name (args)
  • call name (args): invokes the specified program with the specified arguments, if there are any ๐Ÿš€ The names -pl1, -basic, -fortran, and -lisp are reserved to indicate invocation of the matching language processor, so those are off-limits for regular program names ๐Ÿ™…โ€โ™€๏ธ If no source file is indicated, it gets invoked "interpretively" if that's possible ๐Ÿงš

V. On-line Documentation ๐Ÿ“š

help name
  • help name: types out information about the specified UULP command ๐Ÿ“– If name is -sys, you get info about how to use the local system's help mechanism. If name is uulp, you get info about the local system's UULP implementation ๐Ÿซถ If no name is given, it describes the command itself ๐Ÿชž

Appendix 2. Map Command Conventions ๐Ÿ—บ๏ธ

This appendix will eventually contain the case-mapping conventions detailed in RFC 411. It's giving "coming soon" energy, bestie โœจ

Appendix 3. Edit Command Requests โœ๏ธ

This appendix will eventually contain descriptions of the neted command requests (a draft of which now exists), or a reference to the Resource Notebook version, if that gets published first. For now, it's enough to point out that the requests are basically locate, next, top, change, save, and quit. In other words, it's the "old-fashioned" flavor of context editor ๐Ÿ’œ

[Optical character recognition and initial proofreading performed 11/20-21/04 by The Author. A few original typos were corrected; some may remain.]
๐Ÿ“ฆ where this page comes from