[comp.sys.amiga.tech] AmigaLine #D1, Disconnecting a program such that you can EndCLI

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (11/17/88)

	AMIGALINE #D1,	Matthew Dillon

	Disconnecting a program such that you can EndCLI and also allow the
	program to call Execute().

Problem:

	You want to disconnect a program such that when you RUN <nil: >nil:
	(using the new 1.3 RUN) you can then EndCLI the cli.

	This program wants to be able to use Execute() to run other programs. 
	The problem is that Execute() requires a valid pr_ConsoleTask (console)
	or it will freeze.

Solution: General

	Run <nil: >nil: mycprogram

	If using the main() entry point, you can fclose(stderr) to remove
	the reference to "*".  If using the _main() entry point, stdio is
	not setup and thus you do not need to do this (in fact, you can't
	use stdio at all without crashing the computer).

	note: being able to fclose(stderr) from the main() entry point 
	works with Aztec C.  I don't know about Lattice.  Aztec always
	does an Open("*", 1006) to setup stderr and this reference must
	be removed.

					--

	At this point, you can EndCLI and the cli window goes away.  However,
	the 'mycprogram' cannot call Execute() or otherwise run other 
	external programs for two reasons:

		(1) pr_ConsoleTask is still non-NULL and points to the now
		    defunct window (i.e. you will cause a task-held requester)

		(2) you cannot set pr_ConsoleTask to NULL... Execute() does
		    not accept it and freezes up.

					--

	So, you must set pr_ConsoleTask to some other valid device.  Guess
	what?  Any device will do except NIL: which isn't a real device.  For
	example, RAM: :

		extern APTR DeviceProc();
		proc->pr_ConsoleTask = DeviceProc("ram:");

		(assuming RAM: exists)

	What does this do?  Any program which tries to open the console will
	actually open the file "RAM:*", as in Open("RAM:*", 1006).  
	Unfortunetly, there is no way to place "*" in anything but the 
	root directory of the device.  This is essentially a garbage file.

	But the ultimate goal is achieved ... you can kill the CLI window
	and still arbitrarily run programs from the detached program with
	impunity.

	The only possible problem which I have yet to test is when several
	programs try to access RAM:* as their console at the same time.  
	Since the file is openned 1006, other programs trying to Open() it
	will fail while the first programs is still running.  What happens?

							-Matt

nordmark@nada.kth.se (Arne Nordmark) (11/20/88)

In article <8811161843.AA28461@postgres.Berkeley.EDU> dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
>
>	You want to disconnect a program such that when you RUN <nil: >nil:
>	(using the new 1.3 RUN) you can then EndCLI the cli.

[stuff deleteted]

>	So, you must set pr_ConsoleTask to some other valid device.  Guess
>	what?  Any device will do except NIL: which isn't a real device.  For
>	example, RAM: :

Better yet, use null:

It's functionally identical to NIL:, but is a *real* dos-device with it's
own message-port. I've posted it to the moderator for comp.sources.amiga

>		extern APTR DeviceProc();
>		proc->pr_ConsoleTask = DeviceProc("ram:");
>
>		(assuming RAM: exists)

Do this instead:

		proc->pr_ConsoleTask = DeviceProc("null:");

>	But the ultimate goal is achieved ... you can kill the CLI window
>	and still arbitrarily run programs from the detached program with
>	impunity.
>
>	The only possible problem which I have yet to test is when several
>	programs try to access RAM:* as their console at the same time.  
>	Since the file is openned 1006, other programs trying to Open() it
>	will fail while the first programs is still running.  What happens?

God knows what happens. With null: this is no problem since everybody
can open it as many times as he wants, just like with NIL:

I've used null: for half a year now, with no problems at all.
In my version of AmiCron I set pr_ConsoleTask to DeviceProc("null:")
and now it doesn't requires a window to run!

>							-Matt

  - Gunnar

SNAIL: Gunnar Nordmark          VOICE: (+46) 8 - 755 42 52
       Nora strand 5
       S-182 34 DANDERYD        EMAIL: gno@stacken.kth.se
       SWEDEN                          gno@SESTAK.BITNET

