head	1.3;
access;
symbols
	version39-41:1.2;
locks;
comment	@ *  @;


1.3
date	92.08.09.20.41.54;	author amiga;	state Exp;
branches;
next	1.2;

1.2
date	92.07.04.19.10.06;	author mwild;	state Exp;
branches;
next	1.1;

1.1
date	92.05.17.21.01.29;	author mwild;	state Exp;
branches;
next	;


desc
@@


1.3
log
@change to use 2.x header files by default
add option to ignore global environment (ix.ix_ignore_global_env).
@
text
@/*
 *  This file is part of ixemul.library for the Amiga.
 *  Copyright (C) 1991, 1992  Markus M. Wild
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  $Id: _main.c,v 1.2 1992/07/04 19:10:06 mwild Exp $
 *
 *  $Log: _main.c,v $
 *  Revision 1.2  1992/07/04  19:10:06  mwild
 *  add call to ix_install_sigwinch().
 *
 * Revision 1.1  1992/05/17  21:01:29  mwild
 * Initial revision
 *
 * Revision 1.1  1992/05/14  19:55:40  mwild
 * Initial revision
 *
 */

#define KERNEL
#include "ixemul.h"

#include <dos/var.h>
#include <workbench/startup.h>
#include <dirent.h>

extern int _dos20;
extern  struct ExecBase       *SysBase;

