[comp.sys.mac.programmer] Sublaunching in LSC

charles@tasis.utas.oz (Charles Lakos) (07/05/89)

Actually there are 2 questions:

1. Has someone used the sublaunching as described in Tech Note 126 in LSC?
   If so, how is the inline function Launchit coded, and is it necessary
   to type up the assembly code referred to in Tech Note 88 or is it 
   available elsewhere?

2. I have written a DRVR which is given a time slice periodically (by setting
   the dNeedTime flag).  At certain times it decides to perform an action.  
   My question is whether it is possible to determine the "stability of the 
   environment"?  What I mean by this might be best explained by examples.
   The DRVR presumably can sound the bell any time it gets a look in.  But
   it presumably ought to be more reticent putting up a dialog window - you
   might be in the middle of printing or other comms.  And it should be 
   even more reticent in sublaunching another application!  How do I know
   when is a good time to do these things?

Any suggestions welcome.

Charles Lakos.

ACSnet: charles@tasis.utas.oz
ARPA:   charles%tasis.utas.oz@uunet.uu.net
UUCP:   {enea,hplabs,mcvax,uunet,ukc}!munnari!tasis.utas.oz!charles
Snail:  Computer Science Dept., University of Tasmania,
	GPO Box 252C, Hobart, TAS, 7001, Australia.
Charles Lakos.

ACSnet: charles@tasis.utas.oz
ARPA:   charles%tasis.utas.oz@uunet.uu.net
UUCP:   {enea,hplabs,mcvax,uunet,ukc}!munnari!tasis.utas.oz!charles
Snail:  Computer Science Dept., University of Tasmania,
	GPO Box 252C, Hobart, TAS, 7001, Australia.

drew@lethe.UUCP (Drew Sullivan) (07/08/89)

In article <943@diemen.cc.utas.oz> charles@tasis.utas.oz (Charles Lakos) writes:
>1. Has someone used the sublaunching as described in Tech Note 126 in LSC?
>   If so, how is the inline function Launchit coded, and is it necessary
>   to type up the assembly code referred to in Tech Note 88 or is it 
>   available elsewhere?

