Rhapsody Developer Release Copyright © 1997,
1998 by Apple Computer, Inc. All Rights Reserved.
This file contains release notes for the Rhapsody Developer Releases (1 and 2) of the Terminal application. For those familiar with Terminal in OpenStep for Mach, notes specific to this release are included. Also, a section is devoted to some of Terminal's less obvious features. Finally, this document includes information about Terminal's execution service, which is of interest mainly to developers.
The following new features have been added to the Terminal application in this release.
After restarting Terminal, the Shell>Library menu contains
an item for each of the abovementioned files.
These new bugs have appeared since OpenStep for Mach 4.2.
Reference |
1672382 |
Problem |
The Page Up and Page Down keys don't work. |
Reference |
1676977 |
Problem |
Characters lost when pasting text. |
Description |
Pasting a large body of text into a Terminal window will sometimes result in many of the characters being lost. |
ESC ] 0 ; "Title String" BEL
where ESC is '\033', and BEL is '\007'. The initial 0 may
alternatively be a 2. The following csh script code (which
can be added to a .cshrc file) shows one example of how you
can set the title bar to a "clipped" version of the current
directory. It also puts the hostname in the prompt in inverse
video:
# begin csh script to set the title bar to the current working directory set homedirectory = ~${user} alias shortpwd 'pwd|sed -e "s|^/private||" -e "s|${homedirectory}|~${user}|"' alias getTitle 'set titleString="`shortpwd|sed -e '\''s|.*[^/]\(/[^/]*/[^/]*/[^/]*/[^/]*\)|...\1|'\'' `"' getTitle if( ${?prompt} ) then set hostNm=`hostname` alias cd 'cd \!*; getTitle ; echo -n "]0;${titleString}" ; set prompt = "[7m${hostNm} >[m "' endif cd . #end csh script
TERM_PROGRAM=Apple_Terminal TERM_PROGRAM_VERSION=98 (or something else...)
The TSTerminalDOServices protocol, declared in the header
/System/Developer/Headers/Apps/TerminalDOProtocol.h, allows
applications to request that the Terminal application perform
commands on their behalf. This is useful if a program wants to open
up a shell window for the user to interact with, and it may be easier
than setting up pipes and doing a fork
/exec
of a program yourself.
Terminal cannot provide services if it is not running. It may be necessary to use the Application Kit's NSWorkspace API to launch Terminal if the connection to Terminal fails.
You may run the commands in a window, in which case an integer window handle is returned to allow a window to be reused for subsequent commands, or the commands can performed in the background. In addition, you can specify the window's title, as well as the working directory and environment to be used when executing the command.
In the case of commands performed in the background only, you can
pass in an NSData object whose data will be fed to the command's
standard input, and if you pass in a pointer to an NSData, Terminal
can hand you back the output of the command's standard output and
standard error. If you pass a pointer to get these back, the data at
the pointer should be nil
before you invoke the command.
Upon completion, the pointer points to an newly created NSData
containing the output.
For details on the specific methods in the protocol, see the header file referenced above.
By default, Terminal registers a port for the execution service with the Mach bootstrap server. This means that only processes descended from the Workspace application have access to this service. You can also have Terminal register this port with the Mach netname server, which allows access from other machines on the network. This is enabled by setting the default
/usr/bin/defaults write Terminal PublicDOServices YES
Running with this default is a security hazard, as Terminal has no way of verifying who is making the remote connection.
Any user may disable this service by executing the following command:
/usr/bin/defaults write Terminal DisableDOServices YES
The superuser can disable it for all users on a given machine by giving this command:
touch /System/Administration/Terminal.app/.DisableDOServices
The program /usr/bin/terminal, mentioned above in "A Tool for Creating New Terminal Windows," is a simple client which utilizes this protocol. The following is the source code for this program:
// // terminal.m // // Sample client for Terminal.app's Distributed Objects services. // Copyright 1994-1997, Apple Computer, Inc. All rights reserved. // // // This program opens a terminal window in the current directory. It's installed // in /usr/bin/terminal. // // Author: sam streeper // Updated by: Barry Locklear, Grant Baillie // // To compile: // // cc terminal.m -I/System/Developer/Headers -framework Foundation -o terminal // // Usage: // terminal [-shell] [-dir <dir>] [-noclose] [-env] [command] // #import <AppKit/AppKit.h>#import <Foundation/Foundation.h>#import <stdio.h>#import <mach/mach.h>#import <servers/bootstrap.h>#import <Apps/TerminalDOProtocol.h> static void usage(void) { fprintf(stderr,"terminal: open a new Terminal.app window\n\n"); fprintf(stderr,"Usage: terminal [-shell] [-dir <dir>] [-noclose] [-env] [command]\n"); fprintf(stderr," -shell - Run command from default shell\n"); fprintf(stderr," -dir - Specify working directory (default is current)\n"); fprintf(stderr," -noclose - Retain window upon exit\n"); fprintf(stderr," -env - Export current environment\n"); exit(-1); } static id<TSTerminalDOServices> lookupTerminalDOServer(void) { port_t sendMachPort; NSDistantObject *rootProxy = nil; id<TSTerminalDOServices> result; // First, try look up Terminal's DO object in the bootstrap server. // This is where the app registers it by default. if ((BOOTSTRAP_SUCCESS == bootstrap_look_up(bootstrap_port, "TerminalDO", &sendMachPort)) && (PORT_NULL != sendMachPort)) { NSConnection *conn = [NSConnection connectionWithReceivePort:[NSPort port] sendPort:[NSPort portWithMachPort:sendMachPort]]; rootProxy = [conn rootProxy]; } // If the previous call failed, the following might succeed if the user // logged in is running Terminal with the PublicDOServices user default // set. if (!rootProxy) { rootProxy = [NSConnection rootProxyForConnectionWithRegisteredName:@"TerminalDO" host:@""]; } // We could also try to launch Terminal at this point, using // the NSWorkspace protocol. if (!rootProxy) { fprintf(stderr,"Can't connect to Terminal\n"); exit(-1); } [rootProxy setProtocolForProxy:@protocol(TSTerminalDOServices)]; result = (id<TSTerminalDOServices>)rootProxy; if ([result protocolVersion] < 0x10002) { fprintf(stderr,"Incompatible terminal protocol version\n"); exit(-4); } return result; } int main(void) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; id <TSTerminalDOServices> terminal = lookupTerminalDOServer(); NSEnumerator *argsEnum = [[[NSProcessInfo processInfo] arguments] objectEnumerator]; NSString *thisArg; int returnCode; NSMutableString *command = nil; NSDictionary *environment = nil; NSString *directory = nil; TSShellType shellType = TSShellNone; TSExitAction exitAction = TSCloseUnlessError; int winHandle; NSData *inputData = nil; NSData *outputData = nil; NSData *errorData = nil; thisArg = [argsEnum nextObject]; /* Skip the program name */ if (nil == thisArg) { shellType = TSShellDefault; } // Run through the command-line arguments. We only set command to // something non-nil once we encounter an argument that isn't an // option. Once we've done this, though, we treat the rest of // the arguments as part of the command. // while(thisArg = [argsEnum nextObject]) { if (command) { [command appendFormat:@" %@", thisArg]; } else if (![thisArg hasPrefix:@"-"]) { command = [[thisArg mutableCopy] autorelease]; } else if ([@"-shell" isEqualToString:thisArg]) { shellType = TSShellDefault; } else if ([@"-dir" isEqualToString:thisArg]) { if (!(thisArg = [argsEnum nextObject])) usage(); directory = thisArg; } else if ([@"-noclose" isEqualToString:thisArg]) { exitAction = TSDontCloseOnExit; } else if ([@"-env" isEqualToString:thisArg]) { environment = [[NSProcessInfo processInfo] environment]; } else { usage(); } } if (!directory) directory = [[NSFileManager defaultManager] currentDirectoryPath]; if (!command) command = [NSMutableString stringWithCString:""]; [terminal runCommand:command inputData:inputData outputData:&outputData errorData:&errorData waitForReturn:NO windowType:TSWindowNew windowHandle:&winHandle exitAction:exitAction shellType:shellType windowTitle:command directory:directory environment:environment returnCode:&returnCode]; [pool release]; exit(returnCode); }