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 >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  316 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  _main.c,v 1.1.1.1 1994/04/04 04:30:43 amiga Exp
  20.  *
  21.  *  _main.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:43  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.3  1992/08/09  20:41:54  amiga
  26.  *  change to use 2.x header files by default
  27.  *  add option to ignore global environment (ix.ix_ignore_global_env).
  28.  *
  29.  *  Revision 1.2  1992/07/04  19:10:06  mwild
  30.  *  add call to ix_install_sigwinch().
  31.  *
  32.  * Revision 1.1  1992/05/17  21:01:29  mwild
  33.  * Initial revision
  34.  *
  35.  *
  36.  */
  37.  
  38. #define _KERNEL
  39. #include "ixemul.h"
  40. #include "kprintf.h"
  41.  
  42. #include <dos/var.h>
  43. #include <workbench/startup.h>
  44. #include <dirent.h>
  45. #include <stdio.h>
  46. #include <string.h>
  47.  
  48. char **get_global_environment(void)
  49. {
  50.   DIR *dp;
  51.   struct dirent *de;
  52.   int num_env;
  53.   char **cp, **env;
  54.  
  55.   /* now go for global variables */
  56.   
  57.   dp = (DIR *)syscall (SYS_opendir, "ENV:");
  58.   if (dp == NULL)
  59.     /* `panic!', no ENV: logical ! */
  60.     return NULL;
  61.  
  62.   /* first count how many entries we have */
  63.   for (num_env = 0; syscall(SYS_readdir, dp); num_env++) ;
  64.       
  65.   /* skip . and .. */
  66.   syscall (SYS_rewinddir, dp);
  67.   if ((de = (struct dirent *) syscall (SYS_readdir, dp)) 
  68.       && de->d_namlen == 1 && de->d_name[0] == '.' && --num_env &&
  69.       (de = (struct dirent *) syscall (SYS_readdir, dp)) 
  70.       && de->d_namlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.')
  71.     {
  72.       num_env --;
  73.       de = (struct dirent *) syscall (SYS_readdir, dp);
  74.     }
  75.  
  76.   if ((cp = (char **)kmalloc((num_env + 1) * 4)))
  77.     env = cp;
  78.   else
  79.     /* out of memory !!! */
  80.     return NULL;
  81.       
  82.   for (; de; de = (struct dirent *) syscall (SYS_readdir, dp))
  83.     {
  84.       struct stat stb;
  85.       int len = 0;
  86.       char envfile[MAXPATHLEN];
  87.  
  88.       /* Don't include variables with funny names, and don't include
  89.          multiline variables either, they totally confuse ksh.. */
  90.       if (strchr(de->d_name, '.'))
  91.         continue;
  92.  
  93.       sprintf (envfile, "ENV:%s", de->d_name);
  94.  
  95.       if (syscall(SYS_stat, envfile, &stb) == 0)
  96.         {
  97.           len = stb.st_size;
  98.           /* skip directories... shudder */
  99.           if (!S_ISREG (stb.st_mode))
  100.             continue;
  101.         }
  102.  
  103.       /* NAME=CONTENTS\0 */
  104.       *cp = (char *)kmalloc(de->d_namlen + 1 + len + 1);
  105.       if (*cp)
  106.         {
  107.           int written = sprintf (*cp, "%s=", de->d_name);
  108.           int fd;
  109.  
  110.           if (len)
  111.             {
  112.               fd = syscall(SYS_open, envfile, 0);
  113.               if (fd >= 0)
  114.                 {
  115.                   written += syscall(SYS_read, fd, *cp + written, len);
  116.                   (*cp)[written] = 0;
  117.                   if ((*cp)[--written] == '\n')
  118.                 (*cp)[written] = 0;
  119.                   syscall(SYS_close, fd);
  120.                 }
  121.             
  122.               /* now filter out those multiliners (that is, 
  123.                  variables containing \n, you can have variables
  124.                  as long as want, but don't use \n... */
  125.               if (strchr(*cp, '\n'))
  126.                 {
  127.                   kfree(*cp);
  128.                   continue;
  129.                 }
  130.             }
  131.         }
  132.       else
  133.         break;
  134.  
  135.       cp++;
  136.     }
  137.  
  138.   *cp = 0;
  139.   syscall (SYS_closedir, dp);
  140.   return env;
  141. }
  142.  
  143. static char **__get_environ (void)
  144. {
  145.   static char *endmarker = 0;
  146.   char **env = &endmarker;
  147.   int num_env, num_local = 0;
  148.   char **cp, **tmp;
  149.   struct Message *msg;
  150.   struct MsgPort *port;
  151.  
  152.   /* 2.0 local environment overrides 1.3 global environment */
  153.   struct Process *me = (struct Process *)FindTask (0);
  154.   struct LocalVar *lv, *nlv;
  155.  
  156.   /* count total number of local variables (skip aliases) */
  157.   for (num_local = 0, lv = (struct LocalVar *)me->pr_LocalVars.mlh_Head;
  158.        (nlv = (struct LocalVar *)lv->lv_Node.ln_Succ);
  159.        lv = nlv)
  160.     if (lv->lv_Node.ln_Type == LV_VAR)
  161.       num_local++;
  162.  
  163.   if ((cp = (char **) syscall (SYS_malloc, (num_local + 1) * 4)))
  164.     {
  165.       env = cp;
  166.  
  167.       for (lv = (struct LocalVar *)me->pr_LocalVars.mlh_Head;
  168.        (nlv = (struct LocalVar *)lv->lv_Node.ln_Succ);
  169.        lv = nlv)
  170.     {
  171.       /* I'm not interested in aliases, really not ;-)) */
  172.       if (lv->lv_Node.ln_Type != LV_VAR)
  173.         continue;
  174.         
  175.       /* NAME=CONTENTS\0 */
  176.       *cp = (char *)syscall(SYS_malloc, strlen(lv->lv_Node.ln_Name) 
  177.                            + 1 + lv->lv_Len + 1);
  178.       if (*cp)
  179.         sprintf (*cp, "%s=%*.*s", lv->lv_Node.ln_Name, 
  180.           (int)lv->lv_Len, (int)lv->lv_Len, lv->lv_Value);
  181.       else
  182.         break;
  183.       cp++;
  184.     }
  185.     *cp = NULL;
  186.     }
  187.   else
  188.     return env;
  189.  
  190.   if (ix.ix_flags & ix_ignore_global_env)
  191.     return env;
  192.  
  193.   port = ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port;
  194.   if (port == NULL)
  195.     {
  196.       if ((port = CreatePort(NULL, 0)))
  197.         {
  198.           ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port = port;
  199.           port->mp_Flags = PA_IGNORE;
  200.           ix.ix_notify_request.nr_Name = "ENV:";
  201.           ix.ix_notify_request.nr_Flags = NRF_SEND_MESSAGE;
  202.           if (!StartNotify(&ix.ix_notify_request))
  203.             {
  204.               DeletePort(port);
  205.               ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port = NULL;
  206.               return env;
  207.             }
  208.         }
  209.       else
  210.         return env;
  211.     }
  212.   if (ix.ix_global_environment == NULL)
  213.     ix.ix_global_environment = get_global_environment();
  214.   else if ((msg = GetMsg(port)))
  215.     {
  216.       do
  217.       {
  218.         ReplyMsg(msg);
  219.       } while ((msg = GetMsg(port)));
  220.  
  221.       /* free the old environment */
  222.       for (tmp = ix.ix_global_environment; *tmp; kfree(*tmp++)) ;
  223.       kfree(ix.ix_global_environment);
  224.  
  225.       ix.ix_global_environment = get_global_environment();
  226.     }
  227.  
  228.   if (ix.ix_global_environment == NULL)
  229.     return env;
  230.  
  231.   for (num_env = 0, tmp = ix.ix_global_environment; *tmp; tmp++, num_env++);
  232.  
  233.   tmp = (char **)syscall (SYS_realloc, env, (num_local + num_env + 1) * 4);
  234.   if (tmp == NULL)
  235.     return env;
  236.   env = tmp;
  237.   cp = &env[num_local];
  238.  
  239.   for (tmp = ix.ix_global_environment; *tmp; tmp++)
  240.     {
  241.       char *p = strchr(*tmp, '='), *f;
  242.       int offset;
  243.       
  244.       *p = 0;
  245.       f = _findenv(env, *tmp, &offset);
  246.       *p = '=';
  247.       if (f)
  248.         continue;
  249.       *cp++ = (char *)syscall(SYS_strdup, *tmp);
  250.       *cp = NULL;
  251.     }
  252.   return env;
  253. }
  254.  
  255. /* smells abit kludgy I know.. but can live with quite few variables in
  256.  * the user area 
  257.  */
  258.  
  259. int
  260. _main (union { char *_aline; struct WBStartup *_wb_msg; } a1,
  261.        union { int   _alen;  char *_def_window;         } a2,
  262.        int (*main)(int, char **, char **))
  263. #define aline           a1._aline
  264. #define alen            a2._alen
  265. #define wb_msg          a1._wb_msg
  266. #define def_window      a2._def_window
  267. {
  268.   struct Process        *me             = (struct Process *)SysBase->ThisTask;
  269.   char                  **argv, **env;
  270.   int                   argc;
  271.   int            exitcode;
  272.  
  273.   KPRINTF (("entered __main()\n"));
  274.   if (! me->pr_CLI)
  275.     {
  276.       /* Workbench programs expect to have their CD where the executed
  277.        * program lives. */
  278.       if (wb_msg->sm_ArgList)
  279.     {
  280.       CurrentDir (wb_msg->sm_ArgList->wa_Lock);
  281.       syscall (SYS__wb_parse, me, wb_msg, def_window);
  282.     }
  283.       /* argc==0: this means, that argv is really a WBenchMsg, not a vector */
  284.       argc = 0;
  285.       argv = (char **) wb_msg;
  286.     }
  287.   else
  288.     {
  289.       /* if we were started from the CLI, alen & aline are valid and
  290.        * should now be split into arguments. This is done by the
  291.        * function "_cli_parse()", which does wildcard expansion if not
  292.        * disabled (see cli_parse.c). */
  293.       _cli_parse (me, alen, aline, &argc, &argv);
  294.       if (is_ixconfig(argv[0]))
  295.         return 10;
  296.     }
  297.  
  298.   env = __get_environ ();
  299.  
  300.   /* this is not really the right thing to do, the user should call
  301.      ix_get_vars2 () to initialize environ to the address of the variable
  302.      in the calling program. However, this setting guarantees that 
  303.      the user area entry is valid for getenv() calls. */
  304.   u.u_environ = &env;
  305.  
  306.   ix_install_sigwinch ();
  307.   
  308.   /* The finishing touch :-) Not really necessary, though. */
  309.   errno = 0;
  310.  
  311.   exitcode = main (argc, argv, env);
  312.  
  313.   syscall(SYS_exit,exitcode);
  314.   return 0;
  315. }
  316.