#!/bin/sh
#  Unix funcions for the Macintosh
#  All are released for any use.
#  If you have routines, please send them to me.
#  Also if you find bugs I want to know!.
#
echo "x - access.c"
sed "s/^X//" > access.c <<'!-E-o-F'
X/*
X *	access -- macintosh access funcion
X */
X#include <sys/types.h>
X#include <string.h>
X#include <errno.h>
X
X#include "getarg.h"
X
Xextern int errno;
X
X#define NULL	0
X
Xint access(fname, mode) char *fname; int mode; {
X	CInfoPBRec	pb;
X	OSErr		rc;
X	Str255		name;
X
X	if (fname == NULL || *fname == '\0') {
X		errno = EINVAL;
X		return -1;
X	}
X	
X	/* get info the name just passed to us */
X	repmem((char *)&pb,"",1,sizeof(pb));
X	pb.dirInfo.ioDrDirID = av_curdir(fname);
X	pb.dirInfo.ioNamePtr = (StringPtr)CtoPstr(strcpy((char *)name, fname));
X
X	if (mac_err(PBGetCatInfo(&pb, FALSE), "PBGetCatInfo")) {
X		return -1;
X	}
X	/* BUG should check for real read/write, access (Type=='APPL') perms */
X	return 0;
X}
X
!-E-o-F
echo "x - chdir.c"
sed "s/^X//" > chdir.c <<'!-E-o-F'
X#include <stdio.h>
X#include <string.h>
X
X#include "getarg.h"
X
Xint chdir(name) char *name; {
X	char		work[256];
X	WDPBRec		wd;
X	ioParam		pb;
X	OSErr		rc;
X
X	repmem((char *)&wd,"",1,sizeof(wd));
X	
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X		return -1;
X	}
X
X	wd.ioCompletion = NULL;
X	wd.ioNamePtr    = (StringPtr)CtoPstr(strcpy(work, name));
X
X	if (mac_err(PBHSetVol(&wd, FALSE), "PBOpenWD")) {
X		return -1;
X	}
X#if DEBUG
X	printf("wd.ioVRefNum = %x, wd.ioWDDirID = %lx\n", wd.ioVRefNum, wd.ioWDDirID);
X#endif
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X		return -1;
X	}
X	CurDirStore = wd.ioWDDirID;
X	return 0;	
X}
!-E-o-F
echo "x - curdir.c"
sed "s/^X//" > curdir.c <<'!-E-o-F'
X#include "portlink.h"
X#include "stdlib.p"
X#include "getarg.h"
X#include <HFS.h>
X#include <errno.h>
X
X#define EOS	'\0'
X
X/*
X *	av_curdir - is used to check and map to in the current directory
X *		for relative file names;
X */
X
Xlong av_curdir(file) char *file; {
X	OSErr		rc;
X	WDPBRec		wd;
X
X	if (strchr(file, ':') == NULL || *file == ':') {
X		/* relative to the current working directory */
X		repmem((char *)&wd,"",1,sizeof(wd));
X	
X		if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X			return -1;
X		}
X		return wd.ioWDDirID;
X	}
X	/* absolue path, no current working directory */
X	return 0L;
X}
X
X#if DEBUG
X#define	maperr(n,p)	errno = n; msg = p
X#else
X#define	maperr(n,p)	errno = n
X#endif
X
Xint	_mac_error = 0;
Xchar *	_mac_errid = "";
X
Xint mac_err(rc, rn) int rc; char *rn; {
X	char	*msg;
X
X	if (rc == noErr) {
X		return 0;
X	}
X	_mac_error = rc;
X	_mac_errid = rn;
X	
X	switch (rc) {
X	case bdNamErr:	maperr(EINVAL,	"Bad file name");		break;
X	case dirNFErr:	maperr(ENOTDIR,	"Directory not found");		break;
X	case extFSErr:	maperr(EXDEV,	"External file system");	break;
X	case fnfErr:	maperr(ENOENT,	"File not found");		break;
X	case ioErr:	maperr(EIO,	"I/O Error");			break;
X	case nsvErr:	maperr(ENOENT,	"No such volume");		break;
X	case paramErr:	maperr(ENOENT,	"No default volume");		break;
X	default:	maperr(EINVAL,	"<unknown error>");		break;
X	}
X#if DEBUG
X	fprintf(stderr, "%s: %d (%s) -> %d",  rn, rc, msg, errno);
X	perror("");
X#endif
X	return rc;
X}
X
X
!-E-o-F
echo "x - filelength.c"
sed "s/^X//" > filelength.c <<'!-E-o-F'
X/*
X *	filelenth -- return size of a unix file-descriptor
X */
X#include <stdio.h>
X#include <io.h>
X
Xlong filelength(fd) int fd; {
X	long	size;
X	int	rc;
X
X	if (mac_err(GetEOF(_file[fd].refnum, &size), "GetEOF")) {
X		return -1L;
X	}
X	return size; 	/* length of the data fork */
X}
!-E-o-F
echo "x - getarg.c"
sed "s/^X//" > getarg.c <<'!-E-o-F'
X/*
X *	getarg.c -- simulate command line processing
X */
X#include "portlink.h"
X#include "stdio.p"
X#include <ctype.h>
X#include "string.p"
X#include "getarg.h"
X#include "stdlib.p"
X
X#include "stdext.h"
X
X#define	MAXARGS	100
X
Xstatic	void	reopen(char *, FILE *, char *mode);
X
X/*
X *	av_argcnt -- return the number of elements in an argv list (returns argc)
X */
Xint av_argcnt(argv) char **argv; {
X	int	argc = 0;
X	
X	while (*argv++) ++argc;
X	return argc;
X}
X
X/*
X *	av_getargs -- Maps the mac command vector to C's argv vector
X *		it does I/O redirection
X */
Xchar **av_getargs() {
X	static	char *	argbuf[MAXARGS];
X	char	**args = argbuf;
X	char	*arg, buf[BUFSIZ];
X	int	i, t;
X	struct	arg_hdr *ph;
X	AppFile	*ap;
X	
X	*args++ = strdup(strpcpy(buf, CurApName));
X	
X	ph = *(struct arg_hdr **)AppParmHandle;
X	ap = &ph->lst;
X	for (i=0; i < ph->count; ++i) {
X		arg = strpcpy(buf, (char *)ap->fName);
X
X		if ((t = ap->fName[0]+1) & 1) ++t;
X		ap = (AppFile *)(ap->fName + t);
X		
X		if (*arg == '<' ) {
X			reopen(++arg, stdin, "r");
X			continue;
X		}
X		if (*arg == '>') {
X			if (*++arg == '>') {
X				reopen(++arg, stdout, "a");
X				continue;
X			}
X			if (*arg == '?') {
X				reopen(++arg, stderr, "w");
X				continue;
X			}
X			reopen(arg, stdout, "w");
X			continue;
X		}
X		*args++ = strdup(arg);			/* simple arg */
X	}
X	*args = NULL;
X	return argbuf;
X}
X
X
X/*
X *	strpcpy -- copy a pascal string to a c string.
X */
Xchar *strpcpy(s, p) char *s, *p; {
X	strncpy(s, p+1, *p);
X	s[*p] = EOS;
X	return s;
X}
X
X/*
X *	reopen -- re-open stdin/out/err
X *		(bug -- silently terminate program on failure
X */
Xstatic void reopen( file, fp, mode ) char *file; FILE *fp; char *mode; {
X	if ((fp = freopen(file, mode, fp)) == NULL) {
X		exit(1);
X	}
X}
X
!-E-o-F
echo "x - getopt.c"
sed "s/^X//" > getopt.c <<'!-E-o-F'
X#ifndef lint
Xstatic char sccsid[] = "@(#)getopt.c	5.1 (Berkeley) 7/2/83";
X#endif
X
X#include <stdio.h>
X#include <string.h>
X
X#define ERR(s, c)	if(opterr){\
X	fputs(argv[0], stderr);\
X	fputs(s, stderr);\
X	fputc(c, stderr);\
X	fputc('\n', stderr);} else
X
Xint	opterr = 1;
Xint	optind = 1;
Xint	optopt;
Xchar	*optarg;
X
Xint getopt (argc, argv, opts)
Xint argc;
Xchar **argv, *opts;
X{
X	static int sp = 1;
X	register int c;
X	register char *cp;
X
X	if (sp == 1)
X		if (optind >= argc ||
X		   argv[optind][0] != '-' || argv[optind][1] == '\0')
X			return EOF;
X		else if (strcmp(argv[optind], "--") == 0) {
X			optind++;
X			return EOF;
X		}
X	optopt = c = argv[optind][sp];
X	if (c == ':' || (cp=strchr(opts, c)) == NULL) {
X		ERR (": illegal option -- ", c);
X		if (argv[optind][++sp] == '\0') {
X			optind++;
X			sp = 1;
X		}
X		return '?';
X	}
X	if (*++cp == ':') {
X		if (argv[optind][sp+1] != '\0')
X			optarg = &argv[optind++][sp+1];
X		else if (++optind >= argc) {
X			ERR (": option requires an argument -- ", c);
X			sp = 1;
X			return '?';
X		} else
X			optarg = argv[optind++];
X		sp = 1;
X	}
X	else {
X		if (argv[optind][++sp] == '\0') {
X			sp = 1;
X			optind++;
X		}
X		optarg = NULL;
X	}
X	return c;
X}
!-E-o-F
echo "x - getwd.c"
sed "s/^X//" > getwd.c <<'!-E-o-F'
X#include <stdio.h>
X#include <string.h>
X
X#include "getarg.h"
X
Xchar *getwd(name) char *name; {
X	OSErr		rc;
X	WDPBRec		wd;
X
X	repmem((char *)&wd,"",1,sizeof(wd));
X	
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X		return NULL;
X	}
X
X	if (av_getname(name, wd.ioWDDirID)) {
X		return NULL;
X	}
X	if (strchr(name, ':') == NULL) strcat(name, ":");
X	return name;	
X}
X
Xint av_getname(name, n) char *name; long n; {
X	CInfoPBRec	pb;
X	OSErr		rc;
X	char		space[32];
X
X	repmem((char *)&pb,"",1,sizeof(pb));
X	
X	pb.dirInfo.ioNamePtr    = (StringPtr)space;
X	pb.dirInfo.ioFDirIndex  = -1;
X	pb.dirInfo.ioDrDirID    = n;
X		
X	if (mac_err(PBGetCatInfo(&pb, FALSE), "PBGetCatInfo")) {
X		return -1;
X	}
X	PtoCstr(space);
X	if (n <= 2) {
X		strcpy(name, space);
X	} else {
X		av_getname(name, pb.dirInfo.ioDrParID);
X		strcat(name, ":");
X		strcat(name, space);
X	}
X	return 0;
!-E-o-F
echo "x - mount.h"
sed "s/^X//" > mount.h <<'!-E-o-F'
X/*
X *	mount.h
X */
X
Xextern	char *	vol_getlabel(int);		/* get volume name */
X
!-E-o-F
echo "x - putarg.c"
sed "s/^X//" > putarg.c <<'!-E-o-F'
X/*
X *	putarg.c -- simulate command line processing
X */
X#include "portlink.h"
X#include "stdio.p"
X#include <ctype.h>
X#include "string.p"
X#include "getarg.h"
X#include "stdlib.p"
X
X#include "stdext.h"
X
X#define	MAXARGS	100
X
Xstatic	Handle	myAppHandle;
X
Xchar ** av_hackargs(p) char *p; {
X	static	char *argbuf[MAXARGS];
X	char	**av;
X
X	for (av=argbuf; *p; ) {
X		*av++ = p;
X		if ((p=strchr(p, ' ')) == NULL) break;
X		*p++ = '\0';
X		while (*p && isspace(*p)) ++p;
X	}
X	*av = NULL;
X	
X	return argbuf;
X}
X
X/*
X *	av_putargs -- build a low memory version of the arglist.
X */
Xvoid av_putargs(av) char **av; {
X	THz		curzone, syszone;
X	Size		avsize;
X	int		i, t, argc;
X	char		**p;
X	struct		arg_hdr *ph;
X	AppFile		*ap;
X	CInfoPBRec	pb;
X	
X	argc = 0;
X	avsize = sizeof(struct arg_hdr) - sizeof(AppFile);
X	for (p=av; *p; ++p) {
X		++argc;
X		t = strlen(*p)+1;
X		if (t & 1) ++t;
X		avsize += sizeof(AppFile) - sizeof(Str255) + t;
X	}
X	myAppHandle = AppParmHandle;
X	curzone = GetZone();
X	syszone = SystemZone();
X	
X	SetZone(syszone);
X	AppParmHandle = NewHandle(avsize);
X	HLock(AppParmHandle);
X
X	ph = *(struct arg_hdr **)AppParmHandle;
X	ph->message = 0;		/* open file */
X	ph->count = argc;		/* number of args to pass */
X	ap = &ph->lst;
X
X	for (i=0; i < argc; ++i) {
X		strcpy((char *)ap->fName, av[i]);
X		CtoPstr((char *)ap->fName);
X	
X		/* get info the name */
X		repmem((char *)&pb,"",1,sizeof(pb));
X		pb.dirInfo.ioDrDirID = av_curdir(av[i]);
X		pb.dirInfo.ioNamePtr = (StringPtr)ap->fName;
X		if (PBGetCatInfo(&pb, FALSE) == noErr) {
X			ap->vRefNum = pb.hFileInfo.ioVRefNum;
X			ap->fType   = pb.hFileInfo.ioFlFndrInfo.fdType;
X			ap->versNum = 0;
X		} else {
X			ap->vRefNum = 0;
X			ap->fType   = 0;
X			ap->versNum = 0;
X		}
X
X		if ((t = ap->fName[0]+1) & 1) ++t;
X		ap = (AppFile *)(ap->fName + t);
X	}
X#if DEBUG
X	av_dispargs();
X#endif
X	HUnlock(AppParmHandle);	
X	SetZone(curzone);
X}
X
Xvoid av_unputargs() {
X	DisposHandle(AppParmHandle);
X	AppParmHandle = myAppHandle;
X}
X
Xvoid av_dispargs() {
X	char	*arg, buf[BUFSIZ];
X	int	i, t;
X	struct	arg_hdr *ph;
X	AppFile	*ap;
X	
X	printf("av[0]: '%s'\n", strpcpy(buf, CurApName));
X	
X	ph = *(struct arg_hdr **)AppParmHandle;
X	ap = &ph->lst;
X	for (i=0; i < ph->count; ++i) {
X		strpcpy(buf, (char *)ap->fName);
X		printf("av[%d]: %4.4s '%s'\n", i+1, &ap->fType, buf);
X
X		if ((t = ap->fName[0]+1) & 1) ++t;
X		ap = (AppFile *)(ap->fName + t);
X	}
!-E-o-F
echo "x - stat.c"
sed "s/^X//" > stat.c <<'!-E-o-F'
X/*
X *	stat -- return unix stat information.
X */
X#include "portlink.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "string.p"
X#include "stdlib.p"
X#include "getarg.h"
X#include <errno.h>
X
X#define	isadir(pb)	(pb.hFileInfo.ioFlAttrib & 0x0010)	/* bit 4 in ....4 3210 */
X
X#define	EPOC	0	/* map from Jan 1,1904 to ctime's idea of the EPOC */ 
X			/* normally Jan 1,1970, but Lightspeed-C uses the mac's EPOC */
X			
Xint stat(fname, sb) char *fname; struct stat *sb; {
X	CInfoPBRec	pb;
X	OSErr		rc;
X	Str255		name;
X
X	if (fname == NULL || *fname == '\0') {
X		errno = EINVAL;
X		return NULL;
X	}
X	/* get info the name just passed to us */
X	repmem((char *)&pb,"",1,sizeof(pb));
X	pb.dirInfo.ioDrDirID = av_curdir(fname);
X	pb.dirInfo.ioNamePtr = (StringPtr)CtoPstr(strcpy((char *)name, fname));
X
X	if (mac_err(PBGetCatInfo(&pb, FALSE), "PBGetCatInfo")) {
X		return -1;
X	}
X	sb->st_dev   = pb.hFileInfo.ioDirID;
X	sb->st_ino   = pb.hFileInfo.ioFDirIndex;
X	if (isadir(pb)) {
X		sb->st_mode  = S_IFDIR;
X		sb->st_nlink = 2;
X		sb->st_size  = pb.dirInfo.ioDrNmFls;	/* length of the data fork */
X	} else {
X		sb->st_mode  = S_IFREG;
X		sb->st_nlink = 1;
X		sb->st_size  = pb.hFileInfo.ioFlLgLen;	/* length of the data fork */
X#if RESOURCE
X		sb->st_rsize = pb.hFileInfo.ioFlRLgLen;	/* length of the data fork */
X#endif
X	}
X	sb->st_uid   = 0;
X	sb->st_gid   = 0;
X	sb->st_rdev  = sb->st_dev;
X	sb->st_atime = pb.hFileInfo.ioFlBkDat - EPOC;	/* access time is the backup date */
X	sb->st_mtime = pb.hFileInfo.ioFlMdDat - EPOC;	/* modified date */
X	sb->st_ctime = pb.hFileInfo.ioFlCrDat - EPOC;	/* created date */
X	return 0;
X}
X
!-E-o-F
echo "x - stdext.h"
sed "s/^X//" > stdext.h <<'!-E-o-F'
X/*
X *	stdext.h -- standard extensions
X */
X#ifndef _STDEXT_H_DEFINED_
X#define _STDEXT_H_DEFINED_
X
X#define ABORT	(-1)	/* status returns */
X#define ERR	(-1)
X#define OK	0
X
X#define NO	0	/* bool returns */
X#define	YES	1
X
X#define EOS	'\0'
X
X#ifndef NULL
X#define NULL	0
X#endif
X
X#define MAXFNAME 15	/* maximum file name */
X#define MAXPNAME 128	/* maximum path name */
X#define MAXLINE	160	/* maximum line size */
X
Xtypedef unsigned	bool;	/* boolean type */
Xtypedef unsigned char	uchar;	/* unsigned types */
Xtypedef unsigned int	uint;
Xtypedef unsigned long	ulong;
X
Xtypedef struct TABLE	TABLE;	/* table type */
Xtypedef int		STATUS;	/* status type */
Xtypedef unsigned	KEY;
Xtypedef unsigned	RAWKEY;
Xtypedef long 		FPOS;	/* file position */
X
Xextern	char *	memdup(char *, int);		/* malloc a new copy of the memory */
X
Xextern	char *	nextb(char *s);
Xextern	char *	skipb(char *s);
Xextern	char *	skipfld(char *s, int flds);
X
Xextern	char *	strbase(char *s, char sep);	/* point to after sep or s */
Xextern	char *	strrbase(char *s, char sep);	/* point to sep char or end */
Xextern	char *	basename(char *path);		/* point to last part of path */
Xextern	char *	programname(char *pathname, char *misname);	/* dos fixup */
Xextern	char *	tackname(char *path, char *name);
Xextern	int	pathdirlength(char *path);	/* length of the dir part */
Xextern	void	syspath(char *from, char *to);	/* normalize path */
X
Xextern	void	strsetswitch(void);		/* setup the dos switchar */
Xextern	char *	strdelete(char *s, int n);	/* delete n chars from str */
Xextern	char *	strinsert(char *s1, char *s2);	/* s2 inserted into s1 */
Xextern	char *	strtrim(char *s);		/* the string blank trimmed */
Xextern	char *	strnnull(char *s);	/* return a non-null s */
Xextern	char *	strfield(char *p, int n);	/* return ptr to fld n */
Xextern	char *	strflags(uint flag, char *dp);	/* return flags as str */
Xextern	int	strsplit(char **vector, char *str); /* return # of flds */
X
Xextern	char	dos_switchar(char mode);	/* return option char */
Xextern	void	fsync(FILE *);			/* sync a file descriptor */
X
Xextern	char Path_Sep_Str[2];
X#define	PATH_SEP	(Path_Sep_Str[0])
X#define	PATH_SEP_STR	(Path_Sep_Str)
X
X#define bit_flip(f,b)	( f = (f&(~b)) | ((~f)&b) )	/* flip bit b in f */
X
X
X#endif /* _STDEXT_H_DEFINED_ */
!-E-o-F
echo "x - strdup.c"
sed "s/^X//" > strdup.c <<'!-E-o-F'
X/*
X *	strdup -- malloc a copy of string p
X */
X#include <stdlib.h>
X
Xchar *strdup(p) char *p; {
X	char	*s;
X	
X	s = malloc(strlen(p)+1);
X	if (s) strcpy(s, p);
X	return s;
X}
X
!-E-o-F
echo "x - system.c"
sed "s/^X//" > system.c <<'!-E-o-F'
X/*
X *	system -- run a sub-command
X */
X#include <stdio.h>
X#include <string.h>
X#include <HFS.h>
X#include "getarg.h"
X
X#define nil	(void *)0
X
Xtypedef struct LaunchStruct {
X	StringPtr	pfName; 	/* pointer to the name of launchee */
X	long int	param;
X	long int	extBlockLen;	/*number of bytes in extension == 6*/
X	short int	fFlags; 	/*Finder file info flags (see below)*/
X	long int	launchFlags;	/*bit 31,30==1 for sublaunch, others reserved*/
X} *pLaunchStruct;
X
Xstatic	OSErr	sublaunch(char *, char **);
Xstatic	void	subwait(void);
X
Xint system(cmd) char *cmd; {
X	OSErr	rc;
X	char	*p, **av;
X	
X#if DEBUG
X	printf("Run: %s\n", cmd);
X#endif	
X	if ((p = strchr(cmd, ' ')) == NULL) {
X		av_hackargs("");
X	} else {
X		*p++ = '\0';
X		av = av_hackargs(p);
X	}
X
X	rc = sublaunch(cmd, av);
X	return rc < 0 ? -1 : 0;
X}
X
Xstatic OSErr sublaunch(cmd, av) char *cmd, **av; {
X	struct LaunchStruct	myLaunch;
X	Point		where;		/*where to display dialog*/
X	SFTypeList	myFileTypes;	/* we only want APPLs */
X	short int	numFileTypes=1;
X	CInfoPBRec	pb;
X	WDPBRec		wd;
X	StringPtr	dirNameStr;
X	OSErr		rc;
X	char		CmdName[255];
X	
X	/*Get the Finder flags*/
X	repmem((char *)&pb,"",1,sizeof(pb));
X	pb.dirInfo.ioDrDirID = av_curdir(cmd);
X	pb.dirInfo.ioNamePtr = (StringPtr)CtoPstr(strcpy((char *)CmdName, cmd));
X	
X	if (mac_err(PBGetCatInfo(&pb, false), "PBGetCatInfo")) {
X		return -1;
X	}
X	
X	repmem((char *)&wd,"",1,sizeof(wd));
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVOL")) {
X		return -1;
X	}
X	wd.ioWDProcID = 'ERIC';
X	if (mac_err(PBOpenWD(&wd, false), "PBOpenWD")) {
X		return -1;
X	}
X	/*Set the current volume to where the target application is*/
X	if (mac_err(SetVol(nil, wd.ioVRefNum), "SetVol")) {
X		return -1;
X	}
X
X	av_putargs(av);
X	
X	/*Set up the launch parameters*/
X	myLaunch.pfName = (StringPtr)CmdName;	/*pointer to our fileName*/
X	myLaunch.param = 'LC';	/* No alternate screen or sound buffers set up.
X				   'LC' tells Launch that there is non-junk next */
X	myLaunch.extBlockLen = 6;	/* length of param. block past this long word*/
X	
X	/* from _GetCatInfo copy flags; set bit 6 of low byte to 1 for RO access:*/
X	myLaunch.fFlags = pb.hFileInfo.ioFlFndrInfo.fdFlags;
X
X	/* set BOTH hi bits for a sublaunch */
X	myLaunch.launchFlags = 0xC0000000;
X
X	if ((rc=LaunchIt(&myLaunch)) < 0) {
X		mac_err(rc, "Launch");
X		av_unputargs();
X		return -1;
X	}
X	subwait();
X	av_unputargs();
X	return noErr;
X}
X
XOSErr LaunchIt(pLnch) pLaunchStruct pLnch; {	/* < 0 means error */ 
X	register int rc;
X	
X	/* INLINE $205F, $A9F2, $3E80
X	 * pops pointer into A0 and calls Launch,
X	 * pops D0 error code into result:
X	 */
X	asm {  
X		MOVE.L  pLnch,A0
X        	_Launch
X        	MOVE.W  d0,rc
X	}
X#if DEBUG
X	printf("launch rc=%d\n", rc);
X#endif
X        return rc;
X
X}
X
Xstatic void subwait() {
X	int	i;
X	
X	unsigned short mask;
X	EventRecord event;
X	unsigned long sleep;
X	RgnHandle mouseRgn;
X	
X	mask = ~0;
X	sleep = 10;
X	
X	for (i=0; i++ < 50;) {
X		WaitNextEvent(mask, &event, sleep, nil);
X		switch(event.what) {
X		case 0xf:
X			if ((event.message & 0xf) == 1) {
X#if DEBUG
X				printf("Activated.\n");
X#endif
X				return; 
X			}
X			if ((event.message & 0xf) == 2) {
X#if DEBUG
X				printf("Suspened.\n");
X#endif
X				continue;
X			}
X		case updateEvt:
X		case nullEvent:
X			continue;
X		}
X#if DEBUG
X		printf("what=%4x, msgs=%16lx\n", event.what, event.message);
X#endif
X		if (((event.message >> 24L) & 0xFF) == 0xFD) {
X#if DEBUG
X			printf("Process: %d exited\n", event.where);
X#endif
X			return;
X		}
X	}
X}
X
XOSErr do_launch() {
X	struct LaunchStruct	myLaunch;
X	Point			where;		/*where to display dialog*/
X	SFReply			reply;   	/*reply record*/
X	SFTypeList		myFileTypes;	/* we only want APPLs */
X	short int		numFileTypes=1;
X	HFileInfo		myPB;
X	StringPtr	   	dirNameStr;
X	OSErr			rc;
X	
X#if DEBUG
X#define p(M)	((char *)&myLaunch.M - (char *)&myLaunch)
X	printf("pfName=%lx, param=%lx, extBL=%lx, fFlags=%lx, lFlags=%lx\n",
X		
X	p(pfName), 		/* pointer to the name of launchee */
X	p(param),
X	p(extBlockLen),		/*number of bytes in extension == 6*/
X	p(fFlags), 		/*Finder file info flags (see below)*/
X	p(launchFlags));	/*bit 31,30==1 for sublaunch, others reserved */
X#undef p
X#endif
X
X	where.h = 80;
X	where.v = 90;
X	myFileTypes[0] = 'APPL';		/* we only want APPLs */ 
X	/*Let the user choose the file to Launch*/
X	SFGetFile(where, "", nil, numFileTypes, myFileTypes, nil, &reply);
X	if (!reply.good) {
X		return -1;
X	}
X	dirNameStr = (StringPtr)&reply.fName;	/*initialize to file selected*/
X
X	/*Get the Finder flags*/
X	myPB.ioNamePtr= dirNameStr;
X	myPB.ioFDirIndex= 0;
X	myPB.ioDirID = 0;
X	myPB.ioVRefNum = reply.vRefNum;
X	rc = PBGetCatInfo((CInfoPBPtr) &myPB,false);
X	if (rc != noErr)
X		return rc;
X
X	/*Set the current volume to where the target application is*/
X	rc = SetVol(nil, reply.vRefNum);
X	if (rc != noErr)
X		return rc;
X
X	/*Set up the launch parameters*/
X	myLaunch.pfName = (StringPtr)&reply.fName;	/*pointer to our fileName*/
X	myLaunch.param = 'LC';		/*we don't want alternate screen
X							  or sound buffers*/
X	/*set up LC so as to tell Launch that there is non-junk next*/
X	myLaunch.extBlockLen = 6;		/*length of param. block past
X							  this long word*/
X	/*copy flags; set bit 6 of low byte to 1 for RO access:*/
X	myLaunch.fFlags = myPB.ioFlFndrInfo.fdFlags;	/*from _GetCatInfo*/
X
X	/* Test subLaunch and set launchFlags accordingly	*/
X	myLaunch.launchFlags = 0xC0000000;	/*set BOTH hi bits for a sublaunch	*/
X
X	if ((rc = LaunchIt(&myLaunch)) < 0) {		/* call _Launch			*/
X		/* the launch failed, so put up an alert to inform the user */
X#if DEBUG
X		printf("Launch Failed");
X#endif
X		return rc;
X	} else {
X		return noErr;
X	} /*if reply.good*/
X	subwait();
X}
!-E-o-F
echo "x - vol_getlabel.c"
sed "s/^X//" > vol_getlabel.c <<'!-E-o-F'
X
Xchar *vol_getlabel(drive) char drive; {
X	static Str255	name;
X	int	rnum = 0;
X	OSErr	rc;
X	
X	if ((rc = GetVol(name, &rnum)) != 0) {
X		mac_err("vol_getlabel", rc);
X		return (char *)0;
X	}
X#if DEBUG
X	printf("GetVol: %d -> %s, result: %x\n", rc, name, rnum);
X#endif
X	return PtoCstr((char *)name);
X}
!-E-o-F
-- 
  -- Drew Sullivan, <drew@lethe.uucp>
Newsgroups: aus.mac,comp.sys.mac.programmer
Subject: Re: Sublaunching in LSC
Summary: 
Expires: 
References: <943@diemen.cc.utas.oz>
Sender: 
Reply-To: drew@lethe.UUCP (Drew Sullivan)
Followup-To: 
Distribution: 
Organization: Systems Software
Keywords: 

In article <943@diemen.cc.utas.oz> charles@tasis.utas.oz (Charles Lakos) writes:
>1. Has someone used the sublaunching as described in Tech Note 126 in LSC?
>   If so, how is the inline function Launchit coded, and is it necessary
>   to type up the assembly code referred to in Tech Note 88 or is it 
>   available elsewhere?

#!/bin/sh
#  Unix funcions for the Macintosh
#  All are released for any use.
#  If you have routines, please send them to me.
#  Also if you find bugs I want to know!.
#
echo "x - access.c"
sed "s/^X//" > access.c <<'!-E-o-F'
X/*
X *	access -- macintosh access funcion
X */
X#include <sys/types.h>
X#include <string.h>
X#include <errno.h>
X
X#include "getarg.h"
X
Xextern int errno;
X
X#define NULL	0
X
Xint access(fname, mode) char *fname; int mode; {
X	CInfoPBRec	pb;
X	OSErr		rc;
X	Str255		name;
X
X	if (fname == NULL || *fname == '\0') {
X		errno = EINVAL;
X		return -1;
X	}
X	
X	/* get info the name just passed to us */
X	repmem((char *)&pb,"",1,sizeof(pb));
X	pb.dirInfo.ioDrDirID = av_curdir(fname);
X	pb.dirInfo.ioNamePtr = (StringPtr)CtoPstr(strcpy((char *)name, fname));
X
X	if (mac_err(PBGetCatInfo(&pb, FALSE), "PBGetCatInfo")) {
X		return -1;
X	}
X	/* BUG should check for real read/write, access (Type=='APPL') perms */
X	return 0;
X}
X
!-E-o-F
echo "x - chdir.c"
sed "s/^X//" > chdir.c <<'!-E-o-F'
X#include <stdio.h>
X#include <string.h>
X
X#include "getarg.h"
X
Xint chdir(name) char *name; {
X	char		work[256];
X	WDPBRec		wd;
X	ioParam		pb;
X	OSErr		rc;
X
X	repmem((char *)&wd,"",1,sizeof(wd));
X	
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X		return -1;
X	}
X
X	wd.ioCompletion = NULL;
X	wd.ioNamePtr    = (StringPtr)CtoPstr(strcpy(work, name));
X
X	if (mac_err(PBHSetVol(&wd, FALSE), "PBOpenWD")) {
X		return -1;
X	}
X#if DEBUG
X	printf("wd.ioVRefNum = %x, wd.ioWDDirID = %lx\n", wd.ioVRefNum, wd.ioWDDirID);
X#endif
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X		return -1;
X	}
X	CurDirStore = wd.ioWDDirID;
X	return 0;	
X}
!-E-o-F
echo "x - curdir.c"
sed "s/^X//" > curdir.c <<'!-E-o-F'
X#include "portlink.h"
X#include "stdlib.p"
X#include "getarg.h"
X#include <HFS.h>
X#include <errno.h>
X
X#define EOS	'\0'
X
X/*
X *	av_curdir - is used to check and map to in the current directory
X *		for relative file names;
X */
X
Xlong av_curdir(file) char *file; {
X	OSErr		rc;
X	WDPBRec		wd;
X
X	if (strchr(file, ':') == NULL || *file == ':') {
X		/* relative to the current working directory */
X		repmem((char *)&wd,"",1,sizeof(wd));
X	
X		if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X			return -1;
X		}
X		return wd.ioWDDirID;
X	}
X	/* absolue path, no current working directory */
X	return 0L;
X}
X
X#if DEBUG
X#define	maperr(n,p)	errno = n; msg = p
X#else
X#define	maperr(n,p)	errno = n
X#endif
X
Xint	_mac_error = 0;
Xchar *	_mac_errid = "";
X
Xint mac_err(rc, rn) int rc; char *rn; {
X	char	*msg;
X
X	if (rc == noErr) {
X		return 0;
X	}
X	_mac_error = rc;
X	_mac_errid = rn;
X	
X	switch (rc) {
X	case bdNamErr:	maperr(EINVAL,	"Bad file name");		break;
X	case dirNFErr:	maperr(ENOTDIR,	"Directory not found");		break;
X	case extFSErr:	maperr(EXDEV,	"External file system");	break;
X	case fnfErr:	maperr(ENOENT,	"File not found");		break;
X	case ioErr:	maperr(EIO,	"I/O Error");			break;
X	case nsvErr:	maperr(ENOENT,	"No such volume");		break;
X	case paramErr:	maperr(ENOENT,	"No default volume");		break;
X	default:	maperr(EINVAL,	"<unknown error>");		break;
X	}
X#if DEBUG
X	fprintf(stderr, "%s: %d (%s) -> %d",  rn, rc, msg, errno);
X	perror("");
X#endif
X	return rc;
X}
X
X
!-E-o-F
echo "x - filelength.c"
sed "s/^X//" > filelength.c <<'!-E-o-F'
X/*
X *	filelenth -- return size of a unix file-descriptor
X */
X#include <stdio.h>
X#include <io.h>
X
Xlong filelength(fd) int fd; {
X	long	size;
X	int	rc;
X
X	if (mac_err(GetEOF(_file[fd].refnum, &size), "GetEOF")) {
X		return -1L;
X	}
X	return size; 	/* length of the data fork */
X}
!-E-o-F
echo "x - getarg.c"
sed "s/^X//" > getarg.c <<'!-E-o-F'
X/*
X *	getarg.c -- simulate command line processing
X */
X#include "portlink.h"
X#include "stdio.p"
X#include <ctype.h>
X#include "string.p"
X#include "getarg.h"
X#include "stdlib.p"
X
X#include "stdext.h"
X
X#define	MAXARGS	100
X
Xstatic	void	reopen(char *, FILE *, char *mode);
X
X/*
X *	av_argcnt -- return the number of elements in an argv list (returns argc)
X */
Xint av_argcnt(argv) char **argv; {
X	int	argc = 0;
X	
X	while (*argv++) ++argc;
X	return argc;
X}
X
X/*
X *	av_getargs -- Maps the mac command vector to C's argv vector
X *		it does I/O redirection
X */
Xchar **av_getargs() {
X	static	char *	argbuf[MAXARGS];
X	char	**args = argbuf;
X	char	*arg, buf[BUFSIZ];
X	int	i, t;
X	struct	arg_hdr *ph;
X	AppFile	*ap;
X	
X	*args++ = strdup(strpcpy(buf, CurApName));
X	
X	ph = *(struct arg_hdr **)AppParmHandle;
X	ap = &ph->lst;
X	for (i=0; i < ph->count; ++i) {
X		arg = strpcpy(buf, (char *)ap->fName);
X
X		if ((t = ap->fName[0]+1) & 1) ++t;
X		ap = (AppFile *)(ap->fName + t);
X		
X		if (*arg == '<' ) {
X			reopen(++arg, stdin, "r");
X			continue;
X		}
X		if (*arg == '>') {
X			if (*++arg == '>') {
X				reopen(++arg, stdout, "a");
X				continue;
X			}
X			if (*arg == '?') {
X				reopen(++arg, stderr, "w");
X				continue;
X			}
X			reopen(arg, stdout, "w");
X			continue;
X		}
X		*args++ = strdup(arg);			/* simple arg */
X	}
X	*args = NULL;
X	return argbuf;
X}
X
X
X/*
X *	strpcpy -- copy a pascal string to a c string.
X */
Xchar *strpcpy(s, p) char *s, *p; {
X	strncpy(s, p+1, *p);
X	s[*p] = EOS;
X	return s;
X}
X
X/*
X *	reopen -- re-open stdin/out/err
X *		(bug -- silently terminate program on failure
X */
Xstatic void reopen( file, fp, mode ) char *file; FILE *fp; char *mode; {
X	if ((fp = freopen(file, mode, fp)) == NULL) {
X		exit(1);
X	}
X}
X
!-E-o-F
echo "x - getopt.c"
sed "s/^X//" > getopt.c <<'!-E-o-F'
X#ifndef lint
Xstatic char sccsid[] = "@(#)getopt.c	5.1 (Berkeley) 7/2/83";
X#endif
X
X#include <stdio.h>
X#include <string.h>
X
X#define ERR(s, c)	if(opterr){\
X	fputs(argv[0], stderr);\
X	fputs(s, stderr);\
X	fputc(c, stderr);\
X	fputc('\n', stderr);} else
X
Xint	opterr = 1;
Xint	optind = 1;
Xint	optopt;
Xchar	*optarg;
X
Xint getopt (argc, argv, opts)
Xint argc;
Xchar **argv, *opts;
X{
X	static int sp = 1;
X	register int c;
X	register char *cp;
X
X	if (sp == 1)
X		if (optind >= argc ||
X		   argv[optind][0] != '-' || argv[optind][1] == '\0')
X			return EOF;
X		else if (strcmp(argv[optind], "--") == 0) {
X			optind++;
X			return EOF;
X		}
X	optopt = c = argv[optind][sp];
X	if (c == ':' || (cp=strchr(opts, c)) == NULL) {
X		ERR (": illegal option -- ", c);
X		if (argv[optind][++sp] == '\0') {
X			optind++;
X			sp = 1;
X		}
X		return '?';
X	}
X	if (*++cp == ':') {
X		if (argv[optind][sp+1] != '\0')
X			optarg = &argv[optind++][sp+1];
X		else if (++optind >= argc) {
X			ERR (": option requires an argument -- ", c);
X			sp = 1;
X			return '?';
X		} else
X			optarg = argv[optind++];
X		sp = 1;
X	}
X	else {
X		if (argv[optind][++sp] == '\0') {
X			sp = 1;
X			optind++;
X		}
X		optarg = NULL;
X	}
X	return c;
X}
!-E-o-F
echo "x - getwd.c"
sed "s/^X//" > getwd.c <<'!-E-o-F'
X#include <stdio.h>
X#include <string.h>
X
X#include "getarg.h"
X
Xchar *getwd(name) char *name; {
X	OSErr		rc;
X	WDPBRec		wd;
X
X	repmem((char *)&wd,"",1,sizeof(wd));
X	
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVol")) {
X		return NULL;
X	}
X
X	if (av_getname(name, wd.ioWDDirID)) {
X		return NULL;
X	}
X	if (strchr(name, ':') == NULL) strcat(name, ":");
X	return name;	
X}
X
Xint av_getname(name, n) char *name; long n; {
X	CInfoPBRec	pb;
X	OSErr		rc;
X	char		space[32];
X
X	repmem((char *)&pb,"",1,sizeof(pb));
X	
X	pb.dirInfo.ioNamePtr    = (StringPtr)space;
X	pb.dirInfo.ioFDirIndex  = -1;
X	pb.dirInfo.ioDrDirID    = n;
X		
X	if (mac_err(PBGetCatInfo(&pb, FALSE), "PBGetCatInfo")) {
X		return -1;
X	}
X	PtoCstr(space);
X	if (n <= 2) {
X		strcpy(name, space);
X	} else {
X		av_getname(name, pb.dirInfo.ioDrParID);
X		strcat(name, ":");
X		strcat(name, space);
X	}
X	return 0;
!-E-o-F
echo "x - mount.h"
sed "s/^X//" > mount.h <<'!-E-o-F'
X/*
X *	mount.h
X */
X
Xextern	char *	vol_getlabel(int);		/* get volume name */
X
!-E-o-F
echo "x - putarg.c"
sed "s/^X//" > putarg.c <<'!-E-o-F'
X/*
X *	putarg.c -- simulate command line processing
X */
X#include "portlink.h"
X#include "stdio.p"
X#include <ctype.h>
X#include "string.p"
X#include "getarg.h"
X#include "stdlib.p"
X
X#include "stdext.h"
X
X#define	MAXARGS	100
X
Xstatic	Handle	myAppHandle;
X
Xchar ** av_hackargs(p) char *p; {
X	static	char *argbuf[MAXARGS];
X	char	**av;
X
X	for (av=argbuf; *p; ) {
X		*av++ = p;
X		if ((p=strchr(p, ' ')) == NULL) break;
X		*p++ = '\0';
X		while (*p && isspace(*p)) ++p;
X	}
X	*av = NULL;
X	
X	return argbuf;
X}
X
X/*
X *	av_putargs -- build a low memory version of the arglist.
X */
Xvoid av_putargs(av) char **av; {
X	THz		curzone, syszone;
X	Size		avsize;
X	int		i, t, argc;
X	char		**p;
X	struct		arg_hdr *ph;
X	AppFile		*ap;
X	CInfoPBRec	pb;
X	
X	argc = 0;
X	avsize = sizeof(struct arg_hdr) - sizeof(AppFile);
X	for (p=av; *p; ++p) {
X		++argc;
X		t = strlen(*p)+1;
X		if (t & 1) ++t;
X		avsize += sizeof(AppFile) - sizeof(Str255) + t;
X	}
X	myAppHandle = AppParmHandle;
X	curzone = GetZone();
X	syszone = SystemZone();
X	
X	SetZone(syszone);
X	AppParmHandle = NewHandle(avsize);
X	HLock(AppParmHandle);
X
X	ph = *(struct arg_hdr **)AppParmHandle;
X	ph->message = 0;		/* open file */
X	ph->count = argc;		/* number of args to pass */
X	ap = &ph->lst;
X
X	for (i=0; i < argc; ++i) {
X		strcpy((char *)ap->fName, av[i]);
X		CtoPstr((char *)ap->fName);
X	
X		/* get info the name */
X		repmem((char *)&pb,"",1,sizeof(pb));
X		pb.dirInfo.ioDrDirID = av_curdir(av[i]);
X		pb.dirInfo.ioNamePtr = (StringPtr)ap->fName;
X		if (PBGetCatInfo(&pb, FALSE) == noErr) {
X			ap->vRefNum = pb.hFileInfo.ioVRefNum;
X			ap->fType   = pb.hFileInfo.ioFlFndrInfo.fdType;
X			ap->versNum = 0;
X		} else {
X			ap->vRefNum = 0;
X			ap->fType   = 0;
X			ap->versNum = 0;
X		}
X
X		if ((t = ap->fName[0]+1) & 1) ++t;
X		ap = (AppFile *)(ap->fName + t);
X	}
X#if DEBUG
X	av_dispargs();
X#endif
X	HUnlock(AppParmHandle);	
X	SetZone(curzone);
X}
X
Xvoid av_unputargs() {
X	DisposHandle(AppParmHandle);
X	AppParmHandle = myAppHandle;
X}
X
Xvoid av_dispargs() {
X	char	*arg, buf[BUFSIZ];
X	int	i, t;
X	struct	arg_hdr *ph;
X	AppFile	*ap;
X	
X	printf("av[0]: '%s'\n", strpcpy(buf, CurApName));
X	
X	ph = *(struct arg_hdr **)AppParmHandle;
X	ap = &ph->lst;
X	for (i=0; i < ph->count; ++i) {
X		strpcpy(buf, (char *)ap->fName);
X		printf("av[%d]: %4.4s '%s'\n", i+1, &ap->fType, buf);
X
X		if ((t = ap->fName[0]+1) & 1) ++t;
X		ap = (AppFile *)(ap->fName + t);
X	}
!-E-o-F
echo "x - stat.c"
sed "s/^X//" > stat.c <<'!-E-o-F'
X/*
X *	stat -- return unix stat information.
X */
X#include "portlink.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "string.p"
X#include "stdlib.p"
X#include "getarg.h"
X#include <errno.h>
X
X#define	isadir(pb)	(pb.hFileInfo.ioFlAttrib & 0x0010)	/* bit 4 in ....4 3210 */
X
X#define	EPOC	0	/* map from Jan 1,1904 to ctime's idea of the EPOC */ 
X			/* normally Jan 1,1970, but Lightspeed-C uses the mac's EPOC */
X			
Xint stat(fname, sb) char *fname; struct stat *sb; {
X	CInfoPBRec	pb;
X	OSErr		rc;
X	Str255		name;
X
X	if (fname == NULL || *fname == '\0') {
X		errno = EINVAL;
X		return NULL;
X	}
X	/* get info the name just passed to us */
X	repmem((char *)&pb,"",1,sizeof(pb));
X	pb.dirInfo.ioDrDirID = av_curdir(fname);
X	pb.dirInfo.ioNamePtr = (StringPtr)CtoPstr(strcpy((char *)name, fname));
X
X	if (mac_err(PBGetCatInfo(&pb, FALSE), "PBGetCatInfo")) {
X		return -1;
X	}
X	sb->st_dev   = pb.hFileInfo.ioDirID;
X	sb->st_ino   = pb.hFileInfo.ioFDirIndex;
X	if (isadir(pb)) {
X		sb->st_mode  = S_IFDIR;
X		sb->st_nlink = 2;
X		sb->st_size  = pb.dirInfo.ioDrNmFls;	/* length of the data fork */
X	} else {
X		sb->st_mode  = S_IFREG;
X		sb->st_nlink = 1;
X		sb->st_size  = pb.hFileInfo.ioFlLgLen;	/* length of the data fork */
X#if RESOURCE
X		sb->st_rsize = pb.hFileInfo.ioFlRLgLen;	/* length of the data fork */
X#endif
X	}
X	sb->st_uid   = 0;
X	sb->st_gid   = 0;
X	sb->st_rdev  = sb->st_dev;
X	sb->st_atime = pb.hFileInfo.ioFlBkDat - EPOC;	/* access time is the backup date */
X	sb->st_mtime = pb.hFileInfo.ioFlMdDat - EPOC;	/* modified date */
X	sb->st_ctime = pb.hFileInfo.ioFlCrDat - EPOC;	/* created date */
X	return 0;
X}
X
!-E-o-F
echo "x - stdext.h"
sed "s/^X//" > stdext.h <<'!-E-o-F'
X/*
X *	stdext.h -- standard extensions
X */
X#ifndef _STDEXT_H_DEFINED_
X#define _STDEXT_H_DEFINED_
X
X#define ABORT	(-1)	/* status returns */
X#define ERR	(-1)
X#define OK	0
X
X#define NO	0	/* bool returns */
X#define	YES	1
X
X#define EOS	'\0'
X
X#ifndef NULL
X#define NULL	0
X#endif
X
X#define MAXFNAME 15	/* maximum file name */
X#define MAXPNAME 128	/* maximum path name */
X#define MAXLINE	160	/* maximum line size */
X
Xtypedef unsigned	bool;	/* boolean type */
Xtypedef unsigned char	uchar;	/* unsigned types */
Xtypedef unsigned int	uint;
Xtypedef unsigned long	ulong;
X
Xtypedef struct TABLE	TABLE;	/* table type */
Xtypedef int		STATUS;	/* status type */
Xtypedef unsigned	KEY;
Xtypedef unsigned	RAWKEY;
Xtypedef long 		FPOS;	/* file position */
X
Xextern	char *	memdup(char *, int);		/* malloc a new copy of the memory */
X
Xextern	char *	nextb(char *s);
Xextern	char *	skipb(char *s);
Xextern	char *	skipfld(char *s, int flds);
X
Xextern	char *	strbase(char *s, char sep);	/* point to after sep or s */
Xextern	char *	strrbase(char *s, char sep);	/* point to sep char or end */
Xextern	char *	basename(char *path);		/* point to last part of path */
Xextern	char *	programname(char *pathname, char *misname);	/* dos fixup */
Xextern	char *	tackname(char *path, char *name);
Xextern	int	pathdirlength(char *path);	/* length of the dir part */
Xextern	void	syspath(char *from, char *to);	/* normalize path */
X
Xextern	void	strsetswitch(void);		/* setup the dos switchar */
Xextern	char *	strdelete(char *s, int n);	/* delete n chars from str */
Xextern	char *	strinsert(char *s1, char *s2);	/* s2 inserted into s1 */
Xextern	char *	strtrim(char *s);		/* the string blank trimmed */
Xextern	char *	strnnull(char *s);	/* return a non-null s */
Xextern	char *	strfield(char *p, int n);	/* return ptr to fld n */
Xextern	char *	strflags(uint flag, char *dp);	/* return flags as str */
Xextern	int	strsplit(char **vector, char *str); /* return # of flds */
X
Xextern	char	dos_switchar(char mode);	/* return option char */
Xextern	void	fsync(FILE *);			/* sync a file descriptor */
X
Xextern	char Path_Sep_Str[2];
X#define	PATH_SEP	(Path_Sep_Str[0])
X#define	PATH_SEP_STR	(Path_Sep_Str)
X
X#define bit_flip(f,b)	( f = (f&(~b)) | ((~f)&b) )	/* flip bit b in f */
X
X
X#endif /* _STDEXT_H_DEFINED_ */
!-E-o-F
echo "x - strdup.c"
sed "s/^X//" > strdup.c <<'!-E-o-F'
X/*
X *	strdup -- malloc a copy of string p
X */
X#include <stdlib.h>
X
Xchar *strdup(p) char *p; {
X	char	*s;
X	
X	s = malloc(strlen(p)+1);
X	if (s) strcpy(s, p);
X	return s;
X}
X
!-E-o-F
echo "x - system.c"
sed "s/^X//" > system.c <<'!-E-o-F'
X/*
X *	system -- run a sub-command
X */
X#include <stdio.h>
X#include <string.h>
X#include <HFS.h>
X#include "getarg.h"
X
X#define nil	(void *)0
X
Xtypedef struct LaunchStruct {
X	StringPtr	pfName; 	/* pointer to the name of launchee */
X	long int	param;
X	long int	extBlockLen;	/*number of bytes in extension == 6*/
X	short int	fFlags; 	/*Finder file info flags (see below)*/
X	long int	launchFlags;	/*bit 31,30==1 for sublaunch, others reserved*/
X} *pLaunchStruct;
X
Xstatic	OSErr	sublaunch(char *, char **);
Xstatic	void	subwait(void);
X
Xint system(cmd) char *cmd; {
X	OSErr	rc;
X	char	*p, **av;
X	
X#if DEBUG
X	printf("Run: %s\n", cmd);
X#endif	
X	if ((p = strchr(cmd, ' ')) == NULL) {
X		av_hackargs("");
X	} else {
X		*p++ = '\0';
X		av = av_hackargs(p);
X	}
X
X	rc = sublaunch(cmd, av);
X	return rc < 0 ? -1 : 0;
X}
X
Xstatic OSErr sublaunch(cmd, av) char *cmd, **av; {
X	struct LaunchStruct	myLaunch;
X	Point		where;		/*where to display dialog*/
X	SFTypeList	myFileTypes;	/* we only want APPLs */
X	short int	numFileTypes=1;
X	CInfoPBRec	pb;
X	WDPBRec		wd;
X	StringPtr	dirNameStr;
X	OSErr		rc;
X	char		CmdName[255];
X	
X	/*Get the Finder flags*/
X	repmem((char *)&pb,"",1,sizeof(pb));
X	pb.dirInfo.ioDrDirID = av_curdir(cmd);
X	pb.dirInfo.ioNamePtr = (StringPtr)CtoPstr(strcpy((char *)CmdName, cmd));
X	
X	if (mac_err(PBGetCatInfo(&pb, false), "PBGetCatInfo")) {
X		return -1;
X	}
X	
X	repmem((char *)&wd,"",1,sizeof(wd));
X	if (mac_err(PBHGetVol(&wd, false), "PBHGetVOL")) {
X		return -1;
X	}
X	wd.ioWDProcID = 'ERIC';
X	if (mac_err(PBOpenWD(&wd, false), "PBOpenWD")) {
X		return -1;
X	}
X	/*Set the current volume to where the target application is*/
X	if (mac_err(SetVol(nil, wd.ioVRefNum), "SetVol")) {
X		return -1;
X	}
X
X	av_putargs(av);
X	
X	/*Set up the launch parameters*/
X	myLaunch.pfName = (StringPtr)CmdName;	/*pointer to our fileName*/
X	myLaunch.param = 'LC';	/* No alternate screen or sound buffers set up.
X				   'LC' tells Launch that there is non-junk next */
X	myLaunch.extBlockLen = 6;	/* length of param. block past this long word*/
X	
X	/* from _GetCatInfo copy flags; set bit 6 of low byte to 1 for RO access:*/
X	myLaunch.fFlags = pb.hFileInfo.ioFlFndrInfo.fdFlags;
X
X	/* set BOTH hi bits for a sublaunch */
X	myLaunch.launchFlags = 0xC0000000;
X
X	if ((rc=LaunchIt(&myLaunch)) < 0) {
X		mac_err(rc, "Launch");
X		av_unputargs();
X		return -1;
X	}
X	subwait();
X	av_unputargs();
X	return noErr;
X}
X
XOSErr LaunchIt(pLnch) pLaunchStruct pLnch; {	/* < 0 means error */ 
X	register int rc;
X	
X	/* INLINE $205F, $A9F2, $3E80
X	 * pops pointer into A0 and calls Launch,
X	 * pops D0 error code into result:
X	 */
X	asm {  
X		MOVE.L  pLnch,A0
X        	_Launch
X        	MOVE.W  d0,rc
X	}
X#if DEBUG
X	printf("launch rc=%d\n", rc);
X#endif
X        return rc;
X
X}
X
Xstatic void subwait() {
X	int	i;
X	
X	unsigned short mask;
X	EventRecord event;
X	unsigned long sleep;
X	RgnHandle mouseRgn;
X	
X	mask = ~0;
X	sleep = 10;
X	
X	for (i=0; i++ < 50;) {
X		WaitNextEvent(mask, &event, sleep, nil);
X		switch(event.what) {
X		case 0xf:
X			if ((event.message & 0xf) == 1) {
X#if DEBUG
X				printf("Activated.\n");
X#endif
X				return; 
X			}
X			if ((event.message & 0xf) == 2) {
X#if DEBUG
X				printf("Suspened.\n");
X#endif
X				continue;
X			}
X		case updateEvt:
X		case nullEvent:
X			continue;
X		}
X#if DEBUG
X		printf("what=%4x, msgs=%16lx\n", event.what, event.message);
X#endif
X		if (((event.message >> 24L) & 0xFF) == 0xFD) {
X#if DEBUG
X			printf("Process: %d exited\n", event.where);
X#endif
X			return;
X		}
X	}
X}
X
XOSErr do_launch() {
X	struct LaunchStruct	myLaunch;
X	Point			where;		/*where to display dialog*/
X	SFReply			reply;   	/*reply record*/
X	SFTypeList		myFileTypes;	/* we only want APPLs */
X	short int		numFileTypes=1;
X	HFileInfo		myPB;
X	StringPtr	   	dirNameStr;
X	OSErr			rc;
X	
X#if DEBUG
X#define p(M)	((char *)&myLaunch.M - (char *)&myLaunch)
X	printf("pfName=%lx, param=%lx, extBL=%lx, fFlags=%lx, lFlags=%lx\n",
X		
X	p(pfName), 		/* pointer to the name of launchee */
X	p(param),
X	p(extBlockLen),		/*number of bytes in extension == 6*/
X	p(fFlags), 		/*Finder file info flags (see below)*/
X	p(launchFlags));	/*bit 31,30==1 for sublaunch, others reserved */
X#undef p
X#endif
X
X	where.h = 80;
X	where.v = 90;
X	myFileTypes[0] = 'APPL';		/* we only want APPLs */ 
X	/*Let the user choose the file to Launch*/
X	SFGetFile(where, "", nil, numFileTypes, myFileTypes, nil, &reply);
X	if (!reply.good) {
X		return -1;
X	}
X	dirNameStr = (StringPtr)&reply.fName;	/*initialize to file selected*/
X
X	/*Get the Finder flags*/
X	myPB.ioNamePtr= dirNameStr;
X	myPB.ioFDirIndex= 0;
X	myPB.ioDirID = 0;
X	myPB.ioVRefNum = reply.vRefNum;
X	rc = PBGetCatInfo((CInfoPBPtr) &myPB,false);
X	if (rc != noErr)
X		return rc;
X
X	/*Set the current volume to where the target application is*/
X	rc = SetVol(nil, reply.vRefNum);
X	if (rc != noErr)
X		return rc;
X
X	/*Set up the launch parameters*/
X	myLaunch.pfName = (StringPtr)&reply.fName;	/*pointer to our fileName*/
X	myLaunch.param = 'LC';		/*we don't want alternate screen
X							  or sound buffers*/
X	/*set up LC so as to tell Launch that there is non-junk next*/
X	myLaunch.extBlockLen = 6;		/*length of param. block past
X							  this long word*/
X	/*copy flags; set bit 6 of low byte to 1 for RO access:*/
X	myLaunch.fFlags = myPB.ioFlFndrInfo.fdFlags;	/*from _GetCatInfo*/
X
X	/* Test subLaunch and set launchFlags accordingly	*/
X	myLaunch.launchFlags = 0xC0000000;	/*set BOTH hi bits for a sublaunch	*/
X
X	if ((rc = LaunchIt(&myLaunch)) < 0) {		/* call _Launch			*/
X		/* the launch failed, so put up an alert to inform the user */
X#if DEBUG
X		printf("Launch Failed");
X#endif
X		return rc;
X	} else {
X		return noErr;
X	} /*if reply.good*/
X	subwait();
X}
!-E-o-F
echo "x - vol_getlabel.c"
sed "s/^X//" > vol_getlabel.c <<'!-E-o-F'
X
Xchar *vol_getlabel(drive) char drive; {
X	static Str255	name;
X	int	rnum = 0;
X	OSErr	rc;
X	
X	if ((rc = GetVol(name, &rnum)) != 0) {
X		mac_err("vol_getlabel", rc);
X		return (char *)0;
X	}
X#if DEBUG
X	printf("GetVol: %d -> %s, result: %x\n", rc, name, rnum);
X#endif
X	return PtoCstr((char *)name);
X}
!-E-o-F
-- 
  -- Drew Sullivan, <drew@lethe.uucp>