"Words, words, words."  William Shakespeare 

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (11/22/88)

Gunnar gno@stacken.kth.se Writes:
>I've used null: for half a year now, with no problems at all.
>In my version of AmiCron I set pr_ConsoleTask to DeviceProc("null:")
>and now it doesn't requires a window to run!

	Try entering a crontab entry which does this:

	"run list"

	Does that work?  If so, you've just solve all my problems!
I.E.  the command is to 'run' something but redirecting the run <nil: <nil:
is cheating... run has to work alone.  Also try bringing up an application
via the crontab that has external execution capability (i.e. DME, then try an
execute command from DME's command line).

				-Matt

nordmark@nada.kth.se (Arne Nordmark) (11/23/88)

In article <8811211839.AA12164@postgres.Berkeley.EDU> dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
>Gunnar gno@stacken.kth.se Writes:
>>In my version of AmiCron I set pr_ConsoleTask to DeviceProc("null:")
>>and now it doesn't requires a window to run!
>
>	Try entering a crontab entry which does this:
>
>	"run list"
>
>	Does that work?  If so, you've just solve all my problems!

Well, I use ARP in my AmiCron and it barfs on the Run command.

But instead I wrote a test program called DevRun that I've included in this
posting. DevRun lets you run a command with any pr_ConsoleTask you like.

Your example "run list" works great with my null: device.
(I don't think I've solved *all* your problems though :-)

Execute (or is it Run?) seems to use the pr_ConsoleTask for all its IO
including the program it spawns. So if you say
	DevRun "Run List" null:
everyting, including Run's own output goes to neverland. (i.e. null:)

Here is the code. Tryit out on my null: device wich should arrive in
comp.sources.amiga soon.

Good luck!   -Gunnar

/***************************************************************************
 *
 *	devrun.c	Example program that runs a command from
 *			an alternative "console"
 *
 *	Lattice compile:
 *		lc -L DevRun
 *
 *	Manx compile:
 *		cc devrun
 *		ln -o DevRun devrun.o -lc
 *
 *
 *	Usage:  DevRun "commandline" [device]
 *
 *	examples:
 *			DevRun "Run List" null:
 *
 *		Runs the command "Run List" from my null: device
 *
 *			DevRun Date
 *
 *		Runs the command "Date" from the default console
 *		  (completely useless in other words)
 *
 *			DevRun "Date > Now" null:
 *
 *		Runs the command "Date" from my null: device
 *		  The output redirected to the file Now
 *
 *	Author:
 *		Gunnar Nordmark
 *		Nora strand 5
 *		S-182 34  DANDERYD
 *		SWEDEN
 *
 *		gno@stacken.kth.se	(stacken.kth.se!gno@uunet.uu.net)
 *	 	gno@SESTAK.BITNET
 *
 ***************************************************************************/

#include <exec/types.h>
#include <libraries/dosextens.h>
#include <stdio.h>

LONG Execute();
struct Task *FindTask();
struct MsgPort *DeviceProc();

main(argc, argv)
int argc;
char **argv;
{
	struct Process *proc=(struct Process *)FindTask(NULL);
	APTR old_device_proc=proc->pr_ConsoleTask; /* Save the old console */
	APTR new_device_proc;
	char *device;
	LONG ret;
 
	if (argc<2 || argc >3) {
		fprintf(stderr, "Usage:  DevRun \"commandline\" [device]\n");
		exit(RETURN_FAIL);
	}

	if (argc==3) {
		device=argv[2]; /* Get the device process */
		new_device_proc=(APTR)DeviceProc(device);
		if (new_device_proc==NULL) {
			fprintf(stderr, "There's no device-process for %s\n",
				device);
			exit(RETURN_FAIL);
		}
		proc->pr_ConsoleTask=new_device_proc;
	}
	fclose(stderr); /* Get rid of the stderr Open ("*",...) stuff */
	ret=Execute(argv[1], NULL, NULL);
	proc->pr_ConsoleTask=old_device_proc; /* Restore the old console */

	return ret;
}