static char **
__get_environ (void)
{
  static char *endmarker = 0;
  char **env = &endmarker;
  DIR *dp;
  struct dirent *de;
  int num_env, num_local = 0;
  char **cp;

  /* 2.0 local environment overrides 1.3 global environment */

  if (_dos20)
    {
      struct Process *me = (struct Process *) FindTask (0);
      struct LocalVar *lv, *nlv;
      
      /* count total number of local variables (skip aliases) */
      for (num_local = 0, 
	     lv  = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
	   nlv = (struct LocalVar *) lv->lv_Node.ln_Succ;
	   lv  = nlv)
	if (lv->lv_Node.ln_Type == LV_VAR)
	  num_local ++;
      
      if (cp = (char **) syscall (SYS_malloc, (num_local + 1) * 4))
	{
	  env = cp;

	  for (lv  = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
	       nlv = (struct LocalVar *) lv->lv_Node.ln_Succ;
	       lv  = nlv)
	    {
	      /* I'm not interested in aliases, really not ;-)) */
	      if (lv->lv_Node.ln_Type != LV_VAR)
	        continue;
	    
	      /* NAME=CONTENTS\0 */
	      *cp = (char *) syscall (SYS_malloc, (strlen (lv->lv_Node.ln_Name) 
						   + 1 + lv->lv_Len + 1));
	      if (*cp)
		sprintf (*cp, "%s=%*.*s", lv->lv_Node.ln_Name, 
			 lv->lv_Len, lv->lv_Len, lv->lv_Value);
	      else
		break;

	      cp ++;
	    }

	  *cp = 0;
	}
      else
	num_local = 0;
    }

  if (ix.ix_ignore_global_env)
    return env;

  /* now go for global variables */
  
  if (dp = (DIR *) syscall (SYS_opendir, "ENV:"))
    {
      /* first count how many entries we have */
      for (num_env = 0; readdir (dp); num_env++) ;
      
      /* skip . and .. */
      syscall (SYS_rewinddir, dp);
      if ((de = (struct dirent *) syscall (SYS_readdir, dp)) 
	  && de->d_namlen == 1 && de->d_name[0] == '.' && --num_env &&
	  (de = (struct dirent *) syscall (SYS_readdir, dp)) 
	  && de->d_namlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.')
	{
	  num_env --;
	  de = (struct dirent *) syscall (SYS_readdir, dp);
	}

      if (num_local)
	{
	  /* only (!) in this case is `env' allocated and not static */
	  char **tmp = (char **) syscall (SYS_realloc, 
					  env, (num_local + num_env + 1) * 4);
	  if (tmp)
	    {
	      cp = tmp + (cp - env);
	      env = tmp;
	    }
	  else
	    /* out of memory !!! */
	    return &endmarker;
	}
      else
	{
	  if (cp = (char **) syscall (SYS_malloc, (num_env + 1) * 4))
	    env = cp;
	  else
	    /* out of memory !!! */
	    return &endmarker;
	}
	  

      for (;de; de = (struct dirent *) syscall (SYS_readdir, dp))
	{
	  struct stat stb;
	  int len = 0;
	  char envfile[MAXPATHLEN];

	  if (_dos20)
	    {
	      /* if this variable already exists locally, skip it */
	      if (FindVar (de->d_name, GVF_LOCAL_ONLY))
		continue;
	    }

	  /* don't include variables with funny names, and don't include
	     multiline variables either, they totally confuse ksh.. */
	  if (index (de->d_name, '.'))
	    continue;

	  sprintf (envfile, "ENV:%s", de->d_name);

	  if (stat (envfile, &stb) == 0)
	    {
	      len = stb.st_size;
	      /* skip directories... shudder */
	      if (! S_ISREG (stb.st_mode))
	        continue;
	    }

	  /* NAME=CONTENTS\0 */
	  *cp = (char *) syscall (SYS_malloc, 
				  de->d_namlen + 1 + len + 1);
	  if (*cp)
	    {
	      int written = sprintf (*cp, "%s=", de->d_name);
	      int fd;

	      if (len)
		{
		  fd = open (envfile, 0);
		  if (fd >= 0)
		    {
		      written += read (fd, *cp + written, len);
		      (*cp)[written] = 0;
		      if ((*cp)[--written] == '\n')
			(*cp)[written] = 0;
		      close (fd);
		    }
		    
		  /* now filter out those multiliners (that is, 
		     variables containing \n, you can have variables
		     as long as want, but don't use \n... */
		  if (index (*cp, '\n'))
		    {
		      syscall (SYS_free, *cp);
		      continue;
		    }
		}
	    }
	  else
	    break;

	  cp ++;
	}

      *cp = 0;

      syscall (SYS_closedir, dp);
      
      return env;
    }
  else
    /* `panic!', no ENV: logical ! */
    return &endmarker;
}


/* smells abit kludgy I know.. but can live with quite few variables in
 * the user area 
 */

int
_main (union { char *_aline; struct WBStartup *_wb_msg; } a1,
       union { int   _alen;  char *_def_window;         } a2,
       int (* main(int, char **, char **)))
#define aline           a1._aline
#define alen            a2._alen
#define wb_msg          a1._wb_msg
#define def_window      a2._def_window
{
  struct Process        *me             = (struct Process *)SysBase->ThisTask;
  int                   exit_val;
  char                  **argv, **env;
  int                   argc;

  if (! me->pr_CLI)
    {
      /* Workbench programs expect to have their CD where the executed
       * program lives. */
      if (wb_msg->sm_ArgList)
	{
	  CurrentDir (wb_msg->sm_ArgList->wa_Lock);
	  syscall (SYS__wb_parse, me, wb_msg, def_window);
	}
      /* argc==0: this means, that argv is really a WBenchMsg, not a vector */
      argc = 0;
      argv = (char **) wb_msg;
    }
  else
    {
      /* if we were started from the CLI, alen & aline are valid and
       * should now be split into arguments. This is done by the
       * function "_cli_parse()", which does wildcard expansion if not
       * disabled (see cli_parse.c). */
      _cli_parse (me, alen, aline, &argc, &argv);
    }

  env = __get_environ ();

  /* this is not really the right thing to do, the user should call
     ix_get_vars2 () to initialize environ to the address of the variable
     in the calling program. However, this setting guarantees that 
     the user area entry is valid for getenv() calls. */
  u.u_environ = &env;

  ix_install_sigwinch ();

  syscall (SYS_exit, main (argc, argv, env));
}
@


1.2
log
@add call to ix_install_sigwinch().
@
text
@d19 1
a19 1
 *  $Id: _main.c,v 1.1 1992/05/17 21:01:29 mwild Exp $
d22 3
d36 1
a36 55
struct Process_20 {
    struct  Task    pr_Task;
    struct  MsgPort pr_MsgPort; /* This is BPTR address from DOS functions  */
    WORD    pr_Pad;             /* Remaining variables on 4 byte boundaries */
    BPTR    pr_SegList;         /* Array of seg lists used by this process  */
    LONG    pr_StackSize;       /* Size of process stack in bytes           */
    APTR    pr_GlobVec;         /* Global vector for this process (BCPL)    */
    LONG    pr_TaskNum;         /* CLI task number of zero if not a CLI     */
    BPTR    pr_StackBase;       /* Ptr to high memory end of process stack  */
    LONG    pr_Result2;         /* Value of secondary result from last call */
    BPTR    pr_CurrentDir;      /* Lock associated with current directory   */
    BPTR    pr_CIS;             /* Current CLI Input Stream                 */
    BPTR    pr_COS;             /* Current CLI Output Stream                */
    APTR    pr_ConsoleTask;     /* Console handler process for current window*/
    APTR    pr_FileSystemTask;  /* File handler process for current drive   */
    BPTR    pr_CLI;             /* pointer to CommandLineInterface          */
    APTR    pr_ReturnAddr;      /* pointer to previous stack frame          */
    APTR    pr_PktWait;         /* Function to be called when awaiting msg  */
    APTR    pr_WindowPtr;       /* Window for error printing                */

    /* following definitions are new with 2.0 */
    BPTR    pr_HomeDir;         /* Home directory of executing program      */
    LONG    pr_Flags;           /* flags telling dos about process          */
    void    (*pr_ExitCode)();   /* code to call on exit of program or NULL  */
    LONG    pr_ExitData;        /* Passed as an argument to pr_ExitCode.    */
    UBYTE   *pr_Arguments;      /* Arguments passed to the process at start */
    struct MinList pr_LocalVars; /* Local environment variables             */
    ULONG   pr_ShellPrivate;    /* for the use of the current shell         */
    BPTR    pr_CES;             /* Error stream - if NULL, use pr_COS       */
};
#include "gcc:include20/dos/var.h"
#define BASE_EXT_DECL
#define BASE_PAR_DECL	
#define BASE_PAR_DECL0	
#define BASE_NAME	ix.ix_dos_base
__inline static struct LocalVar* FindVar(BASE_PAR_DECL UBYTE* name, long unsigned int type)
{
	BASE_EXT_DECL
	register struct LocalVar* res __asm("d0");
	register void *a6 __asm ("a6");
	register UBYTE* d1 __asm("d1");
	register long unsigned int d2 __asm("d2");

	a6 = BASE_NAME;
	d1 = name;
	d2 = type;
	__asm volatile ("
	jsr a6@@(-0x396)"
	: "=r" (res)
	: "r" (a6), "r" (d1), "r" (d2)
	: "d0", "d1", "a0", "a1", "d2");
	return res;
}


d41 1
d57 1
a57 1
      struct Process_20 *me = (struct Process_20 *) FindTask (0);
d68 1
a68 1
      if (cp = (char **) syscall (SYS_malloc, num_local * 4))
d91 2
d98 2
a231 1
  struct ExecBase       *SysBase        = *(void **)4;
@


1.1
log
@Initial revision
@
text
@d19 1
a19 1
 *  $Id: _main.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
d22 3
d313 2
@
