home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
ixemul-45.0-src.tgz
/
tar.out
/
contrib
/
ixemul
/
library
/
_main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
9KB
|
316 lines
/*
* 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.
*
* _main.c,v 1.1.1.1 1994/04/04 04:30:43 amiga Exp
*
* _main.c,v
* Revision 1.1.1.1 1994/04/04 04:30:43 amiga
* Initial CVS check in.
*
* Revision 1.3 1992/08/09 20:41:54 amiga
* change to use 2.x header files by default
* add option to ignore global environment (ix.ix_ignore_global_env).
*
* 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
*
*
*/
#define _KERNEL
#include "ixemul.h"
#include "kprintf.h"
#include <dos/var.h>
#include <workbench/startup.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
char **get_global_environment(void)
{
DIR *dp;
struct dirent *de;
int num_env;
char **cp, **env;
/* now go for global variables */
dp = (DIR *)syscall (SYS_opendir, "ENV:");
if (dp == NULL)
/* `panic!', no ENV: logical ! */
return NULL;
/* first count how many entries we have */
for (num_env = 0; syscall(SYS_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 ((cp = (char **)kmalloc((num_env + 1) * 4)))
env = cp;
else
/* out of memory !!! */
return NULL;
for (; de; de = (struct dirent *) syscall (SYS_readdir, dp))
{
struct stat stb;
int len = 0;
char envfile[MAXPATHLEN];
/* Don't include variables with funny names, and don't include
multiline variables either, they totally confuse ksh.. */
if (strchr(de->d_name, '.'))
continue;
sprintf (envfile, "ENV:%s", de->d_name);
if (syscall(SYS_stat, envfile, &stb) == 0)
{
len = stb.st_size;
/* skip directories... shudder */
if (!S_ISREG (stb.st_mode))
continue;
}
/* NAME=CONTENTS\0 */
*cp = (char *)kmalloc(de->d_namlen + 1 + len + 1);
if (*cp)
{
int written = sprintf (*cp, "%s=", de->d_name);
int fd;
if (len)
{
fd = syscall(SYS_open, envfile, 0);
if (fd >= 0)
{
written += syscall(SYS_read, fd, *cp + written, len);
(*cp)[written] = 0;
if ((*cp)[--written] == '\n')
(*cp)[written] = 0;
syscall(SYS_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 (strchr(*cp, '\n'))
{
kfree(*cp);
continue;
}
}
}
else
break;
cp++;
}
*cp = 0;
syscall (SYS_closedir, dp);
return env;
}
static char **__get_environ (void)
{
static char *endmarker = 0;
char **env = &endmarker;
int num_env, num_local = 0;
char **cp, **tmp;
struct Message *msg;
struct MsgPort *port;
/* 2.0 local environment overrides 1.3 global environment */
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,
(int)lv->lv_Len, (int)lv->lv_Len, lv->lv_Value);
else
break;
cp++;
}
*cp = NULL;
}
else
return env;
if (ix.ix_flags & ix_ignore_global_env)
return env;
port = ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port;
if (port == NULL)
{
if ((port = CreatePort(NULL, 0)))
{
ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port = port;
port->mp_Flags = PA_IGNORE;
ix.ix_notify_request.nr_Name = "ENV:";
ix.ix_notify_request.nr_Flags = NRF_SEND_MESSAGE;
if (!StartNotify(&ix.ix_notify_request))
{
DeletePort(port);
ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port = NULL;
return env;
}
}
else
return env;
}
if (ix.ix_global_environment == NULL)
ix.ix_global_environment = get_global_environment();
else if ((msg = GetMsg(port)))
{
do
{
ReplyMsg(msg);
} while ((msg = GetMsg(port)));
/* free the old environment */
for (tmp = ix.ix_global_environment; *tmp; kfree(*tmp++)) ;
kfree(ix.ix_global_environment);
ix.ix_global_environment = get_global_environment();
}
if (ix.ix_global_environment == NULL)
return env;
for (num_env = 0, tmp = ix.ix_global_environment; *tmp; tmp++, num_env++);
tmp = (char **)syscall (SYS_realloc, env, (num_local + num_env + 1) * 4);
if (tmp == NULL)
return env;
env = tmp;
cp = &env[num_local];
for (tmp = ix.ix_global_environment; *tmp; tmp++)
{
char *p = strchr(*tmp, '='), *f;
int offset;
*p = 0;
f = _findenv(env, *tmp, &offset);
*p = '=';
if (f)
continue;
*cp++ = (char *)syscall(SYS_strdup, *tmp);
*cp = NULL;
}
return env;
}
/* 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;
char **argv, **env;
int argc;
int exitcode;
KPRINTF (("entered __main()\n"));
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);
if (is_ixconfig(argv[0]))
return 10;
}
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 ();
/* The finishing touch :-) Not really necessary, though. */
errno = 0;
exitcode = main (argc, argv, env);
syscall(SYS_exit,exitcode);
return 0;
}