Path: utzoo!dretor!dciem!nrcaer!julie!mcr From: mcr@julie.UUCP (Michael Richardson) Newsgroups: comp.sys.amiga.tech Subject: Unix V7 functionality under (or along with) AmigaDOS? (*LONG*) Keywords: Unix V7 Minix AmigaDOS shells ... CATS? Randell?? :-) Message-ID: <0776.AA0776@julie> Date: 9 Mar 89 18:08:28 GMT References: Followup-To: comp.sys.amiga.tech Organization: Sandleman Software Works' Debugging Department, Ottawa, ON Lines: 253 Someone said: (beats me, my copy of Amiga Usenet isn't up that type of thing) [Reading in the message and deleting everything but the Subject: and the Message-ID: line and then changing Message-ID: to References: works nicely. Anyway--- ] SOMEONE SAID: >>>>The shell has the responsibility of unloading (or not unloading >>>>in the case of resident segments) the programs. >>> >>>But does this hold true when the shell is NOT running under the CLI? >>>It will be running as a DOS Process, but NOT as a CLI process. The I don't have any real AmigaDOS docs (just Exec docs) and I've yet to completely understand just what is in the Process structure that is not found in the Task structure.... >> Shells are shells, period. The Workbench is a visual shell. >>Exit() itself does almost nothing, except return control to the "shell" >>as if the program had exited. But this also implies (correctly) that CLIs are NOT shells. They are special. That is the very first thing that strikes people about Unix, and where most if not all of its power comes from. Programs are programs. >I'm willing to use AddTask if it will still operate as a DOS process >and be able to call dos.library routines. How should I go about doing >this? Also, what makes pr_SegList bizare? (aside from usage of >BPTRs?) So am I!!!! >Hmm. Looking at "The AmigaDOS manual," (AmigaDOS V1.1, I believe; >published February 1986.) it lists the Process structure starting with >BPTR SegArray, describing it as an array of SegList pointers with its >size in the first longword. [seems consistent with BSTR's.] I really have to get this a copy. >On the other hand, in the include file, the >Process struct is defined with pr_task, pr_MsgPort, pr_Pad, and then ^^^^^^ ^^^^^^^^^ I would assume that the pr_MsgPort has something to do with receiving packets back from the file system task. (For Reads and Writes) >Hmm. This seems the only reasonable way to go; replace CreateProc(), >and use AddTask(). I take it the extra segments in the SegArray >(pr_SegList) are such as that cleanup code for CreateProc() which are >not to be unloaded. May I safely assume that if I replace >CreateProc() with my own function which sets up a structure starting What stuff do you intend on adding? >output of the executed program, or set them to zero and define the >standard input, output and error channels in my own structure? (I >want stderr as a passed file descriptor, along with stdin and >stdout...) I want to break dependency from the CLI, yet still be able ^^^^^^^^^^^^^^^^^^^^^^^ >to run programs which depend on the CLI themselves. (possibly by >using or replacing the AmigaDOS RUN command.) I disagree. CA= won't document a lot of things because they say "it will break in 1.4" but they won't change things because "too many things would break" I think the problem is: "will user x be able to run program y under your shell" (tell them to start a CLI) the problem is "will program x be able to run under the CLI or your shell" That way, you can encourage people to write programs that conform to your standard (generic programs will just need a relinking with a new startup) instead of letting them run all their old code unmodified. If they need the old stuff, "C=+ESC" gets most people a CLI... >Similarly, should I zero pr_ConsoleTask and pr_FileSystemTask or not? >(I intend to have read(), write(), etc. calls... functionally similar >to Lattice's, but not dependant on the Lattice compiler or lc.lib >library.) Wish read(), write(), were better documented. I don't really understand what they do... (internally) >I have programmed quite a bit under Unix and rather prefer the Unix >file system and system calls to many of those available on the Amiga. >I don't much care for AmigaDOS or BCPL. Some of the user interface >issues between Unix and AmigaDOS are trivial, like "../" vs. "/" for >parent directory. >Other differences, such as the way directories are implemented, differ >more significantly. Unix-style directories are far more efficient at >directory listing (but no the hash-lookup searching AmigaDOS does) >than AmigaDOS with its backpointers. Also, the lack of links in >AmigaDOS is a big loss. Rah! Rah! Rah! >I want to write a shell which will be more cleanly implemented than >the CLI (i.e. no BCPL) and which will start programs with argv AND >envp arrays, and have Unix-type calls available. Get out my head! That was my idea! :-) Actually that would be a good initial difference for this shell. Set a flag (pr_CIN and pr_COS==NULL? hmm. ) and then pass the argv and envp. The program which is executed could then check for the flag and (if not set) do the "standard" startup or just use the argv and envp. (Or things can be linked with a startup that doesn't have this. Programmer choice) How to pass argv and envp? This is a message passing operating system right? Well, send the task a message... How do you tell when the task is finished? Well, exit() returns this message (with an error code) and then does a Wait(). The exec.library (woops that name is taken. The Execute.library then--- I guess I mean Execute.device see below) then RemTasks it, and deallocates it (if it isn't on the resident list) and makes the error code available to the task. What else? How about a standard tc_ExeceptionCode? Make SIGBREAKF_CTRL_C, and ^E exceptions. ^C will cause an "abort()" routine to be run. (signal() or sigvec()'able of course) The standard abort() should be able to run some number of clean up functions, and then it should call "exit()" Also, when ^E is received, the task does a "Wait(SIGBREAKF_CTRL_F)" and PRESTO, Job control!!! (Or course, ^E is signal()/sigvec() settable too.) When the shell wishes the job to continue, just send a ^F signal. (Or any other agreed upon signal) This assumes something about the shell though: that it isn't part of the same task as the programs it runs. This is fine, as this CLI "subroutine" stuff bugs me a lot. It ISN'T fork()/exec(), but it does make a much more orthogonal system, shells send messages to "execute" servers, much the same way that comm programs send messages to "serial" devices... >What I would like to do is write a file system based in part on Minix, >and in part on AmigaDOS (but *no* BCPL!) which would work more >effectively with floppy-based systems. (i.e. Mount file systems like >in Minix/Unix, but volume-oriented, as in AmigaDOS.) Have you talked to Colin (Plumb?) (microsoft!w-colinp) His extent based file system looks quite nice... I suggest that you start by writting a file system handler that understands the AmigaDOS file system in C. Then rewrite it (with a different file system type) that is completely C. (Get rid of BSTR, etc... Incompatible, but that's ok.) >I DO rather like the low level Exec. The ROM Kernal is quite well >designed. I consider AmigaDOS to be rather poor, on the other hand. >It DOES contain some rather clever design features; assigned devices >are useful (though not good as a general replacement for environment >variables) and being able to mount devices is a definite plus. Unmount is need though. >But what I DO want now is the fork() and exec() system calls from >Unix. (execve() for purists) And I'm willing to take a stab at >writing them myself. Why? In a way I rather like the idea of calling CreateTask with an entry point. I think that the underlying mechanism could be changed to support a more fork() like system, but in how many cases is fork() not followed immediately by an exec()? In this case, the vfork() call was invented, and also the "copy-on-write" MMU stuff (although that is very usefull for shared libraries too) >Fork() would start with a FindTask(0L) call, allocate space for a new >Task structure, copy the data over, and similarly duplicate the text >and data segments, modifying the appropriate fields to point to the ^^^^^^^^^^^ >copies, and link in the new task to Exec with either AddTask() >(obviously preferable) or manually if necessary. As has been pointed out, this is VERY difficult without an MMU. >void AddTask(struct Task *, char *, char *); task initialPC, finalPC >Anyhow, I see several points of possible difficulty. So do I. >First, is whether this fork() routine would need to disable >multitasking (interrupts seem fine) at all, such as when copying the I don't think so. >Task structure of the current process. Or, is it perfectly safe and >consistent (no race conditions) to let multitasking continue >unhindered while it initializes the new Task structure? (Clearly, it ^^^^^^^^^^^ Nobody but you knows about the task structure until you AddTask. And at that point, you had better be finished fiddling with it, because the process is ready to run. >Second, how should the fork() call make execution begin at the return >point of said fork() call? (Perhaps this question will answer itself >when I look up AddTask().) Look up the return address of the fork(). Put the return value under it, and give the address of a routine that will just do an "RTS". This stack is, of course a freshly copied stack, having all the frame pointers, changed. Even if you leave all the data and code shared, you must at least duplicate the stack. >Finally, (I hope) how to handle file descriptors. The solution for >this would seem to be to have file i/o operations in this library - >open(), close(), read(), write(), etc. and have a table of file >descriptors, file pointers, and AmigaDOS file handles (for now, at >least.) that the "parent" and "child" share. I don't know whether or >not to try to preserve the parent/child relationship as Unix does, or >try some other setup. I'll have to think about it. The fexec() library function would lookup the highest FileHandle assigned to ask (kept in an Exec list of course to eliminate that 20 files open bit) and duplicate each one. This list would be part of the standard stuff passed to the execute.device (along with argv, envp and the name of the program and/or address at which to execute) Parent/child is preserved without being forced. (How do you do redirection? Well, I guess one has to write a custom fexec() as one couldn't go around changing the your own FileHandles, there being no seperation like fork(). --- We don't need to duplicate a running process structure, just get a new "OSInterface" structure. Modify that, and pass it to the execute.device. Actually, that could be interesting: OpenDevice("Execute.device","ls",&lsInterface,0) and then modify the lsInterface (instance of OSInterface) to change the environment, etc... and then do a "DoIO()" on it with a CMD_START (or Send/BeginIO() for asynchronous processes...)) [lots of stuff on exec() deleted] >How to handle resource deallocation of the old process presents yet >another difficulty. (oh, but of course!) >allocated by the prior process need to be released. One solution (the >cheap and easy way out) is to free malloc() allocated memory (if I >write a malloc(), etc. set of routines) and leave other resources >allocated, (such as memory gained from AllocMem) to allow resources to >be passed to the called program. This makes sense to me. If you need to pass the resource, you are already Amiga specific, use the amiga specific call... >initialization program ("Unix" bootstrap program) which would install >the library in ram, start an "init" process, and then hang around as >the "system task" to coordinate everything. I called it "Execute.device" >Someone... anyone... please reply. I wouldn't want this to be a >wasted effort. (And more information/ideas is always helpful.) > >Enough for now. I was going to send this as a reply (and some people may wish that I had) but I changed my mind... >Deven >-- >------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine --------------------- -- :!mcr!: Michael Richardson Amiga v--------+ UUCP: uunet!attcan!lsuc!nrcaer!julie!mcr | INTERNET mcr@doe.carleton.ca Fido: Michael Richardson @ 1:163/109.10<--+ Alter @ 7:483/109.10