This is open.m in view mode; [Download] [Up]
/* -*-ObjC-*-
******************************************************************************
*
* File: open.m
* RCS: /usr/local/lib/cvs/open/open.m,v 1.14 1995/05/08 18:37:59 chris Exp
* Description: replacement for /usr/bin/open
* Author: Christian Limpach <chris@nice.ch>
* Created: Wed Mar 20 23:48:35 1994
* Modified: Mon May 8 20:28:24 1995 (Christian Limpach) chris@nice.ch
* Language: ObjC
* Package: open
* Status: Released
*
* (C) Copyright 1994, Christian Limpach, all rights reserved.
*
******************************************************************************
*/
/*
* open.m,v
* Revision 1.14 1995/05/08 18:37:59 chris
* made -as option sticky, it will now remain in effect until an
* application is explicitely selected via the -a option.
* this is version 1.3 now
*
* Revision 1.13 1995/05/08 17:50:08 chris
* made -as symlink generation reuse existing symlinks if possible
* and use the basename of the file instead of openfiletmp as the
* symlink template [suggested by Peter Langston <psl@acm.org>]
*
* Revision 1.12 1995/05/08 15:44:11 chris
* fixed double tempfile when -as and stdin
* [reported by Peter Langston <psl@acm.org>]
*
* Revision 1.11 1995/05/02 22:28:07 chris
* changed version number to 1.2
*
* Revision 1.10 1995/05/02 22:18:15 chris
* added -as option to define extensions of files without or with
* incorrect extensions [suggested by Peter Langston <psl@acm.org>]
*
* Revision 1.9 1995/04/05 01:10:22 chris
* fixed problem with uninitialized stat parameter
* [reported by Daniel G. Kluge <daniel@vis.inf.ethz.ch>]
*
* Revision 1.8 1995/03/30 17:37:02 chris
* fixed bug with openfiletmpXXXXXX.ext where NXGetTempFilename replaced
* XX.ext insted of XXXXXX. added documentation for -pause and -connectp.
* increased version number to 1.1.
*
* Revision 1.7 1994/09/01 14:58:24 chris
* added -connectp (check if we can connect to a Windowserver) and
* -pause n to make open pause n seconds before exiting
*
* Revision 1.6 1994/06/20 22:19:32 chris
* added -tmpdir option to choose directory used for temporary files
*
* Revision 1.5 1994/05/30 22:02:55 chris
* added -help and -version
*
* Revision 1.4 1994/05/26 12:47:39 chris
* added `Foo.client somefile' = `open -a Foo -wait somefile'
* [suggested by Carl Edman <cedman@princeton.edu>]
*
* Revision 1.3 1994/05/23 18:00:17 chris
* fixed bug which broke 'open -p *.txt' (only the first file was
* printed) [reported by Paul van der Zwan <paulzn@olivetti.nl>]
* fixed bug which broke -NXHost (no more Application object)
* [reported by Bill Bumgarner <bbum@friday.com>]
*
* Revision 1.2 1994/05/09 21:37:42 chris
* fixed NXHost which was broken because of [Application new]
*
* Revision 1.1 1994/05/05 22:32:05 chris
* replaces /usr/bin/open and adds some nice features
*
*/
#ifdef RCSID
static char rcsid[] = "open.m,v 1.14 1995/05/08 18:37:59 chris Exp";
#endif
#define VERSION_STRING "open v1.3\n"
#import "open.h"
@implementation AppInfo
- initFor:(const char *)openApp onHost:(const char *)hostName
{
[super init];
if((Port=NXPortFromName(openApp, hostName)) != PORT_NULL)
{
Name=str_copy(openApp);
Host=str_copy(hostName);
}
return self;
}
- (port_t)port
{
return Port;
}
- (BOOL)isEntryFor:(const char *)openApp:(const char *)hostName
{
if(!strcmp(Name, openApp) &&
(Host==hostName || (Host!=NULL && hostName!=NULL &&
!strcmp(Host, hostName))))
return YES;
else
return NO;
}
@end
@implementation AppList
- (port_t)getPortFor:(const char *)anApp onHost:(const char *)aHost
{
int index;
for(index=0; index<[self count]; index++)
if([[self objectAt:index] isEntryFor:anApp:aHost])
break;
if(index!=[self count])
return [[self objectAt:index] port];
else {
id info;
info=[[AppInfo alloc] initFor:anApp onHost:aHost];
if ([info port]!=PORT_NULL)
[self addObject:info];
return [info port];
}
}
@end
void version()
{
fprintf(stderr, VERSION_STRING);
}
int check_help(int argc, char *argv[], const char *appName, int flag)
{
if(argc>1 && !strcmp(argv[1], "-help"))
{
if(flag==HELP_UNHIDE)
fprintf(stderr, "%s [app] ", appName);
else if(flag==HELP_APPOPEN)
fprintf(stderr, "%s app ", appName);
else if(flag==HELP_OPENAS)
fprintf(stderr, "%s extension ", appName);
else
fprintf(stderr, "%s ", appName);
fprintf(stderr, "[-a app] [-o file] [-p] "
"[-NXHost hostname] [-unhide] [-nostat] [-wait] "
"[-temp] [-tmpdir directory] [-connectp] [-pause n] "
"[-as extension] [+linenum] [filename] ...\n");
return 1;
} else if(argc>1 && !strcmp(argv[1], "-version")) {
version();
return 1;
} else
return 0;
}
void main(int argc, char *argv[])
{
port_t appPort;
int ok, arg=1;
char *host=NULL;
const char *openApp=WORKSPACE, *appName, *tmpDir="/tmp", *asExt="";
id appSpeaker = [[Speaker alloc] init];
id appList = [[AppList alloc] init];
int openMode=OPEN, fileMode=DISK, openedAFile=0;
int oline=0, waitForFileChange=0, noStat=0, openAs=0;
if(appName=strrchr(argv[0], '/'))
appName++;
else
appName=argv[0];
if(strcmp(appName, "open"))
if(!strcmp(appName, "appopen") || !strcmp(appName, "run"))
{
if(check_help(argc, argv, appName, HELP_APPOPEN)) {
arg++;
openedAFile++;
} else if(argc<(arg+1)) {
printf("Usage: %s Application file...\n", appName);
exit(1);
}
openApp=argv[arg++];
} else if(!strcmp(appName, "unhide")) {
if(check_help(argc, argv, appName, HELP_UNHIDE)) {
arg++;
openedAFile++;
}
if(argc>arg)
openApp=argv[arg++];
openMode=UNHIDE;
} else if(strlen(appName)>CLIENTEXTLEN &&
!strcmp(&appName[strlen(appName)-CLIENTEXTLEN],
CLIENTEXT)) {
register char *name;
waitForFileChange++;
name=str_copy(appName);
name[strlen(name)-CLIENTEXTLEN]='\000';
openApp=name;
if(check_help(argc, argv, appName, HELP_OPEN)) {
arg++;
openedAFile++;
}
} else if(!strcmp(appName, "openAs")) {
if(check_help(argc, argv, appName, HELP_OPENAS)) {
arg++;
openedAFile++;
} else if(argc<(arg+1)) {
printf("Usage: %s extension file...\n", appName);
exit(1);
}
asExt=argv[arg++];
openAs++;
} else {
openApp=appName;
if(check_help(argc, argv, appName, HELP_OPEN)) {
arg++;
openedAFile++;
}
}
else
if(check_help(argc, argv, appName, HELP_OPEN)) {
arg++;
openedAFile++;
}
while(1)
{
int argIsFile=0;
if(arg>=argc)
/* auto detect stdin */
if(openedAFile)
break;
else {
if((openApp!=WORKSPACE && openMode==OPEN) || openMode==UNHIDE)
{
if(openMode==OPEN)
openMode=APP;
fileMode=NONE;
} else
fileMode=STDIN;
argIsFile++;
}
else if(argv[arg][0]=='-') {
if(!strcmp(&argv[arg][1], "NXHost"))
{
if(arg!=(argc-1))
host=argv[++arg];
else argIsFile++;
} else if(!strcmp(&argv[arg][1], "wait")) {
waitForFileChange++;
} else if(!strcmp(&argv[arg][1], "nostat")) {
noStat++;
} else if(!strcmp(&argv[arg][1], "unhide") ||
!strcmp(&argv[arg][1], "activate") ||
!strcmp(&argv[arg][1], "makeKey")) {
openMode=UNHIDE;
fileMode=NONE;
argIsFile++;
} else if(!strcmp(&argv[arg][1], "temp")) {
fileMode=TEMP;
} else if(!strcmp(&argv[arg][1], "version")) {
version();
} else if(!strcmp(&argv[arg][1], "tmpdir")) {
if(arg!=(argc-1))
tmpDir=argv[++arg];
else argIsFile++;
} else if(!strcmp(&argv[arg][1], "connectp")) {
if(NXPortFromName(WORKSPACE, host) != PORT_NULL)
exit(0);
else
exit(1);
} else if(!strcmp(&argv[arg][1], "pause")) {
if(arg!=(argc-1))
sleep(atoi(argv[++arg]));
else argIsFile++;
} else if(!strcmp(&argv[arg][1], "as")) {
if(arg!=(argc-1)) {
openAs++;
asExt=argv[++arg];
} else argIsFile++;
} else if(argv[arg][1]=='\000') {
if(arg==(argc-1) && !openedAFile)
fileMode=STDIN;
argIsFile++;
} else if(argv[arg][2]=='\000') {
switch(argv[arg][1]) {
case 'a': /* next arg is new application to open with */
if(arg!=(argc-1)) {
openApp=argv[++arg];
openAs=0;
} else argIsFile++;
break;
case 'o': /* open next arg without checking switches */
openMode=OPEN;
if(arg!=(argc-1))
arg++;
argIsFile++;
break;
case 'p': /* go printmode */
openMode=PRINT;
break;
default: /* not a switch -> open it */
argIsFile++;
break;
}
} else argIsFile++; /* not a longopt -> open it */
} else if(argv[arg][0]=='+') {
int i=0;
oline=0;
while(argv[arg][++i]!='\0')
if(isdigit(argv[arg][i]))
oline=10*oline+(argv[arg][i]-48);
else {
argIsFile++;
break;
}
if(!argIsFile)
{
if(arg!=(argc-1))
{
openMode=OPENLINE;
arg++;
}
argIsFile++;
}
} else argIsFile++; /* not an opt at all -> open it */
if(argIsFile)
{
char fname[MAXPATHLEN+1+(arg>=argc?0:strlen(argv[arg]))+
(openAs?strlen(asExt):0)+1];
struct stat buf;
switch(fileMode) {
case STDIN: {
char buffer[STDINBUFSIZE+1];
int len, xxpos;
FILE *file;
if((len=fread(buffer, 1, STDINBUFSIZE, stdin))>=0)
{
if(tmpDir[0]=='/')
strcpy(fname, tmpDir);
else {
getwd(fname);
strcat(fname, "/");
strcat(fname, tmpDir);
}
if(fname[strlen(fname)-1]!='/')
strcat(fname, "/");
strcat(fname, "openfiletmpXXXXXX");
xxpos=strlen(fname)-6;
buffer[len]='\0';
if (!openAs) {
if(len>=5 && !strncmp(buffer, "{\\rtf", 5))
strcat(fname, ".rtf");
else if(len>=11 && !strncmp(buffer, "%!PS-Adobe-", 11))
if(strstr(buffer, "EPSF-")<strchr(buffer, '\012'))
strcat(fname, ".eps");
else
strcat(fname, ".ps");
} else {
strcat(fname, ".");
strcat(fname, asExt);
}
NXGetTempFilename(fname, xxpos);
if(!(file=fopen(fname, "wb")))
{
printf("%s: couldn't create temp file\n", appName);
exit(1);
}
while(len==STDINBUFSIZE)
{
fwrite(buffer, STDINBUFSIZE, 1, file);
len=fread(buffer, 1, STDINBUFSIZE, stdin);
}
fwrite(buffer, 1, len, file);
fclose(file);
}
break;
}
case NONE:
break;
case DISK:
case TEMP:
default:
if(argv[arg][0]=='/')
strcpy(fname, argv[arg]);
else {
getwd(fname);
strcat(fname, "/");
strcat(fname, argv[arg]);
}
if(fname[strlen(fname)-1]=='/')
strcat(fname, ".");
break;
}
if(openAs && fileMode!=STDIN) {
char *tmp, fname2[MAXPATHLEN+1+(arg>=argc?0:strlen(argv[arg]))+
strlen(asExt)+1],
fname3[MAXPATHLEN];
int count=1, cc;
if(tmpDir[0]=='/')
strcpy(fname2, tmpDir);
else {
getwd(fname2);
strcat(fname2, "/");
strcat(fname2, tmpDir);
}
if(fname2[strlen(fname2)-1]!='/')
strcat(fname2, "/");
tmp=fname2+strlen(fname2);
if(strrchr(fname, '/')) {
strcat(fname2, strrchr(fname, '/')+1);
if(tmp=strrchr(tmp, '.'))
*tmp='\0';
} else
strcat(fname2, "openfiletmp");
tmp=fname2+strlen(fname2);
sprintf(tmp, "%06d.%s", count++, asExt);
while(!stat(fname2, &buf)) {
if(buf.st_mode & S_IFLNK) {
cc=readlink(fname2, fname3, MAXPATHLEN);
if(!strncmp(fname, fname3, cc)) {
tmp=NULL;
break;
}
}
sprintf(tmp, "%06d.%s", count++, asExt);
}
if(tmp) {
symlink(fname, fname2);
}
strcpy(fname, fname2);
}
if(!noStat && openMode!=APP && openMode!=UNHIDE && stat(fname, &buf))
printf("%s: can't stat file: %s\n", appName, fname);
else {
char *connName;
NXAtom type;
if((openMode==PRINT || openMode==OPENLINE) &&
!strcmp(openApp, WORKSPACE))
[[Application workspace] getInfoForFile:fname
application:&connName type:&type];
else
connName=str_copy(openApp);
if((appPort=[appList getPortFor:connName onHost:host]) !=
PORT_NULL)
{
[appSpeaker setSendPort:appPort];
switch(openMode) {
case UNHIDE:
[appSpeaker performRemoteMethod:"unhide"];
break;
case APP:
break;
case OPENLINE:
[appSpeaker selectorRPC:"openFile:onHost:atTrueLine:"
paramTypes:"cci", fname,
host?host:"localhost", oline];
break;
case PRINT:
if([appSpeaker msgPrint:fname ok:&ok] || !ok)
printf("%s: unable to print file: %s\n", appName, fname);
break;
case OPEN:
default:
if(fileMode==STDIN || fileMode==TEMP || openAs)
{
if([appSpeaker openTempFile:fname ok:&ok] || !ok)
printf("%s: unable to open temp file: %s\n", appName,
fname);
} else {
if([appSpeaker openFile:fname ok:&ok] || !ok)
printf("%s: unable to open file: %s\n", appName,
fname);
}
break;
}
if(!noStat && waitForFileChange)
{
time_t last=buf.st_mtime;
while(buf.st_mtime==last && !sleep(1))
stat(fname, &buf);
}
} else {
printf("%s: can't open connection to %s on %s.\n",
appName , openApp, host?host:"local host");
}
str_free(connName);
}
waitForFileChange=0;
noStat=0;
fileMode=DISK;
if(openMode!=PRINT)
openMode=OPEN;
openedAFile++;
}
arg++;
}
[appSpeaker free];
exit(0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.