Path: utzoo!utgpu!jarvis.csri.toronto.edu!dptcdc!lethe!drew From: drew@lethe.UUCP (Drew Sullivan) Newsgroups: comp.sys.mac.programmer Subject: Re: Sublaunching in LSC Message-ID: <3172@lethe.UUCP> Date: 7 Jul 89 18:46:04 GMT References: <943@diemen.cc.utas.oz> Reply-To: drew@lethe.UUCP (Drew Sullivan) Organization: Systems Software Lines: 1816 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 X#include X#include 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 X#include 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 X#include 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, ""); 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 X#include 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 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 X#include 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 X#include 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 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 X#include X#include "string.p" X#include "stdlib.p" X#include "getarg.h" X#include 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 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 X#include X#include 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, 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 X#include X#include 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 X#include 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 X#include 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, ""); 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 X#include 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 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 X#include 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 X#include 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 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 X#include X#include "string.p" X#include "stdlib.p" X#include "getarg.h" X#include 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 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 X#include X#include 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,