koren@hpfelg.HP.COM (Steve Koren) (11/29/89)
I have a few how-to-do-it style questions for knowlegable Amiga people. Probably email is best for responses; I'll summarize and post if there is sufficient interest. 1) How do you move bits around the filesystem as fast as possible? I am looking to improve the performance of the 'cp' command in SKsh. Right now, I have a loop that does a read() and a write() in 32K chunks (I've tried everything from 4K to 32K). However, c:copy still has a large performance advantage (for the FFS on a 28ms drive). 2) There's a command called something like "SetWindowTitles()" (I'm doing this from memory so that may not be the exact name). I can set the window title to anything I choose; I've found from experimentation that I need to AllocMem() the memory for the title so that it doesn't go away when my program terminates (since apparently SetWindowTitles() doesn't copy the string you give it, it just uses it directly). Well, that much is no problem. But I'd like to get rid of the space used by the *old* title. I am afraid to just FreeMem() it, though, since my program hasn't a clue where it came from. It *could* have been created by an AllocMem() call, or it could be a static string in some program. In the latter case, it would be quite rude to FreeMem() the string. How do I get rid of it if I don't know where it came from? (I can't just save it and put it back later since I am creating a stand-alone binary which changes the title). Also, if I assume it was AllocMem()ed, I don't know how big the buffer was. For example, it could have been 100 allocated bytes with a 20 byte string copied into it. Since FreeMem() needs to know the byte size, I wouldn't be freeing all the memory. 3) How do you execute a program when you know it is resident? I can get a pointer to a resident structure if I have the name; that's no problem. But I'm not sure what to do from there. I can't find a seglist in the structure anywhere. (Even if I had one, there's still the problem of BCPL programs being different thaan Lattice programs which are different from Manx programs which are different from programs compiled on Tuesday). Also, is the ARP resident list the same thing as the AmigaDos resident list? Does anyone have a short bit of code they'd be willing to pass along which executes resident programs? Even if I don't use it directly at least I could perhaps check it out to see how to do it. Any help would be greatly appreciated, thanks, - steve (koren@hpfela.HP.COM)
jimm@amiga.UUCP (Jim Mackraz) (12/01/89)
In article <13920020@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes:
)2) There's a command called something like "SetWindowTitles()" (I'm
) doing this from memory so that may not be the exact name). I can
) set the window title to anything I choose; I've found from experimentation
) that I need to AllocMem() the memory for the title so that it doesn't
) go away when my program terminates (since apparently SetWindowTitles()
) doesn't copy the string you give it, it just uses it directly). Well,
) that much is no problem. But I'd like to get rid of the space used by
) the *old* title. I am afraid to just FreeMem() it, though, since my
) program hasn't a clue where it came from. It *could* have been created
) by an AllocMem() call, or it could be a static string in some program.
) In the latter case, it would be quite rude to FreeMem() the string.
) How do I get rid of it if I don't know where it came from? (I can't
) just save it and put it back later since I am creating a stand-alone
) binary which changes the title). Also, if I assume it was AllocMem()ed,
) I don't know how big the buffer was. For example, it could have been
) 100 allocated bytes with a 20 byte string copied into it. Since
) FreeMem() needs to know the byte size, I wouldn't be freeing all the
) memory.
In normal circumstances, this is no problem. If you close your window
when you exit, Intuition will not need to fetch that window's screen title
again, I believe. It leaves it rendered on the screen bar, and
hangs onto the pointer, but that pointer gets reset when any window
becomes active in the same screen. I'm pretty sure that the title
won't get rerendered using the bogus pointer.
Do you have a counterexample? It sounds a lot like you are setting
titles for windows you do not own and then exiting, or otherwise
treading dangerously on thin ice.
You should try not to leave little "title turds" hanging around in memory,
nor should you guess whether to free memory you encounter.
Write a library, have it track your memory turds, and when you call
its SetAllocedWindowTitles(), it will toss the old title if it recognizes
as something from its list. You could also hang a bookkeeping list
off of a named port that your weird little program can find.
jimm
--
-------------------------------------------------- - opinions by me
"This voice console is a *must*. I press Execute.
`Hello, I know that you've been feeling tired.
I bring you love and deeper understanding.' " -lyrics by Kate Bush
koren@hpfelg.HP.COM (Steve Koren) (12/04/89)
> Do you have a counterexample? It sounds a lot like you are setting > titles for windows you do not own and then exiting, or otherwise > treading dangerously on thin ice. Well, this point is a little unclear to me. Who "owns" the CLI window? Is the the currently running shell? What if a shell is invoked from within a shell? I wished to add a command which lets the user change the window title bar of the CLI window by saying something like: window -title "my title" I wanted to implement this command as an external binary. The binary sets the window title and then exits. Perhaps that is not a legal thing to do, in which case I'll leave the command out. It is probably a bit late for this now, but it is my belief (just opinion here) that a child procedure should not depend on dynamically allocated data passed to it hanging around after the child exits. If it needs the data, it should copy it. Having it depend on the data's persistance increases coupling strength between the two procedures, which is generally regarded as a "bad thing" in software engineering circles. (Of course, I do this sometimes myself :-) Anyhow, thanks for the help. - steve
koren@hpfelg.HP.COM (Steve Koren) (12/07/89)
Another "how do you do it" question: I want to find out, for any given device name, whether that is a currently mounted file system device. Moreover, I want to do this without bringing up the requester. In short, I need a routine like this: int IsMounted(char *Device_Name) {} First of all, I would expect that there would be an easy way to do it; ie, something like the above function call. If there is no programatic interface to this, I will probably forget it until one appears. Does anyone know? I can't find it documented anyplace, but it seems like a logical thing to have. (On the other hand, a way to execute programs seems like a logical thing to have, too, and that's not there either, at least not in a usable manner). I tried to write such a function using ARP's AddDADevs() call, but I had problems with that. They have a flag called DLX_UNMOUNTED which you can examine, but it is only valid for "volume" names, not device (like df0:) or "dir names" (like c:). It tells me that df0: is always mounted, even if it contains no disk, and it tells me that c: is never mounted, even though it is assigned someplace. In short, it doesn't do me any good. Anybody know if my IsMounted() funtion exists, or if not, when it might appear? - steve
peter@sugar.hackercorp.com (Peter da Silva) (12/08/89)
In article <13920023@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: > Well, this point is a little unclear to me. Who "owns" the CLI window? Its instance of console.device. The *best* situation would be a console.device that took escape sequences for "set window title", "set menu", and so on. -- Peter "Have you hugged your wolf today" da Silva <peter@sugar.hackercorp.com> `-_-' 'U` "Really, a video game is nothing more than a Skinner box." -- Peter Merel <pete@basser.oz>
jms@tardis.Tymnet.COM (Joe Smith) (12/09/89)
In article <13920023@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: Steve> Well, this point is a little unclear to me. Who "owns" the CLI window? In article <4698@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes: Peter>Its instance of console.device. Peter>The *best* situation would be a console.device that took escape sequences Peter>for "set window title", "set menu", and so on. I second that suggestion. Something like: ESC ] l title-for-window ESC \ To change the title on an open window ESC [ 2 t To iconify the window ESC ] L label ESC \ To change label of iconified window ESC ] I DH0:file.info ESC \ To use different icon image ESC [ 1 t To go from icon back to normal window ESC [ 3 ; 5 0 ; 1 0 0 t To move upper left corner to y=50, x=100 ESC [ 4 ; 2 0 0 ; 6 4 0 t To make window full size (200x640 pixels) ESC [ 5 t Window to front ESC [ 6 t Window to back ESC [ 7 t Redraw window ESC [ 8 ; 1 2 ; 4 0 t Change size to 12 rows of 40 columns Does any system other than Sun use these escape sequences? Has anyone hacked up a console.device to use something like this? -- Joe Smith (408)922-6220 | SMTP: JMS@F74.TYMNET.COM or jms@gemini.tymnet.com BT Tymnet Tech Services | UUCP: ...!{ames,pyramid}!oliveb!tymix!tardis!jms PO Box 49019, MS-D21 | PDP-10 support: My car's license plate is "POPJ P," San Jose, CA 95161-9019 | humorous dislaimer: "My Amiga speaks for me."
ecarroll@vax1.tcd.ie (Eddy Carroll) (12/10/89)
In article <13920027@hpfelg.HP.COM>, koren@hpfelg.HP.COM (Steve Koren) writes: > Another "how do you do it" question: > > I want to find out, for any given device name, whether that is a currently > mounted file system device. Moreover, I want to do this without bringing > up the requester. In short, I need a routine like this: > > int IsMounted(char *Device_Name) {} > The following seems to do the trick: /* Compile with Lattice C V5.04 */ #include <exec/types.h> #include <proto/exec.h> #include <proto/dos.h> /* * Checks to see if the specified device (DF0:, DF1:, XYZ: etc.) is * mounted; returns TRUE if it is, FALSE if it isn't. */ int IsMounted(devname) char *devname; { BPTR lock; APTR oldwindow; struct Process *me = (struct Process *)FindTask(NULL); oldwindow = me->pr_WindowPtr; /* Save current requester state */ me->pr_WindowPtr = (APTR)-1; /* Disable AmigaDOS requesters */ lock = Lock(devname, ACCESS_READ); /* Try and get lock on device */ if (lock) /* If we succeeded, */ UnLock(lock); /* Free up the lock */ me->pr_WindowPtr = oldwindow; /* Restore original requesters */ return (lock); /* Return TRUE if device online */ } > - steve I'm really impressed with SKsh. As many others have said already, a "real" Unix shell has long been overdue for the Amiga (though Matt's shell has done me nicely in the meantime). -- Eddy Carroll ----* Genuine MUD Wizard | "You haven't lived until INTER: ecarroll@vax1.tcd.ie | you've died in MUD!" UUCP: {..uunet}!mcvax!ukc!vax1.tcd.ie!ecarroll | -- Richard Bartle
peter@sugar.hackercorp.com (Peter da Silva) (12/11/89)
In article <13920027@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: > I want to find out, for any given device name, whether that is a currently > mounted file system device. There are two parts to this question. First, whether it's a file-system device. Second, whether it's currently mounted. The second is easy... you can just set your pr_windowptr to -1 and try to access it. To see if it's a file system device is a bit harder. You can try doing a getdiskinfo on it. Or you can traverse the device list and kill two birds with one stone. Let me dig up the code... Bummer. That disk has an error. I'll run disksalv on it while I read news and let you know what comes out. (let's see you do *that* on a Mac!) -- Peter "Have you hugged your wolf today" da Silva <peter@sugar.hackercorp.com> `-_-' 'U` "I haven't lost my mind, it's backed up on tape somewhere"
peter@sugar.hackercorp.com (Peter da Silva) (12/11/89)
Here it is, as promised. You can scan the device list with this code, and do all sorts of fun stuff. Make SKSH the first program to support wildcarding the device name! : This archive contains the following files... : 'mounted.c' : 'readme' : To extract them, run the following through /bin/sh echo x - mounted.c sed 's/^X//' > mounted.c << '//END' X/* MOUNTED -- is a disk mounted? X * X * Copyright 1987 by Peter da Silva. X * X * This code may be freely distributed provided this notice is X * retained. It may be hacked, munged, and incorporated in commercial X * software if you want, so long as you credit me for it. X */ X#include <stdio.h> X#include <ctype.h> X#include <libraries/dosextens.h> X Xstruct DosLibrary *DosLibrary; X X/* hack BPTRS */ X X#define toAPTR(b) ((b)<<2) X#define toBPTR(a) ((a)>>2) X X#define VOLUMES 16 /* If you have more than 16 drives, tough luck :-> */ Xchar volumes[VOLUMES][33]; Xint nvols; X Xmain(ac, av) Xint ac; Xchar **av; X{ X GetVolumes(); X if(ac==0) wbmain(); /* I think this should work with Lattice */ X else if(ac==1) dumpvols(); X else if(ac==2 && av[1][0] != '?') X exit(mounted(av[1])?0:5); /* Code 5 is warn */ X else { X /* should loop & return success only if all work. */ X printf("MOUNTED Copyright (c) 1987 by Peter da Silva.\n"); X printf("Usage: mounted [volumename]\n"); X printf("Returns error code 5 is volume is not mounted.\n"); X exit(10); /* code 10 is error. maybe Should be 20 (fatal). */ X } X exit(0); X} X XGetVolumes() /* who'se out there */ X{ X struct RootNode *root; X struct DosInfo *info; X struct DeviceList *list; X X DosLibrary = OpenLibrary("dos.library", 0); X if(!DosLibrary) { X printf("Can't open dos.library\n"); X exit(2); X } X nvols = 0; X X /* The following 3 lines caused me some worry, but they worked X first time. Thank you C=Amiga. */ X root = DosLibrary -> dl_Root; X info = toAPTR(root->rn_Info); X list = toAPTR(info->di_DevInfo); X while(list) { X if(list->dl_Type == DLT_VOLUME && /* is it a device? */ X list->dl_Task != 0) { /* Ignore unmounted devices */ X char *ptr; X int count; X ptr = toAPTR((BPTR)list->dl_Name); X count = *ptr++; X if(count > 16) /* Should be a CONSTANT */ X count = 16; X strncpy(volumes[nvols], ptr, count); X volumes[nvols][count] = 0; X nvols++; X } X list = toAPTR(list->dl_Next); X } X CloseLibrary(DosLibrary); X} X Xwbmain(dummy) /* if run from workbench, just list mounted volumes */ X{ X FILE *fp; X if(!(fp = fopen("CON:160/50/320/100/Mounted volumes."))) X return; X fdumpvols(fp); X sleep(10); X fclose(fp); X} X Xsleep(n) /* This should have been provided by Aztec, for god's sake. */ X{ X Delay(50*n); X} X Xdumpvols() X{ X fdumpvols(stdout); X} X Xfdumpvols(fp) XFILE *fp; X{ X int i; X for(i = 0; i < nvols; i++) X printf("%s\n", volumes[i]); X} X Xmounted(name) /* The biggee */ Xchar *name; X{ X int i; X for(i = 0; i < nvols; i++) X if(streq(volumes[i], name)) X return 1; X return 0; X} X Xstreq(s1, s2) Xchar *s1, *s2; X{ X normalise(s1); X normalise(s2); X return strcmp(s1, s2)==0; X} X Xnormalise(s) Xchar *s; X{ X int i; X for(i = 0; s[i]; i++) X if(isupper(s[i])) X s[i] = tolower(s[i]); X else if(s[i]==':') { X s[i] = 0; X break; X } X} //END echo x - readme sed 's/^X//' > readme << '//END' XMOUNTED is a quick little program I wrote to tell if a disk is mounted Xor not. It's intended to be used in startup-sequences to conditionally Xexecute programs from df1. For example, mine includes: X Xmounted playit Xif not warn X run playit:play playit:bachfugue.smus playit: Xendif X XSo if I start up with the disk "playit" in df1: it plays a bach fugue Xduring loading. This program illustrates how to deal with BPTRs in a Xwell behaved way, and how to get hold of the device list. It's full Xof magic numbers and inefficient code, and including stdio bloats it Xup to 8K. A little tidying up can probably get it down quite a bit. But Xit fits nicely in *my* c: directory and I'm arrogant enough to think XI have better things to do. It's a good idea to have the AmigaDOS Xmanual open to pages 266-269 while you're checking out the code. XIt's written for Aztec V3.40a with the +P option set, so it should run Xjust fine with Lattice. X X -- Peter da Silva. X -- Author of the fantastic screen hack "Workbench Lander". X -- And incredibly modest guy. //END : end of archive. exit 0 -- Peter "Have you hugged your wolf today" da Silva <peter@sugar.hackercorp.com> `-_-' 'U` "I haven't lost my mind, it's backed up on tape somewhere"
cmcmanis%pepper@Sun.COM (Chuck McManis) (12/11/89)
In article <13920027@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: >Another "how do you do it" question: > >I want to find out, for any given device name, whether that is a currently >mounted file system device. Moreover, I want to do this without bringing >up the requester. In short, I need a routine like this: > > int IsMounted(char *Device_Name) {} The simple way : #include <libraries/dosextens.h> APTR OldWindow; ULONG l, mounted; struct Process *pr; OldWindow = pr->pr_WindowPtr; pr->pr_WindowPtr = -1; /* Turn off requesters */ l = Lock(Volume_Name, ACCESS_READ); /* Check for volume mounted */ mounted = (l != 0); if (mounted) UnLock(l); pr->pr_WindowPtr = OldWindow; return(mounted); >First of all, I would expect that there would be an easy way to do it; >ie, something like the above function call. If there is no programatic >interface to this, I will probably forget it until one appears. Does >anyone know? I can't find it documented anyplace, but it seems like a >logical thing to have. The above code will do what you want, however ... >I tried to write such a function using ARP's AddDADevs() call, but I had >problems with that. They have a flag called DLX_UNMOUNTED which you can >examine, but it is only valid for "volume" names, not device (like df0:) >or "dir names" (like c:). It tells me that df0: is always mounted, even if >it contains no disk, and it tells me that c: is never mounted, even though >it is assigned someplace. In short, it doesn't do me any good. You don't seem to grok what Volume's are. They are basic unit of Disk, not the device like df0:. If I have a volume on a floppy, I don't care what disk drive it is in. DF0: is a device which is either present or not present. That and the geometry of the disks it will read aree the only interesting tidbits about it. You can figure out if a volume is currently inserted into DF0: but generally this is useless info. Assigns, like C:, are something else entirely. Their function is to name a file or directory unambiguously. They provide a "universal" name for different directories. The information provided within the assignment includes the volume that they point are actually on so it is fairly trivial to check to see if they are available. But again, they are never "mounted", they simply exist to say "If you need this named group of files, this context independent name will point to them." Is that any clearer? --Chuck McManis uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@Eng.Sun.COM These opinions are my own and no one elses, but you knew that didn't you. "If it didn't have bones in it, it wouldn't be crunchy now would it?!"
koren@hpfelg.HP.COM (Steve Koren) (12/11/89)
> int IsMounted(char *Device_Name) {}
Ok, I have the solution now. Thank you to those who responded. The
solution was only a few lines of code; you have to make the pointer to
the error window (-1), call Lock(), then restore the pointer.
- steve
fgd3@jc3b21.UUCP (Fabbian G. Dufoe) (12/12/89)
If I followed this discussion correctly the fundamental question is how do you find out what disk devices are configured? That's important if you want to write a file requester that automatically creates a button for each disk device. How do I know the system has df0:? Oh, right, they all have df0:. Well, what about df3:? Is there a RAM: drive? A RAD:? --Fabbian Dufoe 350 Ling-A-Mor Terrace South St. Petersburg, Florida 33705 813-823-2350 UUCP: ...uunet!pdn!jc3b21!fgd3
kodiak@amiga.UUCP (Robert R. Burns) (12/13/89)
In article <4731@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes: )Here it is, as promised. You can scan the device list with this code, and do )all sorts of fun stuff. )X/* MOUNTED -- is a disk mounted? )X * )X * Copyright 1987 by Peter da Silva. )X * )X * This code may be freely distributed provided this notice is )X * retained. It may be hacked, munged, and incorporated in commercial )X * software if you want, so long as you credit me for it. Please hack it to include a Forbid() around the manipulation of the dos device list, lest you find yourself holding onto an obsolete node and then linking off to junk. -- Bob Burns, amiga!kodiak _ | /_ _|. _ | Commodore __ |_) _ |_ _ )' |<(_)(_)|(_\|< /\ | ||| _` /\ |_)(_\| )(_\ | | \ Software ___/..\|\/|||__|/..\___ Faith
doug@xdos.UUCP (Doug Merritt) (12/13/89)
In article <4731@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes: >Here it is, as promised. You can scan the device list with this code, and do >all sorts of fun stuff. Make SKSH the first program to support wildcarding >the device name! Hey! My "filetype" program was the first to support wildcards in device names! I claim priority by about 2 1/2 years. Doug -- Doug Merritt {pyramid,apple}!xdos!doug Member, Crusaders for a Better Tomorrow Professional Wildeyed Visionary
doug@xdos.UUCP (Doug Merritt) (12/13/89)
In article <4730@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes: >In article <13920027@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: >> I want to find out, for any given device name, whether that is a currently >> mounted file system device. > >There are two parts to this question. First, whether it's a file-system device. >Second, whether it's currently mounted. The second is easy... you can just >set your pr_windowptr to -1 and try to access it. To see if it's a file >system device is a bit harder. You can try doing a getdiskinfo on it. > >Or you can traverse the device list and kill two birds with one stone. Let >me dig up the code... > >Bummer. That disk has an error. I'll run disksalv on it while I read news and >let you know what comes out. (let's see you do *that* on a Mac!) Since I haven't seen Peter's code yet (DOA? Give my regards to Lazarus), here's mine ("fs.c"). Hmmm. I just saw Peter's code after all, but since I spent an hour creating "fs.c" out of the relevent piece of my "filetype" program, I'll post it anyway. It does lots more than Peter's code (weak justification for posting :-). In fact, it does more than you asked for...given a device/volume/assign name, it tells you everything known about it (see examples below). If you want to follow Peter's suggestion about having SKsh wildcard device names, I'm very much in favor...I'm always wishing the CLI supported that. Anyway, as I said in another posting today, my filetype program does exactly that, and I can give you complete working code to support that feature if you want it. As for this "fs.c", it works quite well, although I see Chuck McManis just posted something (Subject: "Re: Problem with handler) that suggests that in addition to checking for a handler task, I should perhaps also check DSKENV and even send an ACTION_DISKINFO packet. I'll have to look into that; but meanwhile the simple check has never produced any problem reports. Examples of 'fs' in action: For instance, "fs Workbench1.3:" produces Workbench1.3: -- volume (mounted on DF0) Conversely, "fs df0:" produces df0: -- device (file system; contains Workbench1.3) After ejecting the diskette, the same commands produces df0: -- device (file system; ejected) Or for ASSIGN'ed directories, "fs src:" produces src: -- directory (SupraDrive0:SOURCE) The code works on ram:, rad:, etc. Hope it helps. Doug -- Doug Merritt {pyramid,apple}!xdos!doug Member, Crusaders for a Better Tomorrow Professional Wildeyed Visionary ---------------------- CUT HERE ---------------------------------- /* * fs -- check filesystem devices (extracted from my 'filetype' source) * * copyright 1987 Douglas R. Merritt * License to use is hereby granted on the condition that this * notice be retained unchanged, and that any commercial * use must conspicuously credit the copyright holder. * */ #define NONE_SUCH 0 #define DEVICE 1 #define DIRECTORY 2 #define VOLUME 3 char *ExtraInfo; #define TextCountDirEntries(N) "" char *strdup(), *Name2Path(), *concat3(); #include "ctype.h" #include "exec/types.h" #include "libraries/dos.h" #ifdef BADDR #undef BADDR #endif #define BADDR(N) ((char *) ( ((ULONG)(N)) << 2) ) #define BCAST(TYPE, VAL) ((TYPE) BADDR((ULONG)VAL)) /* * RoundUp0 -- ceiling (yields 0 if n % TO == 0) * BufRound -- given buffer address, rounds up to word boundary */ #define RoundUp0(N,TO) ( (TO - (((ULONG)N) & (TO-1)) ) & (TO-1)) #define BufRound(BUF) &BUF[ RoundUp0(BUF,4) ] extern char *calloc(); extern struct FileHandle *Output(), *Open(), *output; extern ULONG Read(); #include "exec/nodes.h" #include "exec/memory.h" #include "exec/resident.h" #include "libraries/dosextens.h" #include "libraries/dos.h" #include "libraries/diskfont.h" #include "libraries/filehandler.h" #include "exec/libraries.h" #include "workbench/startup.h" ULONG Examine(), ExNext(); /* move to def.h? */ struct FileLock *Lock(), *ParentDir(); struct Process *FindTask(); struct FileInfoBlock *GetInfo(); char *FileName(), *Name2Path(), *concat3(); extern struct DosLibrary *DOSBase; typedef struct DeviceList *DevPtr; /************************* misc. functions ************************/ /* * is this a device name? (e.g. "ser:") */ int IsDevName(name) char *name; { char *s; for (s=name; *s; ++s) if (*s == ':') break; if (!s[0] || s[1]) return(0); return(1); } /* IsDevName() */ /* * compare a string and a BSTR, case-insensitive */ StrBstrCmp(s, b) unsigned char *s; BPTR b; { int total, rdone, sdone, c1, c2; unsigned char *r, *rstart; if (!s || !b) return(-1); r = (unsigned char *) BADDR(b); total = *r++; rstart = r; rdone = sdone = 0; while (1) { if (!*s) sdone = 1; if ((r - rstart) >= total) rdone = 1; if (sdone || rdone) return(sdone - rdone); c1 = isupper(*s) ? tolower(*s) : *s; c2 = isupper(*r) ? tolower(*r) : *r; if (c1 != c2) return(c1 - c2); ++s; ++r; } /*NOTREACHED*/ } /* StrBstrCmp() */ /* * convert a BSTR to a string * We count on exit() freeing the allocated memory. */ char * Bstr2Str(s) unsigned char *s; { char *ret; int len; if (!s) s = (unsigned char *) "\0"; else s = (unsigned char *) BADDR(s); len = s[0] & 0xff; ret = calloc(1, len+2); strncpy(ret, &s[1], len); ret[ len ] = '\0'; return(ret); } /* Bstr2Str() */ /* * given a pointer to the MsgPort part of a task structure, return * the name found in the Node portion. */ char * taskname(p) struct MsgPort *p; { struct Node *t; char *s; if (!p) return(0); t = (struct Node *) p->mp_SigTask; if (t->ln_Name) { s = t->ln_Name; if (*s) return(strdup(s)); } return((char *) 0); } /* taskname() */ /* * case-insensitive string compare */ stricmp(a, b) /*register*/ char *a, *b; { int c1, c2; if (!a || !b) return(-1); while (*a && *b) { c1 = isupper(*a) ? tolower(*a) : *a; c2 = isupper(*b) ? tolower(*b) : *b; if (c1 != c2) return(c1 - c2); ++a; ++b; } return(((int) *a) - ((int) *b)); } /* stricmp() */ #define GetLock(cur) BCAST(struct FileLock *, cur->dl_Lock) #define GetVol(cur) BCAST(struct DeviceList *, cur->fl_Volume) #define DevNode(cur) ((struct DeviceNode *) cur) #define IsVolMounted(cur) (cur->dl_Task != NULL) /* * Find device list entry of specified type and handler values. * Used to match volumes with devices & vice versa. */ struct DeviceList * FindDevType(task, type) struct MsgPort *task; ULONG type; { struct DosInfo *dos; struct RootNode *root; struct DeviceList *dev, *cur; if (!task) return(0); /* * find device list, starting from Dosbase; see AmyDos Tech. Ref Man * and libraries/dosextens.h */ root = (struct RootNode *) DOSBase->dl_Root; dos = BCAST(struct DosInfo *, root->rn_Info); dev = BCAST(struct DeviceList *, dos->di_DevInfo); /* device is *supposed* to be treated differently, so we do: */ if (type == DLT_DEVICE) { Forbid(); for (cur=dev; cur!=NULL; cur=BCAST(DevPtr, cur->dl_Next)) { if (cur->dl_Type != DLT_DEVICE) continue; if (DevNode(cur)->dn_Task == task) { Permit(); return(cur); } } Permit(); } else { Forbid(); for (cur=dev; cur!=NULL; cur=BCAST(DevPtr, cur->dl_Next)) { if (cur->dl_Type != type) continue; if (cur->dl_Task == task) { Permit(); return(cur); } } Permit(); } return(0); } /* FindDevType() */ /* * check device list to see if this name is on it */ int IsDevice(buf) char *buf; { struct DosInfo *dos; struct RootNode *root; struct MsgPort *task; DevPtr dev, cur; char *s, name[128], *strchr(); char *str, *on, *devname; enum FILETYPE ret; int mtd, isfs; struct Process *tp; APTR tmp; strcpy(name, buf); if (s=strchr(name, ':')) *s = '\0'; /* erase ':' */ else return(NONE_SUCH); /* fail safe...shouldn't happen */ /* * find device list, starting from Dosbase; see AmyDos Tech. Ref Man * and libraries/dosextens.h */ Forbid(); /* vvvvvv */ root = (struct RootNode *) DOSBase->dl_Root; dos = BCAST(struct DosInfo *, root->rn_Info); dev = BCAST(struct DeviceList *, dos->di_DevInfo); for (cur=dev; cur!=NULL; cur=BCAST(DevPtr, cur->dl_Next)) { s = BCAST(char *, cur->dl_Name); if (StrBstrCmp(name, cur->dl_Name)) continue; switch(cur->dl_Type) { case DLT_DEVICE: #if 0 /* * this older code is interesting, but it turns out nobody puts * anything very useful in those fields. */ if (DevNode(cur)->dn_Handler) { ExtraInfo = Bstr2Str(DevNode(cur)->dn_Handler); } else if (DevNode(cur)->dn_Task) { ExtraInfo = taskname(DevNode(cur)->dn_Task); } if (!ExtraInfo || !*ExtraInfo || !isprint(*ExtraInfo) || !isprint(ExtraInfo[1])) ExtraInfo = "no id"; #endif task = DevNode(cur)->dn_Task; Permit(); /* ^^^^^^ */ #if 0 tp = FindTask((char *) 0 ); tmp = tp->pr_WindowPtr; tp->pr_WindowPtr = (APTR) -1L; isfs = IsDir(GetInfo(buf)); tp->pr_WindowPtr = tmp; if (isfs) { #endif if (task) { char buf[256], *str; strcpy(buf, "file system; "); if (cur=FindDevType(task, DLT_VOLUME)) { str = Bstr2Str(cur->dl_Name); strcat(buf, "contains "); strcat(buf, str); free(str); } else { strcat(buf, "ejected"); } ExtraInfo = strdup(buf); } else { ExtraInfo = "non-file system"; } return(DEVICE); case DLT_DIRECTORY: cur = GetVol(GetLock(cur)); mtd = IsVolMounted(cur); Permit(); /* ^^^^^^ */ if (mtd) { ExtraInfo = Name2Path(buf); } else { char *tmp, *dup; dup = Bstr2Str(cur->dl_Name); tmp = "unmounted volume "; ExtraInfo = concat3(tmp, dup, ""); free(dup); } return(DIRECTORY); case DLT_VOLUME: mtd = IsVolMounted(cur); Permit(); /* ^^^^^^ */ if (!mtd) { ExtraInfo = "unmounted"; return(VOLUME); } /* * avoid bug in ram disk; try * dir "RAM Disk:" * (task hangs, don't say I didn't warn you) */ if (!stricmp(buf, "RAM Disk:")) { str = TextCountDirEntries("ram:"); } else { str = TextCountDirEntries(buf); } task = DevNode(cur)->dn_Task; /* "impossible" error: */ if (!(cur=FindDevType(task, DLT_DEVICE))) { devname = strdup("???"); } else { devname = Bstr2Str(cur->dl_Name); } on = "mounted on ", ExtraInfo = concat3(str, on, devname); free(str); free(devname); return(VOLUME); default: Permit(); /* ^^^^^^ */ ret = NONE_SUCH; return(ret); } break; } Permit(); /* ^^^^^^ */ return(NONE_SUCH); /* unknown volume name */ } /* IsDevice() */ /* * copy a string into newly allocated space */ char * strdup(s) char *s; { char *ret; if (!s) return(0); ret = calloc(1, strlen(s)+1); strcpy(ret, s); return(ret); } /* strdup() */ /* * concatenate 3 strings into newly allocated storage */ char * concat3(a, b, c) char *a, *b, *c; { int total; char *ret; register char *tmp; total = strlen(a) + strlen(b) + strlen(c); tmp = ret = calloc(1, total+1); while (*a) *tmp++ = *a++; while (*b) *tmp++ = *b++; while (*c) *tmp++ = *c++; *tmp = '\0'; return(ret); } /* concat3() */ /* * convert any name (e.g. relative to current directory) to its * true full path name (in newly allocated space) */ char * Name2Path(name) char *name; { struct FileLock *Ilock; char buf[256]; Ilock = Lock(name, (ULONG) ACCESS_READ); if (!Ilock) return(strdup(name)); Lock2Path(Ilock, buf); UnLock(Ilock); return(strdup(buf)); } /* Name2Path() */ /* * Get full path corresponding to lock (locked file should exist!) * Since we have to go upward one directory at a time, * we have to go all the way to the top before we can build * the path left to right. A data stack is used for this. */ Lock2Path(curlock, pathbuf) struct FileLock *curlock; char *pathbuf; { #define LOCKSTACKSIZE 128 struct FileLock *locklist[LOCKSTACKSIZE]; UBYTE Ibuf [ sizeof(struct FileInfoBlock) + 4]; struct FileInfoBlock *Ifib; int i; char *s, *path; Ifib = (struct FileInfoBlock *) BufRound(Ibuf); if (!Examine(curlock, Ifib)) return(0); /* if (!IsDir(Ifib)) return(0); */ /* * find full path name; build LIFO stack of * pushed locks; when full use popped locks with * Examine() to get each name in path. */ for (i=0; i<LOCKSTACKSIZE; i++) { locklist[i] = curlock; if (!(curlock = ParentDir(curlock)) ) break; /* normal loop exit */ } path = &pathbuf[0]; if (i >= LOCKSTACKSIZE) { err("Too many subdirectories"); *path++ = '?'; *path++ = '/'; --i; } /* * concatenate each component of path */ if (!Examine(locklist[i--], Ifib)) goto wierd; for (s=Ifib->fib_FileName; *s; ) *path++ = *s++; *path++ = ':'; while (i >= 0) { if (!Examine(locklist[i], Ifib)) goto wierd; for (s=Ifib->fib_FileName; *s; ) *path++ = *s++; if (i>0) *path++ = '/'; --i; } *path = '\0'; return(path - &pathbuf[0]); wierd: *path++ = '?'; *path++ = '/'; *path = '\0'; return(path - &pathbuf[0]); } /* Lock2Path() */ /* * is this a directory? */ IsDir(Ifib) struct FileInfoBlock *Ifib; { if (!Ifib) return(0); if (Ifib->fib_DirEntryType > 0) return(1); return(0); } /* IsDir() */ main(argc, argv) int argc; char **argv; { int type; char *typename; if (argc != 2 || !IsDevName(argv[1])) { printf("Usage (e.g)-- devinfo df0:\n"); exit(1); } type = IsDevice(argv[1]); printf("%s -- ", argv[1]); switch(type) { case NONE_SUCH: typename = "does not exist"; break; case DEVICE: typename = "device"; break; case DIRECTORY: typename = "directory"; break; case VOLUME: typename = "volume"; break; default: typename = "???"; } printf(" %s ", typename); if (ExtraInfo) printf("(%s)\n", ExtraInfo); else printf("\n"); } err(s) char *s; { printf("error: %s\n", s); } -- Doug Merritt {pyramid,apple}!xdos!doug Member, Crusaders for a Better Tomorrow Professional Wildeyed Visionary
koren@hpfelg.HP.COM (Steve Koren) (12/14/89)
> pr->pr_WindowPtr = -1; /* Turn off requesters */ That was the key thing I needed to know. Thanks. It works, but I've never seen it documented anyplace, so I'm a bit nervous about it. > You don't seem to grok what Volume's are. They are basic unit of Disk, not > the device like df0:. If I have a volume on a floppy, I don't care what .... > inserted into DF0: but generally this is useless info. Assigns, like C:, .... > Is that any clearer? Yes, I have understood the differences between volumes and devices since around 1985, but I disagree with your comment about the status of df0: being useless info. If the user has included 'df0:c' in his path, I need to bypass df0: if there is no disk inserted. The user might well do this instead of using the volume name to access the files in the 'c' directory of whatever disk happens to be in df0: at the time, while c: might point to the 'c' directory on his hard disk. Anyhow, this new feature of ignoring offline parts of the path has been added; it will appear in 1.3. I also do that for some commands; for example, a 'cd df0:' will not produce the requester if there is no disk in df0:. - steve
cmcmanis%pepper@Sun.COM (Chuck McManis) (12/15/89)
In article <13920033@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: > ... I disagree with your comment about the status of df0: >being useless info. If the user has included 'df0:c' in his path, I >need to bypass df0: if there is no disk inserted. The user might well >do this instead of using the volume name to access the files in the 'c' >directory of whatever disk happens to be in df0: at the time, while c: >might point to the 'c' directory on his hard disk. This is an interesting semantic for path searching that I don't suspect is intuitive. When I read this originally, I thought what you might want to do is find out what volume was in df0:c, and store that so that if the user had made their path df0:c;df0:tools;sys:lc;Utilities: you could note the volume that was on df0: and not search df0:c or df0:tools when it wasn't mounted. However, on rereading it I suspect you really want the behaviour to be if there is *any* disk in df0: and it has a c directory search it at this point in the path. At first this sounds kind of nifty since you don't care what the volume is you can just change your path by swapping the disk in df0:. And yet, on closer inspection, it seems that there might be massive user confusion if they had only floppy drives and were trying to run a script that involved more disks then they had floppies. Let's say they have one floppy and their script is a usenet news unpacker. Now they have a disk full of Usenet news, and a "usenet" system disk which has on it compress, rnews etc. Now if their path was df0:c, when they start up the script, everything works until they have to swap the system disk with the data disk. The next command that runs (let's further assume the script is in ram: so that they don't have to go back to the system disk to read it.) the next command it searches for df0:c, finds it isn't there and the script exits with command not found. Not to friendly, and not to useful either. Something that happens to me all of the time is that I've renamed my EMACs "ed" because I just type ed and it gives me whatever editor I use on the system I type it on. This works because I've deleted the CBM ed from all of my system disks. Now if I suddenly put a fresher copy of a workbench into my drive, I would wind up with the wrong editor. As I see it the Volume concept makes single drive machines possible because you can specify the volume name and the machine will always ask you to insert the disk if it isn't available. This all brings up another interesting idea. Lets say you cached the names of all the executables in a path. Now searching the path would be really fast, and you would never look at a disk unless you needed a command from it, and you could request disks that weren't in a drive currently to be loaded if you needed a command from them. Of course when the contents of the directories changed you would have to type rehash or something similar to get them back into your path but csh users live with that today and it doesn't seem to bother them. --Chuck McManis uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@Eng.Sun.COM These opinions are my own and no one elses, but you knew that didn't you. "If it didn't have bones in it, it wouldn't be crunchy now would it?!"
peter@sugar.hackercorp.com (Peter da Silva) (12/15/89)
In article <5010@amiga.UUCP> kodiak@batgirl.UUCP (Robert R. Burns) writes: > Please hack it to include a Forbid() around the manipulation of the dos > device list, lest you find yourself holding onto an obsolete node and then > linking off to junk. Oops. Sorry, Bob. -- Peter "Have you hugged your wolf today" da Silva <peter@sugar.hackercorp.com> `-_-' 'U` "I haven't lost my mind, it's backed up on tape somewhere"
peter@sugar.hackercorp.com (Peter da Silva) (12/15/89)
In article <13920033@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: > Anyhow, this new feature of ignoring offline parts of the path has been > added; it will appear in 1.3. I also do that for some commands; for > example, a 'cd df0:' will not produce the requester if there is no disk > in df0:. Could you make this settable? With default ON in interactive use and OFF otherwise? Sometimes you want the requestor. -- Peter "Have you hugged your wolf today" da Silva <peter@sugar.hackercorp.com> `-_-' 'U` "I haven't lost my mind, it's backed up on tape somewhere"
koren@hpfelg.HP.COM (Steve Koren) (12/18/89)
> This all brings up another interesting idea. Lets say you cached the names > of all the executables in a path. Now searching the path would be really > fast, and you would never look at a disk unless you needed a command from Yeah, I think csh (Un*x) does that. I might do it evenentually, but there's a bunch of issues to be worked out first. Also, Peter writes (re: bypassing disk requesters): > Could you make this settable? With default ON in interactive use and OFF > otherwise? Sometimes you want the requestor. I think so. That's a good idea, and should be easy to do. - steve
peter@sugar.hackercorp.com (Peter da Silva) (12/19/89)
In article <13920034@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: > Also, Peter writes (re: bypassing disk requesters): > > Could you make this settable? With default ON in interactive use and OFF > > otherwise? Sometimes you want the requestor. > I think so. That's a good idea, and should be easy to do. Another thing: how about going back and checking the unmounted volumes with requestors ON if you don't find the command in any of the mounted components of your PATH? (and how about allowing wildcards on volume names, huh?) -- Peter "Have you hugged your wolf today" da Silva <peter@sugar.hackercorp.com> `-_-' 'U` "I haven't lost my mind, it's backed up on tape somewhere"
kim@uts.amdahl.com (Kim DeVaughn) (12/20/89)
In article <4797@sugar.hackercorp.com>, peter@sugar.hackercorp.com (Peter da Silva) writes: > In article <13920034@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes: > > Also, Peter writes (re: bypassing disk requesters): > > > > Could you make this settable? With default ON in interactive use and OFF > > > otherwise? Sometimes you want the requestor. > > > I think so. That's a good idea, and should be easy to do. > > Another thing: how about going back and checking the unmounted volumes with > requestors ON if you don't find the command in any of the mounted components > of your PATH? If you do this, could you make this settable? With default either way. Some people don't want requesters at all. /kim -- UUCP: kim@amdahl.amdahl.com or: {sun,decwrl,hplabs,pyramid,uunet,oliveb,ames}!amdahl!kim DDD: 408-746-8462 USPS: Amdahl Corp. M/S 249, 1250 E. Arques Av, Sunnyvale, CA 94086 BIX: kdevaughn GEnie: K.DEVAUGHN CIS: 76535,25
koren@hpfelg.HP.COM (Steve Koren) (01/03/90)
I have a question about the console device: The Amiga console device normally blocks programs from outputting text if you have typed characters from the keyboard that have not yet been read. For example, I can type my_prog which outputs some stuff, and if I type some characters while my_prog is loading, my_prog will produce no output until I press return. I want to be able to convince the console that its OK for my_prog to output some characters. I wish to use this for SKsh; for example, you type a command, and just before the Sksh prompt appears you type another. Currently, SKsh won't display the prompt while you type the second command, since the console is stopping it from doing so. Does anyone know how I can fix this? Something like ProdConsoleDevice() would be what I need. thanks, any help will be appriciated! -steve (koren@hpfela.HP.COM)
jac@muslix.llnl.gov (James Crotinger) (01/05/90)
Does Sksh use ConMan? One of the conman devices (used to be cnd:, but I think 1.3c calls it cnn:) does non-blocking type-ahead. Lots of VMS users asked for this, and I really like it. Does the real ksh do this? I may just have to give it a try. Anyway, cnn: allows you to type ahead whilee the text is scrolling. The text you type will show up the next time the console is ready to read. However if the program throws the console into raw mode you lose what you typed. Jim
koren@hpfelg.HP.COM (Steve Koren) (01/08/90)
> Does Sksh use ConMan? One of the conman devices (used to be cnd:, but > I think 1.3c calls it cnn:) does non-blocking type-ahead. Lots of VMS No, right now it simply uses the AmigaDos console device and sends ANSI codes to it. Does ConMan support ANSI control codes? I'd prefer to obtain the desired non-blocking behavior with the AmigaDos console device. I'm trying to keep SKsh as independent as possible of non-AmigaDos software. I already depend on ARP for binary execution (since there was no reliable way to accomplish this in AmigaDos), so even now SKsh cannot be used on a stock Amiga until the user finds ARP. There has been alot of confusion from people who have a really old arp and try to use SKsh. If 1.4 brings a way to execute external binaries reliably, I will remove the ARP dependency from SKsh. There is nothing wrong with ARP, but using it means that 1) SKsh will break if ARP goes away or breaks, 2) SKsh will break if user's have an old version of ARP, and 3) users must know how where to get ARP. > users asked for this, and I really like it. Does the real ksh do this? Yes, the real ksh does this (at least on some systems). I like it too. > the console is ready to read. However if the program throws the console > into raw mode you lose what you typed. Right now, SKsh does put the console in raw mode sometimes. It has to in order to accomplish the command line editing functions. So, does anyone know how to accomplish non-blocking input with the normal AmigaDos console device? thanks, - steve