home *** CD-ROM | disk | FTP | other *** search
- head 1.5;
- access;
- symbols
- version39-41:1.3;
- locks;
- comment @ * @;
-
-
- 1.5
- date 92.09.14.01.38.35; author mwild; state Exp;
- branches;
- next 1.4;
-
- 1.4
- date 92.08.09.20.37.07; author amiga; state Exp;
- branches;
- next 1.3;
-
- 1.3
- date 92.07.04.19.02.39; author mwild; state Exp;
- branches;
- next 1.2;
-
- 1.2
- date 92.05.22.01.45.00; author mwild; state Exp;
- branches;
- next 1.1;
-
- 1.1
- date 92.05.14.19.55.40; author mwild; state Exp;
- branches;
- next ;
-
-
- desc
- @load segment, consider resident list, do interpreter expansion
- @
-
-
- 1.5
- log
- @fix a bug with #! expansion (forgot separating /)
- @
- 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: __load_seg.c,v 1.4 1992/08/09 20:37:07 amiga Exp $
- *
- * $Log: __load_seg.c,v $
- * Revision 1.4 1992/08/09 20:37:07 amiga
- * change to use 2.x header files by default
- *
- * Revision 1.3 1992/07/04 19:02:39 mwild
- * fix typo, the buffer for interpreter-expansion was ways too small...
- *
- * Revision 1.2 1992/05/22 01:45:00 mwild
- * rewrote interpreter expansion, `should' now work as expected
- *
- * Revision 1.1 1992/05/14 19:55:40 mwild
- * Initial revision
- *
- */
-
- #define KERNEL
- #include "ixemul.h"
- #include <ctype.h>
- #include <string.h>
-
- #ifdef DEBUG
- #define DP(a) kprintf a
- #else
- #define DP(a)
- #endif
-
- #if __GNUC__ != 2
- #define alloca __builtin_alloca
- #endif
-
- /* until sksh is fixed... */
- #define BIG_KLUDGE
-
- extern int _dos20;
-
- /* 2.0 support */
- #include <utility/tagitem.h>
- #include <dos/dostags.h>
-
- extern void *kmalloc (size_t size);
-
- struct my_seg {
- BPTR segment; /* the thing our clients can use */
- enum { LOADSEG, RESSEG } type;
- u_int priv; /* information depending on type */
- };
-
-
- static struct my_seg *try_load_seg (BPTR lock, char *name, char **args);
-
-
- static inline struct my_seg *
- check_resident (char *tmp)
- {
- struct my_seg *res = 0;
- struct Segment *seg = 0;
-
- if (_dos20)
- {
- /* big problem: Commo only stores the bare names in the resident
- list. So we have to truncate to the filename part, and so lose
- the ability to explicitly load the disk version even if a
- resident version is installed */
-
- char *cp = rindex (tmp, '/');
- if (cp)
- tmp = cp + 1;
- else if (cp = index (tmp, ':'))
- tmp = cp + 1;
-
- Forbid ();
- seg = FindSegment (tmp, 0, 0);
- if (seg)
- {
- /* strange they didn't provide a function for this... */
- if (seg->seg_UC >= 0)
- seg->seg_UC++;
- }
- Permit ();
- }
-
- if (seg && (res = (struct my_seg *) kmalloc (sizeof (*res))))
- {
- res->segment = seg->seg_Seg;
- res->type = RESSEG;
- res->priv = (u_int) seg;
- }
- else if (seg)
- {
- Forbid ();
- if (seg->seg_UC > 0)
- seg->seg_UC--;
- Permit ();
- }
-
- return res;
- }
-
-
- static inline struct my_seg *
- check_loadseg (char *tmp)
- {
- struct my_seg *res = 0;
- BPTR seg;
-
- seg = LoadSeg (tmp);
- if (seg && (res = kmalloc (sizeof (*res))))
- {
- res->segment = seg;
- res->type = LOADSEG;
- res->priv = seg;
- }
- else if (seg)
- UnLoadSeg (seg);
-
- return res;
- }
-
-
- void
- __free_seg (BPTR *seg)
- {
- struct my_seg *ms;
-
- ms = (struct my_seg *) seg;
-
- if (ms->type == RESSEG)
- {
- struct Segment *s = (struct Segment *) ms->priv;
-
- Forbid ();
- if (s->seg_UC > 0)
- s->seg_UC--;
- Permit ();
- }
- else
- UnLoadSeg (ms->priv);
-
- kfree (ms);
- }
-
-
- /*
- * This function does what LoadSeg() does, and a little bit more ;-)
- * Besides walking the PATH of the user, we try to do interpreter expansion as
- * well. But, well, we do it a little bit different then a usual Amiga-shell.
- * We check the magic cookies `#!' and `;!', and if found, run the interpreter
- * specified on this first line of text. This does *not* depend on any script
- * bit set!
- * If this check is negative, the script bit is tested. If set, the special
- * BPTR (-2) is returned, this is the hint to ssystem() to go and invoke
- * system() with the command line. In this case *NO* interpreter expansion
- * takes place, as the expansion must have already failed before.
- */
-
- /*
- * IMPORTANT: only call this function with all signals masked!!!
- */
-
- /*
- * name: the name of the command to load. Can be relative to installed PATH
- * args: if set, a string to the first part of an expanded command is stored
- */
-
- BPTR *
- __load_seg (char *name, char **args)
- {
- BPTR lock, parent_lock;
- struct my_seg *seg;
- char *base_name;
-
- /* perhaps the name is vanilla enough, so that even LoadSeg() groks it? */
- if (args) *args = 0;
-
- seg = check_resident (name);
-
- if (! seg)
- seg = check_loadseg (name);
-
- if (seg)
- return &seg->segment;
-
- /* try to lock the file (using __lock() provides full path-parsing ;-)) */
-
- lock = __lock (name, ACCESS_READ);
- if (lock)
- {
- /* this is tricky.. it is legal to CurrentDir() to a file. This is what
- * we do here, we try to LoadSeg("") afterwards ;-)) */
- seg = try_load_seg (lock, "", args);
-
- __unlock (lock);
- }
-
- /* now we may have a valid segment */
- if (seg)
- return &seg->segment;
-
- /* if the command was specified with some kind of path, for example with a
- * device or a directory in it, we don't run it thru the PATH expander
- */
- if (strpbrk (name, ":/"))
- return 0;
-
- /* so the command is not directly addressable, but perhaps it's in our PATH? */
- {
- struct Process *me = (struct Process *)((*(struct ExecBase **)4)->ThisTask);
- struct CommandLineInterface *cli;
-
- /* but we need a valid CLI then */
- if (cli = BTOCPTR (me->pr_CLI))
- {
- struct path_element {
- BPTR next;
- BPTR lock;
- } *lock_list;
-
- for (lock_list = BTOCPTR (cli->cli_CommandDir);
- lock_list;
- lock_list = BTOCPTR (lock_list->next))
- {
- #if 0
- DP(("__load_seg: trying PATH component: next = $%lx, lock = $%lx\n",
- lock_list->next, lock_list->lock));
- #endif
-
- if (seg = try_load_seg (lock_list->lock, name, args))
- break;
- }
- }
- }
-
- if (seg)
- return &seg->segment;
-
- errno = ENOENT;
- return 0;
- }
-
- static struct my_seg *
- try_load_seg (BPTR lock, char *name, char **args)
- {
- BPTR ocd;
- struct my_seg *seg;
-
- if (args) *args = 0;
-
- ocd = CurrentDir (lock);
-
- seg = check_loadseg (name);
-
- /* try to do interpreter - expansion, but only if args is non-zero */
- if (! seg && args)
- {
- int fd;
- char magic[2];
- struct stat stb;
-
- if (syscall (SYS_stat, name, &stb) == 0 && S_ISREG (stb.st_mode))
- {
- if ((fd = syscall (SYS_open, name, 0)) >= 0)
- {
- if (syscall (SYS_read, fd, magic, 2) == 2 &&
- (((magic[0] == '#' || magic[0] == ';') && magic[1] == '!')
- #ifdef BIG_KLUDGE
- /* I can't currently use #! expansion with sksh, since the shell
- * does the same expansion again, and then doesn't seem to get
- * it right anymore... this is the so far unused hidden bit,
- * set it with PROTECT +h
- */
- || (stb.st_amode & (1 << 7))
- #endif
- ))
- {
- char interp[MAXPATHLEN + 1];
- int n;
-
- if ((n = syscall (SYS_read, fd, interp, MAXINTERP)) > 0)
- {
- char *cp, *colon, ch;
- char *interp_path;
-
- #ifdef BIG_KLUDGE
- if (stb.st_amode & (1<<7))
- {
- strcpy (interp, "sksh -c");
- n = strlen (interp);
- }
- #endif
-
- /* oky.. got one.. terminate with 0 and try to find end of it */
- interp[n] = 0;
- for (cp = interp; cp < interp + n; cp++)
- if (*cp == 0 || isspace (*cp)) break;
- ch = *cp;
- *cp = 0;
-
- /* okay, lets try to load this instead. Call us recursively,
- * but leave out the argument-argument, so we can't get
- * into infinite recursion. Interpreter-Expansion is only
- * done the first time __load_seg() is called from
- * ssystem()
- */
- seg = (struct my_seg *) __load_seg (interp, 0);
- *cp = ch;
- if (! seg)
- goto ret;
-
- /* in this case, set the argument as well.
- */
-
- /* first skip intergap whitespace */
- for (;cp < interp + n; cp++)
- if (!*cp || ! isspace (*cp) || *cp == '\n')
- break;
-
- if (*cp && *cp != '\n')
- {
- /* we read a certain amount of bytes, but we
- * unconditionally stop when we hit newline
- */
- interp_path = cp;
-
- /* crop any further arguments, only ONE argument
- * is supported
- */
- for (;cp < interp + n; cp++)
- if (isspace (*cp))
- break;
- if (cp < interp + n)
- *cp = 0;
-
- *cp++ = ' ';
- }
- else
- cp = interp_path = interp;
- #ifdef BIG_KLUDGE
- if (stb.st_amode & (1<<7))
- {
- *cp++ = '\"';
- }
- #endif
- if (ix.ix_translate_slash && name[0] != '/')
- *cp++ = '/';
-
- if (name[0] != '/' && !index (name, ':'))
- {
- if (NameFromLock (lock, cp,
- MAXPATHLEN-(cp-interp)) == -1)
- strcat (strcat (cp, "/"), name);
- else
- strcpy (cp, name);
- }
- else
- strcpy (cp, name);
-
- if (ix.ix_translate_slash && (colon = index (cp, ':')))
- *colon = '/';
-
- *args = syscall (SYS_strdup, interp_path);
- #ifdef BIG_KLUDGE
- if (stb.st_amode & (1<<7))
- {
- /* tell ssystem() that it should add the closing
- * quote... shudder.. I want a newer sksh !
- */
- *args = (char *)(-(int)*args);
- }
- #endif
- }
- }
- syscall (SYS_close, fd);
- }
-
- ret:
- /* check to see if script bit is set, no matter whether we could
- * actually open the file or not. If set, set seg to magic BPTR */
- if (! seg && (stb.st_amode & FIBF_SCRIPT))
- seg = (struct my_seg *) -2;
- }
- }
-
- CurrentDir (ocd);
-
- return seg;
- }
- @
-
-
- 1.4
- log
- @change to use 2.x header files by default
- @
- text
- @d19 1
- a19 1
- * $Id: __load_seg.c,v 1.3 1992/07/04 19:02:39 mwild Exp $
- d22 3
- d370 1
- a370 1
- strcat (cp, name);
- @
-
-
- 1.3
- log
- @fix typo, the buffer for interpreter-expansion was ways too small...
- @
- text
- @d19 1
- a19 1
- * $Id: __load_seg.c,v 1.2 1992/05/22 01:45:00 mwild Exp $
- d22 3
- d54 2
- a55 58
- #include "gcc:include20/utility/tagitem.h"
- #include "gcc:include20/dos/dostags.h"
- #define BASE_EXT_DECL
- #define BASE_PAR_DECL
- #define BASE_PAR_DECL0
- #define BASE_NAME ix.ix_dos_base
- __inline static LONG NameFromLock(BASE_PAR_DECL BPTR lock, UBYTE* buffer, long int len)
- {
- BASE_EXT_DECL
- register LONG res __asm("d0");
- register void *a6 __asm ("a6");
- register BPTR d1 __asm("d1");
- register UBYTE* d2 __asm("d2");
- register long int d3 __asm("d3");
-
- a6 = BASE_NAME;
- d1 = lock;
- d2 = buffer;
- d3 = len;
- __asm volatile ("
- jsr a6@@(-0x192)"
- : "=r" (res)
- : "r" (a6), "r" (d1), "r" (d2), "r" (d3)
- : "d0", "d1", "a0", "a1", "d2", "d3");
- *(u_char *)d2=*(u_char *)d2;
- return res;
- }
- #ifndef CMD_SYSTEM
- #define CMD_SYSTEM -1
- #define CMD_INTERNAL -2
-
- struct Segment {
- BPTR seg_Next;
- LONG seg_UC;
- BPTR seg_Seg;
- UBYTE seg_Name[4]; /* actually the first 4 chars of BSTR name */
- };
- #endif
- __inline static struct Segment* FindSegment(BASE_PAR_DECL UBYTE* name, struct Segment* seg, long int system)
- {
- BASE_EXT_DECL
- register struct Segment* res __asm("d0");
- register void *a6 __asm ("a6");
- register UBYTE* d1 __asm("d1");
- register struct Segment* d2 __asm("d2");
- register long int d3 __asm("d3");
-
- a6 = BASE_NAME;
- d1 = name;
- d2 = seg;
- d3 = system;
- __asm volatile ("
- jsr a6@@(-0x30c)"
- : "=r" (res)
- : "r" (a6), "r" (d1), "r" (d2), "r" (d3)
- : "d0", "d1", "a0", "a1", "d2", "d3");
- return res;
- }
- @
-
-
- 1.2
- log
- @rewrote interpreter expansion, `should' now work as expected
- @
- text
- @d19 1
- a19 1
- * $Id: __load_seg.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
- d22 3
- d345 1
- a345 1
- char interp[MAXINTERP + 1];
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d19 1
- a19 1
- * $Id$
- d21 4
- a24 1
- * $Log$
- d300 5
- a304 1
- return &seg->segment;
- d347 2
- a348 1
- char *cp;
- d360 1
- a360 1
- for (cp = interp; cp < interp+n; cp++)
- d362 2
- a363 1
- *cp++ = 0;
- d372 3
- d376 2
- a377 4
- if (seg)
- {
- char *interp_path;
- int len;
- d379 4
- a382 4
- /* in this case, set the argument as well.
- */
- for (;cp < interp+n; cp++)
- if (! isspace (*cp) || *cp == '\n') break;
- d384 2
- d389 1
- a389 2
- if (*cp == '\n')
- n = cp - interp;
- a390 3
- if (cp < interp+n)
- *args = cp;
-
- d394 1
- a394 1
- for (;cp < interp+n; cp++)
- d397 1
- a397 1
- if (cp < interp+n)
- d400 4
- a403 26
- /* okay, now get a reasonably long buffer for the
- * system to convert our lock into a path-name
- */
- if (! strpbrk (name, ":/"))
- {
- interp_path = alloca (MAXPATHLEN);
- if (NameFromLock (lock, interp_path, MAXPATHLEN) == -1)
- len = strlen (interp_path);
- else
- len = 0;
- }
- else
- len = 0;
-
- /* now build the argument string */
- if (! *args) *args = "";
- cp = (char *)syscall (SYS_malloc, len + 1 +
- strlen (name) + 1
- + strlen (*args) + 2);
- *cp = 0;
- if (**args)
- {
- strcat (cp, *args);
- strcat (cp, " ");
- }
-
- d405 4
- a408 2
- if (stb.st_amode & (1<<7))
- strcat (cp, "\"");
- d410 13
- d424 2
- a425 7
- if (len)
- {
- strcat (cp, interp_path);
- if (! index (":/", cp[strlen (cp) - 1]) && *name)
- strcat (cp, "/");
- }
- strcat (cp, name);
- d427 1
- a427 1
- *args = cp;
- d429 7
- a435 7
- if (stb.st_amode & (1<<7))
- {
- /* tell ssystem() that it should add the closing
- * quote... shudder.. I want a newer sksh !
- */
- *args = (char *)(-(int)cp);
- }
- a436 1
- }
- d442 1
- d449 1
- a449 1
-
- @
-