/*******************************************************************
Le-Lisp (r) version 15.22
Bibliothe`que d'Exe'cution en C
utilisable sur syste`me d`exploitation "a` la UN*X"
*****************************************************************
(r) Le-Lisp est une marque de'pose'e de l'INRIA
*****************************************************************
Ce fichier est en lecture seule. Il est maintenu par :
ILOG S.A.
2 Avenue Gallie'ni
BP 85
94253 Gentilly Cedex
*****************************************************************
$Header: lelisp.c,v 4.43 89/01/16 19:53:14 kuczynsk Exp $
*******************************************************************/
/* Liste des conditionnelles de compilation C :
============================================
Les types et sous-types de syste`mes UNIX :
S5 : System V
SPS9 : sous-type Ridge SPS9
SPS7 : sous-type SPS7 SMX 5.1
CADMUS : sous-type Cadmus
HP9300 : sous-type HP9000 se'rie 300
LEWS : enleve les ← devant les defextern
UNIGRAPH : enleve les ← devant les defextern
IBMRT :
BSD4x : Syste`me Berkeley
BSD41 : de type 4.1
BSD42 : de type 4.2
SEQUENT : sous-type Sequent DYNIX
Les traits pre'sents :
FOREIGN : les messages sont en Breton!
PAGESIZE: La taille des pages
EXECORE : L'image me'moire est un exe'cutable (a.out)
Les autres options fournies a` la compilation C
NBSYST : nume'ro du syste`me a` cre'er
FILEINI : nom du fichier startup
FILIT : indicateur de fichier initial
LLBAN : indicateur de pre'sence de bannie`re
PAGESIZE : la taille d'une page me'moire
TIMEUNIT : fre'quence de l'horloge.
LELISPDIR : repertoire du systeme lelisp
*/
/* Choix du numero du systeme :
----------------------------
1 = VERSADOS, 2 = VME, 3 = MicroMega, 4 = APOLLO
5 = SM90, 6 = PE32OS, 7 = PE32UNIX, 8 = VAXUNIX
9 = VAXVMS, 10= multics, 11= METHEUS, 12= UNIVERSE68
13= MCPM86, 14= PCDOS, 15= MACII, 16= VAXIS3,
17= MAC, 18= SPS9, 19= BELLMAC, 20= VM370UTS,
21= PCS, 22= SUN, 23= HP9000-300, 24= METAVISEUR,
25= GOULD, 26= IBMRT, 27= PYRAMID, 28= SEQUENT
29= UNIGRAPH, 30= CL1000, 31= CL1020, 32= TEKTRONIX 43xx,
33= C, 34= DPX1000, 35= SUN4 36= ATARI,
37= CONVEX.
*/
#ifndef NBSYST
#define NBSYST 22
#endif NBSYST
/* Les autres parametres dependants du systeme
------------------------------------------- */
#ifndef FILEINI
#define FILEINI "/usr/ilog/lelisp/llib/startup.ll"
#endif FILEINI
#define FILIT 0 /* 0 = fichier initial, 1 = core */
#define LLBAN 0 /* 0 = banniere, 1 = silence */
/* la taille des pages (obtenu par pagesize(1) ou getpagesize(2) ou
par la documentation). Doit etre une puissance de 2 >= BIPTR */
#ifndef PAGESIZE
#define PAGESIZE 1024
#endif PAGESIZE
#define align(x) (x = ((x+PAGESIZE-1)&~(PAGESIZE-1)))
/* Les tailles des zones (attention aux Unite's!)
--------------------------------------------- */
/* Les Unites avec lesquelles sont definies les zones */
#define PTR (sizeof (char *))
#define BIPTR (PTR*2)
#define KPTR (PTR*1024)
int SSTACK = 6; /* en K objets de type pointeurs */
int SCODE = 128; /* en K octets */
int SHEAP = 70; /* en K octets */
int SNUMB = 0; /* en K objets de type entiers */
int SFLOAT = 1; /* en K objets de type flottant */
int SVECT = 1; /* en K objets de type vecteur */
int SSTRG = 3; /* en K objets de type chaine */
int SSYMB = 2; /* en K objets de type symboles */
int SCONS = 3; /* en 8 K CONS */
int UCONS = 0; /* en 32 CONS */
/* Si en mode debug, on n'arme pas les interruptions et on ne fait pas
de stty. Principalement pour adb. */
int lldebug=0;
/* les include */
#include <sys/types.h> /* pour tout le monde */
#include <sys/stat.h> /* pour tout le monde */
#include <signal.h> /* pour les signaux */
#include <stdio.h> /* pour les entre'es sorties */
#include <errno.h> /* pour perror(), et le save-core BSD */
#include <a.out.h> /* pour getglobal, et le save-core BSD */
/* V-- cf page 3-218 AIX o/s guide */
#if IBMRT || LEWS || UNIGRAPH
#undef n←name
#endif /* IBMRT LEWS UNIGRAPH */
#ifdef LEWS
/* Les bibliotheques du LEWS exploitent ces traits */
#define u3b 0
#define vax 0
#define u3b5 0
#define sm90 1 /* pour nlist (dans a.out.h) */
#define ridge 0
#endif LEWS
#ifdef BSD42 /* pour runtime */
#include <sys/time.h>
#include <sys/resource.h>
#else BSD42
#include <time.h>
#ifdef Perkin /* le Perkin n'a pas l'include sys/times.h */
struct tms {
long tms←utime;
long proc←system←time;
long child←user←time;
long child←system←time;
};
#else Perkin
#include <sys/times.h> /* pour les autres */
#endif Perkin
#endif BSD42
#ifdef VAXUNIX
#define N←DATADDR(gg) gg.a←text
#endif VAXUNIX
/* les point d'entree de Le-Lisp LLM3 */
extern host←start(), llstdio();
extern float accusingle1;
/*
Les variables globales Le-Lisp.
Elles sont toutes definies dans LLINIT.LLM3
mais doivent etre chargees ici.
*/
/* la pile d'evaluation de Le-Lisp */
extern char *bstack, *estack, *mstack1, *mstack2;
/* les limites des zones des differents types Le-Lisp */
extern char *bcode, *ccode, *ecode,
*bheap, *cheap, *eheap,
*bnumb, *cnumb,
*bfloat, *cfloat,
*bvect, *cvect,
*bstrg, *cstrg,
*bsymb, *csymb,
*bcons, *ccons, *econs;
char *llucode, *lluheap; /* fin des zones code et heap (trous) */
/* le fichier initial et la ligne de commande */
extern int filiz, filit;
extern char *filin;
extern int llban;
/* le numero (type) du systeme Le-Lisp */
extern int nbsyst;
/* Le flag controlant l'impression des erreurs syste`me */
extern int **prtmsgs; /* il est dans le save-core ! */
#define errreturn(M,V) { if(**prtmsgs != 0) perror(M) ; return(V); }
/*
Les variables du lanceur
Elles ne sont pas sauve'es par save-core
*/
/* tailles des zones */
int sstack, scode, sheap, snumb, sfloat, svect, sstrg, ssymb, scons;
/* bits invisibles */
int stbin;
char *btbin;
/* bits du GC */
int stbgc;
char *btbgc;
/* debut et fin de la memoire */
char *bmem;
char *emem;
#ifdef EXECORE
/* Environnement Shell initial (pour le restore-core BSD) */
char **envpini;
#endif EXECORE
/* Path absolu du repertoire lelisp */
char *lelisp←racine;
/* Path absolu du binaire lelispbin */
char lelispbin[256];
char *getenv();
/* les variables et fonctions du cload */
char *mktemp();
char template[] = "/tmp/lelisp←XXXXXX";
/*
Points d'entree
*/
/* Pour les erreurs */
int out(), oupps();
char *usage();
/*
References externes
*/
/* Allocation de la me'moire */
extern char *brk();
extern char *sbrk();
#define RATE (char *) -1
char *END;
/********************************************************
Gestion du Terminal
********************************************************/
#ifdef S5
#include <fcntl.h>
#include <termio.h>
#endif S5
#ifdef BSD4x
#include <sgtty.h>
#endif BSD4x
#ifdef S5
struct termio tioini, tiolisp; /* les termio initiaux et lisp */
#endif S5
#ifdef BSD4x
struct sgttyb ttyini, ttylisp; /* les stty initiaux et lisp */
#endif BSD4x
int realterminal = 0; /* =0 c'est un vrai terminal */
extern init←stty();
extern lisp←stty();
extern unix←stty();
/* init←stty: intialise les structures stty initiales
-------------------------------------------------- */
init←stty () {
realterminal = isatty(0); /* est-on interactif ? */
if (realterminal != 0) {
#ifdef S5
(void) ioctl(0, TCGETA, &tioini); /* prend le tty initial */
(void) ioctl(0, TCGETA, &tiolisp);
tiolisp.c←cc[VMIN] = 6;
tiolisp.c←cc[VTIME] = 1;
tiolisp.c←iflag &= ~(IGNBRK|INLCR|ICRNL);
tiolisp.c←iflag |= BRKINT;
tiolisp.c←oflag &= ~(OPOST|ONLCR|OCRNL|ONOCR|ONLRET);
tiolisp.c←lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
tiolisp.c←lflag |= ISIG;
(void) ioctl(0, TCSETAF, &tiolisp); /* mets le tty lisp */
#endif S5
#ifdef BSD4x
(void) gtty(0, &ttyini); /* prend le tty initial */
(void) gtty(0, &ttylisp); /* recopie' dans le tty lisp */
ttylisp.sg←flags |= CBREAK; /* Lisp est en cbreak -echo -nl */
ttylisp.sg←flags &= ~(ECHO|CRMOD);
#endif BSD4x
}
}
/* lisp←stty: passe le terminal en mode Le-Lisp
-------------------------------------------- */
lisp←stty () {
if (realterminal != 0)
#ifdef S5
(void) ioctl(0, TCSETAF, &tiolisp);
#endif S5
#ifdef BSD4x
(void) stty(0, &ttylisp);
#endif BSD4x
}
/* unix←stty: passe le terminal en mode UN*X
----------------------------------------- */
unix←stty () {
if (realterminal != 0)
#ifdef S5
(void) ioctl(0, TCSETAF, &tioini);
#endif S5
#ifdef BSD4x
(void) stty(0, &ttyini);
#endif BSD4x
}
/********************************************************
Gestion de la Signalerie UN*X
********************************************************/
extern ll←break(); /* dans ../<system>/ll<system>.llm3 */
extern ll←merro();
extern ll←clock();
#ifdef BSD41
onstop41(signo) /* gestion du "stopped job" ↑Z sous BSD 4.1 */
int signo;
{
unix←stty();
sigset(signo, SIG←DFL);
kill(0, signo);
sigset(signo, onstop41);
}
oncont41(signo) /* repasse en Lisp */
int signo;
{
lisp←stty();
}
#endif BSD41
#ifdef BSD42
onstop42(signo) /* gestion du "stopped job" ↑Z sous BSD 4.2 */
int signo;
{
unix←stty();
signal(SIGTSTP, SIG←DFL);
killpg(getpgrp(0), signo);
}
oncont42(signo) /* repasse en mode Lisp */
int signo;
{
lisp←stty();
signal(SIGTSTP, onstop42);
}
shstop42(signo) /* pendant un COMLINE */
int signo;
{
signal(SIGTSTP, SIG←DFL);
killpg(getpgrp(0), signo);
}
shcont42(signo) /* pendant un COMLINE */
int signo;
{
signal(SIGTSTP, shstop42);
}
#endif BSD42
/* init←signal: intialise les signaux UN*X ge're's par Le-Lisp
----------------------------------------------------------- */
init←signal() {
int i;
if ( lldebug == 0 ) {
for(i = 3 ; i <= 12; signal(i++, oupps));
#ifdef BSD41
sigset(SIGTSTP, onstop41);
sigset(SIGCONT, oncont41);
#endif BSD41
#ifdef BSD42
signal(SIGTSTP, onstop42);
signal(SIGCONT, oncont42);
#endif BSD42
}
}
/* pour e'viter un "core-dumped" pour les mauvais signaux */
oupps(n) {
#ifdef FOREIGN
fprintf(stderr, "Le-Lisp : I quit on signal %d\r\n", n);
#else FOREIGN
fprintf(stderr, "signal %d\r\n", n);
fprintf(stderr, "OUPPS! J'ai failli faire un core\r\n");
#endif FOREIGN
out(-1);
}
int←ign () {
if (realterminal != 0)
signal(SIGINT, SIG←IGN); /* interrupt */
signal(SIGILL, SIG←IGN); /* illegal instruction */
signal(SIGBUS, SIG←IGN); /* bus error */
signal(SIGSEGV, SIG←IGN); /* segmentation violation */
signal(SIGTRAP, SIG←IGN); /* trace trap */
signal(SIGFPE, SIG←IGN); /* floating point exception */
#ifdef BSD42
signal(SIGTSTP, shstop42); /* stop generated from keyboard */
signal(SIGCONT, shcont42); /* continue after stop */
#endif
};
/* int←std: passe en mode signaux standard pour le COMLINE
------------------------------------------------------- */
int←std() {
if (realterminal != 0)
signal(SIGINT, SIG←DFL); /* interrupt */
signal(SIGILL, SIG←DFL); /* illegal instruction */
signal(SIGBUS, SIG←DFL); /* bus error */
signal(SIGSEGV, SIG←DFL); /* segmentation violation */
signal(SIGTRAP, SIG←DFL); /* trace trap */
signal(SIGFPE, SIG←DFL); /* floating point exception */
#ifdef BSD42
signal(SIGTSTP, SIG←DFL); /* stop generated from keyboard */
signal(SIGCONT, SIG←DFL); /* continue after stop */
#endif
};
/* inton: arme les signaux UN*X qui seront ge're's par Le-Lisp
----------------------------------------------------------- */
inton () {
if ( lldebug == 0 ) {
if (realterminal != 0)
signal(SIGINT, ll←break); /* interrupt */
signal(SIGILL, ll←merro); /* illegal instruction */
signal(SIGBUS, ll←merro); /* bus error */
signal(SIGSEGV, ll←merro); /* segmentation violation */
signal(SIGTRAP, ll←merro); /* trace trap */
signal(SIGFPE, ll←merro); /* floating point exception */
signal(SIGALRM, ll←clock); /* alarm clock */
#ifdef BSD42
signal(SIGTSTP, onstop42);
signal(SIGCONT, oncont42);
sigsetmask(0);
#endif BSD42
#ifdef IBMRT
signal(SIGDANGER, ll←merro); /* impending lack of page space */
#endif IBMRT
}
}
/* intoff: de'sarme les signaux UN*X ge're's par Le-Lisp
----------------------------------------------------- */
/* ?!?!?! ou` est le code S5 ?!?!? */
intoff () {
if ( lldebug == 0 ) {
#ifdef BSD42
#define mask(s) (1 << ((s)-1))
return(sigblock (mask (SIGALRM) | mask(SIGINT)));
#else BSD42
if (realterminal != 0)
signal(SIGINT, SIG←IGN);
#endif BSD42
}
}
/*******************************************
INLELISP (pour ne pas dire MAIN !!)
point d'entree de Le-Lisp
*******************************************/
inlelisp(argc, argv, envp)
int argc; char **argv, **envp; {
int n, size;
int verbose=0;
#ifdef EXECORE
int selfcore = 0;
#endif EXECORE
#ifdef EXECORE
envpini = envp; /* sauvegarde de l'environnement Shell */
#endif EXECORE
init←signal(); /* initialisation des signaux */
filin = FILEINI; /* initialisation des valeurs par defaut */
filit = FILIT;
llban = LLBAN;
nbsyst = NBSYST;
#ifdef HP9300
lelisp←racine = LELISPDIR;
#endif HP9300
/* De'cryptage des arguments
Le premier argument est TOUJOURS le path absolu de lelispbin
L'argument 0 est le path absolu du binaire */
strcpy(lelispbin, argv[0]);
#define suitarg() ((++n >= argc) ? usage() : *(argv+n))
#define checkarg(s) (!strcmp(s,*(argv+n)))
for(n = 1; n < argc; n++){
if((**(argv+n) >= '0') && (**(argv+n) <= '9')) {
SCONS = atoi(*(argv+n)); continue; }
if(**(argv+n) == '-'){
#ifdef EXECORE
if(checkarg("-c")){
selfcore = 1; continue; }
#endif EXECORE
if(checkarg("-s")){
llban = 1; continue; }
if(checkarg("-r")) {
filit = 1; filin = suitarg(); continue; }
if(checkarg("-debug")) {
lldebug = 1; continue; }
if(checkarg("-v")) {
verbose = 1; continue; }
if(checkarg("-stack")) {
SSTACK = atoi(suitarg()); continue; }
if(checkarg("-code")) {
SCODE = atoi(suitarg()); continue; }
if(checkarg("-heap")) {
SHEAP = atoi(suitarg()); continue; }
if(checkarg("-number")) {
SNUMB = atoi(suitarg()); continue; }
if(checkarg("-float")) {
SFLOAT = atoi(suitarg()); continue; }
if(checkarg("-vector")) {
SVECT = atoi(suitarg()); continue; }
if(checkarg("-string")) {
SSTRG = atoi(suitarg()); continue; }
if(checkarg("-symbol")) {
SSYMB = atoi(suitarg()); continue; }
if(checkarg("-cons")) {
SCONS = atoi(suitarg()); continue; }
if(checkarg("-ucons")) {
UCONS = atoi(suitarg()); continue; }
(void) usage();
}
filit = 0; filin = *(argv+n);
}
filiz=strlen(filin);
if( lldebug == 0 )
init←stty(); /* initialisation du terminal */
sstack = SSTACK * KPTR;
scode = SCODE * 1024;
sheap = SHEAP * 1024;
snumb = SNUMB * KPTR;
sfloat = SFLOAT * KPTR * 2;
svect = SVECT * KPTR * 2;
sstrg = SSTRG * KPTR * 2;
ssymb = SSYMB * KPTR * 8; /* symbole = 8 pointeurs */
scons = SCONS * KPTR * 16; /* c'est en 8K CONS */
scons += UCONS * PTR * 64; /* c'est en paquet de 32 CONS*/
/*
Verifications des arguments.
Les zones FLOAT (flottants 31 bits) et NUMB (Toutes machines)
peuvent e↑tre demande'es vides
*/
align(snumb);
align(sfloat);
align(scode);
#define nozero(zone, nom) if(zone == 0) zonevide(nom)
nozero(sstack,"stack"); align(sstack);
nozero(sheap,"heap"); align(sheap);
nozero(svect,"vector"); align(svect);
nozero(sstrg,"string"); align(sstrg);
nozero(ssymb,"symbol"); align(ssymb);
nozero(scons,"cons"); align(scons);
/*
Calcul de la taille de la me'moire
*/
stbin = scons / 64; /* taille de la table des bits invisibles */
align(stbin);
stbgc = (snumb+sfloat+svect+sstrg+ssymb+scons)/64; /* bits GC */
align(stbgc);
/* en 2 coups a cause des limites de certains compilos C */
size = sstack+scode+sheap+svect;
size = size+snumb+sfloat+sstrg+ssymb+scons+stbin+stbgc;
if ( verbose )
{printf("FILIT %3d\r\n", filit);
printf("FILIN %s\r\n", filin);
printf("Tailles des zones me'moires (octets)\r\n");
printf("pile %8d\r\n", sstack);
printf("code %8d\r\n", scode);
printf("tas %8d\r\n", sheap);
printf("nombres %8d\r\n", snumb);
printf("flottants %8d\r\n", sfloat);
printf("vecteurs %8d\r\n", svect);
printf("strings %8d\r\n", sstrg);
printf("symboles %8d\r\n", ssymb);
printf("cons %8d\r\n", scons);
printf("bits invisibles %8d\r\n", stbin);
printf("bits de marquage %8d\r\n", stbgc);
printf(" total %8d\r\n", size);
}
#ifdef EXECORE
if(selfcore == 1){
corinit(); /* restauration turbo */
out(-1); /* au cas ou on rentrerait */
}
#endif EXECORE
if (filiz) {
if (close(open(filin, 0)) != 0){
#ifdef FOREIGN
fprintf(stderr, "Le-Lisp : cannot find file %s\r\n", filin);
#else FOREIGN
fprintf(stderr, "Le-Lisp : je ne trouve pas le fichier %s\r\n",
filin);
#endif FOREIGN
out(-1);
}
#ifdef EXECORE
if (filit == 1) {
int dummy;
int *pdummy;
dummy = 1;
pdummy = &dummy;
prtmsgs = &pdummy; /* **prtmsgs existe */
corest(filin);
out(-1);
}
#endif EXECORE
}
/*
Allocation de la me'moire
*/
/* Pour pre'allouer ce qu'il faut pour un GETGLOBAL et e'viter
que le MALLOC n'aille prendre de la place n'importe ou` */
#ifdef BSD4x
(void) getgloba("start");
#endif BSD4x
bmem = sbrk(0);
bmem = (char *) (((long)bmem+PAGESIZE-1)&~(PAGESIZE-1));
(void) brk(bmem);
bmem = sbrk(size);
if(bmem == RATE){
#ifdef FOREIGN
fprintf(stderr, "Le-Lisp : I can't get required memory space\r\n");
#else FOREIGN
fprintf(stderr,
"Le-Lisp : Impossible d'allouer tant de memoire\r\n");
#endif FOREIGN
out(-1);
}
END = sbrk(0); /* pour voir si malloc prend de la place */
/* chargement des variables pre'de'finies */
estack = bmem + (4 * PTR); /* tole'rance minimale */
mstack2 = estack + (128 * PTR); /* Full Stack non re'cupe'rable */
mstack1 = estack + (1024 * PTR); /* Full Stack re'cupe'rable */
bstack = estack + sstack - PTR;
bcode = bstack + PTR;
ccode = bcode;
ecode = bcode + scode;
bheap = ecode;
cheap = bheap;
eheap = bheap + sheap;
bnumb = eheap;
cnumb = bnumb;
bfloat = bnumb + snumb;
cfloat = bfloat;
bvect = bfloat + sfloat;
cvect = bvect;
bstrg = bvect + svect;
cstrg = bstrg;
bsymb = bstrg + sstrg;
csymb = bsymb;
bcons = bsymb + ssymb;
econs = bcons + scons;
ccons = bcons;
btbin = econs;
btbgc = btbin + stbin;
emem = btbgc;
/* et on y va !!! */
llstdio();
lisp←stty();
host←start();
/* au retour (si l'on rentre) on sort joliement */
out(0);
}
/**********************************************************
L E S I M A G E S M E M O I R E S
**********************************************************/
/* l'instruction LLM3 CORSAV doit positionner les 4 variables:
bllm3, ellm3 limites de la zone impure LLM3
llucode fin de la zone code utilise'e
lluheap fin de la zone heap utilise'e */
char *bllm3, *ellm3;
/* Pour ne faire que des petites entrees/sorties (cf NFS ...) */
#ifndef WRITESIZE
#define WRITESIZE 8192
#endif WRITESIZE
WRITE(fd,where,length)
int fd, length;
char *where;
{
int cc, n;
/* Si on veut une trace e'crite: */
/* printf("WRITE: %d %x %x \r\n", fd, where, length); */
n = length;
while(n >= WRITESIZE) {
if ((cc = write(fd, where, WRITESIZE)) < 0)
return(cc);
where += cc;
n -= cc;
}
while(n > 0) {
if ((cc = write(fd, where, n)) < 0)
return(cc);
where += cc;
n -= cc;
}
return(length);
}
/************************************
Les images me'moires en mode EXECORE
************************************/
#ifdef EXECORE
/* Point de lancement effectif */
extern llcorgo(); /* dans ../<system>/ll<system>.llm3 */
/* Variables positionnees au moment du save-core BSD4x */
int corscons; /* taille des CONS de l'image me'moire */
int corstbin; /* bits invisibles de l'image me'moire */
char *corbtbin;
/***********
Le lancement direct (lelispbin -c) d'une image me'moire
re'alise'e en mode EXECORE.
***********/
extern corinit();
corinit () {
int diffcons;
int diffmem;
int i;
if (scons > corscons) {
if (sbrk(0) != END)
#ifdef FOREIGN
fprintf (stderr,
"Le-Lisp : I can't allocate space without hole\r\n");
#else FOREIGN
fprintf (stderr,
"Le-Lisp : je ne peux pas allouer de la place sans trou\r\n");
#endif FOREIGN
else {
/* l'image memoire est plus petite que lelisp courant */
diffcons = (scons - corscons);
/* bits invisibles */
diffmem = diffcons + (diffcons / 64);
/* bits du GC */
diffmem += diffcons / 64;
align(diffmem);
if (sbrk(diffmem) == RATE) {
#ifdef FOREIGN
fprintf (stderr,
"Le-Lisp : not enough ressources to allocate space\r\n");
#else FOREIGN
fprintf (stderr,
"Le-Lisp : Impossible de vous fournir tant de place\r\n");
#endif FOREIGN
out(-1);
}
econs += diffcons;
btbin = econs;
for (i = corstbin; --i >= 0;)
btbin[i] = corbtbin[i];
btbgc = btbin + stbin;
END = sbrk(0);
}
}
inton();
llcorgo();
}
/**********
Save-core en mode EXECORE
***********/
struct exec entete;
char corbuf[1024];
extern int errno;
int corsav (nom) char *nom; {
int fd, fdbin;
long symbols;
long bout;
int n, wr;
llglobb("","",-1); /* pour tuer un sous-sh */
/* positionne les variables pour le restore-core */
corscons = scons;
corbtbin = btbin;
corstbin = stbin;
if((fdbin = open(lelispbin, 0)) == -1)
errreturn(lelispbin, 1);
read(fdbin, &entete, sizeof (struct exec));
if((fd = creat(nom, 0777)) /* rwxrwxrwx | umask */
== -1){
if(errno != ETXTBSY)
errreturn(nom, 1);
if(unlink(nom) == -1)
errreturn(nom, 1);
if((fd = creat(nom, 0777)) /* rwxrwxrwx | umask */
== -1)
errreturn(nom, 1);
}
bout = (long) sbrk(0);
/* c'est la table des symboles de lelispbin qui nous interesse,
Il faut la calculer avant de changer le champ entete.a←data */
symbols = N←SYMOFF(entete);
entete.a←data = bout - N←DATADDR(entete);
entete.a←bss = 0;
entete.a←magic = ZMAGIC;
/* le header */
write(fd, &entete, sizeof(struct exec));
#ifdef SEQUENT
/* recopie du texte */
n = N←DATAOFF(entete) - sizeof(struct exec);
while (n >= 1024) {
read(fdbin, corbuf, 1024);
WRITE(fd, corbuf, 1024);
n -= 1024;
}
read(fdbin, corbuf, n);
WRITE(fd, corbuf, n);
WRITE(fd, entete.a←text, llucode - entete.a←text); /* le bas de lisp */
#else SEQUENT
#ifdef VAXUNIX
lseek(fd, N←TXTOFF(entete), 0); /* va au debut du texte */
write(fd, 0L, llucode); /* le bas de lisp */
#endif VAXUNIX
#endif SEQUENT
#ifdef VAXUNIX || SEQUENT
lseek(fd, bheap-llucode, 1); /* le trou fin de code */
WRITE(fd, bheap, lluheap-bheap); /* le tas */
lseek(fd, bnumb-lluheap, 1); /* le trou fin de tas */
WRITE(fd, bnumb, econs-bnumb); /* le reste */
WRITE(fd, btbin, stbin); /* les bits invisibles */
lseek(fd, bout-(long)btbin-stbin, 1);
#else VAXUNIX || SEQUENT
/* recopie du texte */
n = entete.a←text - sizeof(struct exec);
while (n >= 1024) {
read(fdbin, corbuf, 1024);
wr=write(fd, corbuf, 1024);
if(wr != 1024) { perror ("save-core1"); exit(1); }
n -= 1024;
}
read(fdbin, corbuf, n);
wr=write(fd, corbuf, n);
if(wr != n) { perror ("save-core1.1"); exit(1); }
/* le data */
wr=write(fd, N←DATADDR(entete), bout - N←DATADDR(entete));
if(wr != (int)bout-N←DATADDR(entete))
{ perror ("save-core2"); exit(1);}
#endif VAXUNIX || SEQUENT
/* le symbol */ /* on ajuste, normalement 0 sauf sur Sequent */
lseek(fdbin, symbols, 0);
while ((n = read(fdbin, corbuf, 1024)) > 0)
WRITE(fd, corbuf, n);
close(fdbin);
close(fd);
/* chmod(nom, 493); -rwxr-xr-x Pour garder le umask du user (creat).*/
return(0);
}
/**********
Restore-core en mode EXECORE
***********/
char *corargv[5] = { "lelispbin", "003", "003", "-c", 0};
int corest (nom) char *nom; {
int fd, i;
corargv[0] = nom; /* convention Unix */
if ((fd = open(nom, 0)) == -1)
errreturn(nom, 1);
close(fd);
sprintf(corargv[2], "%d", scons/(8*8*1024));
execve(nom, corargv, envpini);
errreturn (nom, 1);
}
#else EXECORE
/*************************************
Les images me'moires en mode standard
*************************************
L'ente↑te des fichiers image-me'moire contient :
- 3 mots d'identification (12 caracte`res)
- les tailles des zones de l'image me'moire
corsstack
corscode
corsheap
corsnumb
corsfloat
corsvect
corsstrg
corssymb
corscons
corstbin
- les tailles des bouts me'moires sauve's
sllm3
ucode
uheap
urest
*/
#define ID "lelisp core "
struct ENTETE {
char idlelisp[12];
int corsstack;
int corscode;
int corsheap;
int corsnumb;
int corsfloat;
int corsvect;
int corsstrg;
int corssymb;
int corscons;
int corstbin;
int sllm3;
int ucode;
int uheap;
int urest;
} entete;
/**********
Save-core en mode standard
***********/
int corsav (nom) char *nom; {
int fd;
if((fd = creat(nom, 511)) == -1)
errreturn(nom, 1);
strncpy(entete.idlelisp, ID, 12);
entete.corsstack = sstack;
entete.corscode = scode;
entete.corsheap = sheap;
entete.corsnumb = snumb;
entete.corsfloat = sfloat;
entete.corsvect = svect;
entete.corsstrg = sstrg;
entete.corssymb = ssymb;
entete.corscons = scons;
entete.corstbin = stbin;
entete.sllm3 = ellm3 - bllm3;
entete.ucode = llucode - bmem;
entete.uheap = lluheap - bheap;
entete.urest = econs - bnumb;
if(WRITE(fd, &entete, sizeof(struct ENTETE))
!= sizeof(struct ENTETE)){
/* entete */
close(fd);
errreturn(nom, 1);
}
if((WRITE(fd, bllm3, entete.sllm3)) != entete.sllm3){
/* variables LLM3 */
close(fd);
errreturn(nom, 1);
}
if((WRITE(fd, bmem, entete.ucode)) != entete.ucode){
/* code utilise' */
close(fd);
errreturn(nom, 1);
}
if((WRITE(fd, bheap, entete.uheap)) != entete.uheap){
/* heap utilise' */
close(fd);
errreturn(nom, 1);
}
if((WRITE(fd, bnumb, entete.urest)) != entete.urest){
/* zones lisp */
close(fd);
errreturn(nom, 1);
}
if((WRITE(fd, btbin, entete.corstbin)) != entete.corstbin){
/* bits invisibles */
close(fd);
errreturn(nom, 1);
}
if (close(fd) < 0)
errreturn("Le-Lisp",1);
return(0);
}
/**********
Restore-core en mode standard
***********/
int READ(fd,where,length)
int fd, length;
char *where;
{
int cc, n;
/* Si on veut une trace e'crite: */
/* printf("READ: %d %x %x \r\n", fd, where, length); */
return(read(fd, where, length));
}
int corest (nom) char *nom; {
int fd;
if((fd = open(nom, 0)) == -1)
errreturn(nom, 1);
if(READ(fd, &entete, sizeof(struct ENTETE))
!= sizeof(struct ENTETE)){
/* lit l'entete */
close(fd);
errreturn(nom, 1);
}
if(strncmp(entete.idlelisp, ID, 12)){
/* chai↑ne d'identification */
#ifdef FOREIGN
fprintf(stderr, "Le-Lisp : %s is not a core image\r\n", nom);
#else FOREIGN
fprintf(stderr,
"Le-Lisp : %s n'est pas une image memoire\r\n", nom);
#endif FOREIGN
close(fd);
if ((prtmsgs == 0) || (*prtmsgs == 0)) out (-1);
errreturn(nom, 1);
}
if((entete.corsstack != sstack)
|| (entete.corscode != scode)
|| (entete.corsheap != sheap)
|| (entete.corsnumb != snumb)
|| (entete.corsfloat != sfloat)
|| (entete.corsvect != svect)
|| (entete.corsstrg != sstrg)
|| (entete.corssymb != ssymb)){ /* les tailles fixes */
#ifdef FOREIGN
fprintf(stderr,
"Le-Lisp : non compatible core image : %s\r\n", nom);
#else FOREIGN
fprintf(stderr,
"Le-Lisp : image memoire non compatible : %s\r\n", nom);
#endif FOREIGN
close(fd);
if ((prtmsgs == 0) || (*prtmsgs == 0)) out (-1);
errreturn(nom, 1);}
if(entete.corscons > scons){ /* trop gros ? */
#ifdef FOREIGN
fprintf(stderr, "Le-Lisp : core image too large : %s\r\n", nom);
#else FOREIGN
fprintf(stderr, "Le-Lisp : image memoire trop grosse : %s\r\n",
nom);
#endif FOREIGN
close(fd);
errreturn(nom, 1);
}
if((READ(fd, bllm3, entete.sllm3)) != entete.sllm3){
/* variables LLM3 */
close(fd);
errreturn(nom, 1);
}
if((READ(fd, bmem, entete.ucode)) != entete.ucode){
/* code utilise' */
close(fd);
errreturn(nom, 1);
}
if((READ(fd, bheap, entete.uheap)) != entete.uheap){
/* heap utilise' */
close(fd);
errreturn(nom, 1);
}
if((READ(fd, bnumb, entete.urest)) != entete.urest){
/* zones lisp */
close(fd);
errreturn(nom, 1);
}
if((READ(fd, btbin, entete.corstbin)) != entete.corstbin){
/* bits invisibles */
close(fd);
errreturn(nom, 1);
}
close(fd);
return(0);
}
#endif EXECORE
/**********************************************************
cline: Envoi d'une commande au SHELL
**********************************************************/
cline (buff)
char *buff;
{
char *dir;
if (!strncmp(buff, "cd", 2)) { /* c'est peut-etre un cd */
dir = buff + 1;
while (*++dir == ' ')
/* void */ ;
if (*dir=='\0')
cchdir(getenv("HOME")); /* cd tout court */
else if (dir != buff+2)
if (!cchdir(dir)) /* cd PATH */
return (0);
}
unix←stty();
system(buff);
lisp←stty();
inton();
}
system(s)
char *s;
{
int status, pid, w;
#ifdef BSD4x
pid=vfork(); /* on forke astucieusement */
#endif
#ifdef S5
pid =fork(); /* on ne vforke pas en systeme 5 */
#endif
if (pid == 0) {
{int f;
for(f = 3;f < 10; f++)
(void) close(f); /* parano ! */
}
int←std();
execl("/bin/sh", "sh", "-c", s, 0);
←exit(127);
}
int←ign();
while ((w = wait(&status)) != pid && w != -1)
;
if (w == -1)
status = -1;
return(status);
}
/* runtime
=======
Retourne le temps depuis le debut du job.
Ce temps est en secondes (flottant).
L'unite' de temps de'pend du syste`me
*/
#ifndef TIMEUNIT
#ifdef BSD4x
#define TIMEUNIT 60.
#endif BSD4x
#ifdef S5
#define TIMEUNIT 1000.
#endif S5
#endif TIMEUNIT
#ifdef BSD42
double
runtime()
{
struct rusage urusage;
struct timeval utimeval;
getrusage(0, &urusage);
utimeval = urusage.ru←utime;
return(utimeval.tv←sec+(utimeval.tv←usec/1000000.));
}
#else BSD42
double
runtime()
{
struct tms timebuffer;
times(&timebuffer);
return (timebuffer.tms←utime / TIMEUNIT);
}
#endif BSD42
/* sleep
=======
Dort n secondes. Ce temps est en secondes (flottant).
Helas UN*X ne peut dormir qu'un nb de sec fixes
*/
/* En 31bitfloats: l'argument est dans accusingle1 */
csleep()
{
unsigned seconds;
seconds = accusingle1;
sleep(seconds);
}
/* En 64bitfloats: l'argument est en argument(dans la pile) */
cdleep(f)
double f; {
unsigned seconds;
seconds = f;
sleep(seconds);
}
/* cdate
=====
Donne la date courante
*/
extern struct tm *localtime();
cdate (date←lisp)
int *date←lisp;
{
struct tm decoded;
long clock;
clock = time(0);
decoded = *localtime(&clock);
date←lisp[0] = decoded.tm←year + 1900;
date←lisp[1] = decoded.tm←mon + 1;
date←lisp[2] = decoded.tm←mday;
date←lisp[3] = decoded.tm←hour;
date←lisp[4] = decoded.tm←min;
date←lisp[5] = decoded.tm←sec;
date←lisp[7] = decoded.tm←wday == 0 ? 7 : decoded.tm←wday;
}
/* setalarm
========
De'clenche une alarme apre`s n secondes (flottant).
*/
double setalarm(f)
double f; {
#ifdef BSD42
struct itimerval nit,oit;
register int secs;
secs = (long) (f * 1e+6); /* marche si f < 1000000 s ! */
timerclear(&nit.it←interval);
nit.it←value.tv←sec = secs / 1000000;
nit.it←value.tv←usec = secs % 1000000;
if (setitimer(ITIMER←REAL, &nit, &oit) < 0)
return(0);
return(oit.it←value.tv←sec + oit.it←value.tv←usec * 1e-6);
#else BSD42
#ifdef SPS7
/* sur SMX 5.1 il y a un hack pour avoir une horloge au 1/1000ieme */
register int secs;
extern int alarm←on;
secs = (long) (f * -1000.);
if ((secs == 0) && (f != 0.))
secs = -1; /* pour l'arrondi */
return((double) alarm(secs));
#else SPS7
register int secs;
extern int alarm←on;
secs = (long) f;
alarm←on = f == 0. ? 0 : 1;
if ((secs == 0) && (f != 0.))
secs = 1; /* pour l'arrondi */
return((double) alarm(secs));
#endif SPS7
#endif BSD42
}
/* getenvrn
========
Recherche d'une variable de l'environnement.
Rempli le buffer donne argument avec la chaine resultat.
Retourne la taille de la chaine.
*/
extern char *getenv();
int getenvrn (nom, buff)
char *nom, *buff;{
char *u;
if(nom = (u = getenv(nom))){
while(*buff++ = *u++);
return (u-nom-1);
}
return (0);
}
/* getgloba
=========
retourne la valeur associee a un symbole
dans la table des symboles de l'image Le-Lisp.
*/
/* la macro NLISTNAME permet de positionner le champ n←name d'un
e'le'ment de table des symboles.
Ca depend beaucoup des systemes... */
#ifdef BSD4x
#define NLISTNAME(e,i,s) e[i].n←un.n←name = s
#endif BSD4x
#ifdef Perkin
#define NLISTNAME(e,i,s) strncpy(e[i].n←name,s,8)
#endif Perkin
#ifdef CADMUS
#define NLISTNAME(e,i,s) strcpy(e[i].n←name, s)
#endif CADMUS
#ifdef HP9300
#define NLISTNAME(e,i,s) e[i].n←name = (*s == 0) ? NULL : s
#endif HP9300
#ifdef UNIGRAPH | LEWS
#define NLISTNAME(e,i,s) e[i].n←name = (*s == 0) ? s : s+1
#endif UNIGRAPH
/* le defaut */
#ifndef NLISTNAME
#define NLISTNAME(e,i,s) e[i].n←name = s
#endif NLISTNAME
struct nlist elem[2];
int getgloba (strg) char *strg; {
NLISTNAME(elem, 0, strg);
NLISTNAME(elem, 1, "");
nlist(lelispbin, elem);
return(elem[0].n←value);
}
/* le getglobal multiple */
struct lisp←string {
char *pad1;
char *pad2;
char chars;
};
struct lisp←cons {
struct lisp←string **car;
struct lisp←cons *cdr;
};
void mgetglo (list, nil)
struct lisp←cons *list, *nil; {
int length, i;
struct lisp←cons *courant;
struct nlist *elems;
char *name;
length = 0;
for (courant = list; courant != nil;
courant = (struct lisp←cons *)courant->cdr)
length++;
elems = (struct nlist *) malloc ((length+1) * sizeof(struct nlist));
i = 0;
for (courant = list; courant != nil;
courant = (struct lisp←cons *) courant->cdr) {
name = &((*(courant->car))->chars);
NLISTNAME(elems, i, name);
i++;
}
NLISTNAME(elems, i, "");
nlist (lelispbin, elems);
i = 0;
for (courant = list; courant != nil;
courant = (struct lisp←cons *) courant->cdr) {
courant->car = (struct lisp←string **) elems[i].n←value;
i++;
}
free(elems);
}
/* la routine de sortie */
out(code)
int code; {
if(!strncmp(lelispbin, template, 12))
unlink(lelispbin);
unix←stty();
exit(code); /* puis sort avec code de retour */
}
outner () { /* sortie normale depuis lisp */
out(0);
}
outwer () { /* sortie anormale depuis lisp */
out(-1); /* suivant la convention UNIX */
}
outcore() {
perror("Le-Lisp : restore-core : ");
out(-1);
}
/* la syntaxe d'appel de Le-Lisp sous UN*X */
char *usage() {
fprintf(stderr, "Usage : lelisp [-s] [file] [-r file] [number] \
[-stack number] [-code number] [-heap number] [-float number] \
[-vector number] [-string number] [-symbol number] [-cons number]\r\n");
out(-1);
return((char *)-1);
}
zonevide(s){
#ifdef FOREIGN
fprintf(stderr, "Empty %s zone\r\n", s);
#else FOREIGN
fprintf(stderr, "Zone %s vide\r\n", s);
#endif FOREIGN
out(-1);
}
/*
Le chargement dynamique de modules C
Courtesy of L. Fallot
Revu par M. Devin
*/
#define wwe(s) write(2,s,strlen(s))
#define round(x,s) ((((x)-1) & ~((s)-1)) +(s))
#ifndef S5
char *
cload(file, ccode, ecode)
char *file, *ccode, *ecode;{
char *ccoderound;
int taille;
int totale;
char cbuf[512];
int fd;
struct exec header;
int i;
/* remettre 6 X au bout du template
et ge'ne'rer un nom unique */
for(i = strlen(template)-6; i < strlen(template); i++)
template[i] = 'X';
mktemp(template);
/* arrondir ccode a` la taille de la page */
#ifdef SPS9
ccoderound = (char *)round((int)ccode, 4096);
#else SPS9
#ifdef SEQUENT
ccoderound = (char *)round((int)ccode, 2048);
#else SEQUENT
ccoderound = (char *)round((int)ccode, 512);
#endif SEQUENT
#endif SPS9
/* appeler le linker */
sprintf(cbuf,
#ifdef SPS9
"/bin/ld -C -A %s -N -x -T %x -o %s %s -lc",
#else SPS9
#ifdef SUNOS40
"/bin/ld -A %s -Bstatic -N -x -T %x -o %s %s -lc",
#else SUNOS40
"/bin/ld -A %s -N -x -T %x -o %s %s -lc",
#endif SUNOS40
#endif SPS9
lelispbin,
ccoderound,
template,
file);
cline(cbuf);
/* Le link est-il bien fini ? */
fd = open(template, 0);
if (fd < 0) {
perror(template);
unlink(template);
return(ccode);
}
if(read(fd,&header,sizeof(header)) != sizeof(header)) {
perror(template);
close(fd);
unlink(template);
return(ccode);
}
/* le programme ge'ne're' tient-il dans la zone code ? */
taille = round(header.a←text, 4) + round(header.a←data, 4);
totale = taille + header.a←bss;
#ifdef SPS9
totale = round(totale, 4096);
#else SPS9
#ifdef SEQUENT
totale = round(totale, 2048);
#else SEQUENT
totale = round(totale, 512);
#endif SEQUENT
#endif SPS9
if((ccoderound+totale) >= ecode){
fprintf(stderr,
#ifdef FOREIGN
"cload: fatal error full code zone: missing %d Kbytes\r\n",
#else FOREIGN
"cload: erreur fatale zone code pleine: il manque %d Koctets\r\n",
#endif FOREIGN
((ccoderound+totale-ecode))/1024+1);
return(ccode);
}
if (taille != read(fd,ccoderound,taille)) {
perror(template);
close(fd);
unlink(template);
return(ccode);
}
close(fd);
if(!strncmp(lelispbin, template, 12))
unlink(lelispbin);
strcpy(lelispbin, template);
return(ccoderound+totale);
}
#endif S5
/* le repertoire courant */
int
llgetwd (s, l) char *s; int l; {
int code;
#ifdef VAXUNIX
code = getwd(s); /* maxpathlen is the max */
#else VAXUNIX
code = getcwd(s, l);
#endif VAXUNIX
return(code ? strlen(s) : 0);
}
/*
Les tests pour callextern
*/
int cchdir (strg) char *strg; {
return(llglobb(strg,"",0));
}
char *chome () {
return(getenv("HOME"));
}
#ifdef BSD42
char *date () {
char *s;
long temps;
temps = time(0);
s = ctime(&temps);
*(s+24) = '\0';
return(s);
}
#endif BSD42
#ifdef SPS9
#include "lelisp.h"
struct LL←SYMBOL *ll←concat;
struct LL←SYMBOL *
getsym (s) char *s; {
pusharg(LLT←STRING, s);
return (struct LL←SYMBOL *) lispcall (LLT←T, 1, ll←concat);
}
#endif SPS9
int cmoinsun () {
return(-1);
}
double ctest (strg,nf,ni,vect) char *strg; double nf; int ni; int *vect;{
int i;
printf("la chaine est %s\r\n", strg);
printf("le flottant est %e\r\n", nf);
printf("l'entier est %d\r\n", ni);
printf("le vecteur contient vect[0]=%8x,vect[1]=%8x\r\n",
vect[0], vect[1]);
i = vect[0]; vect[0] = vect[1]; vect[1] = i;
return(nf*ni);
}
cboucle () {
while (1) sin(3.14);
}
/*
* newer
* =====
* Lists both of its arguments newer first.
* For CAML module system.
*/
static time←t fdate(name)
char *name;
{
struct stat stbuf;
if (stat(name, &stbuf) == -1) {
return(-1);
}
return(stbuf.st←mtime);
}
newer(name1,name2)
char *name1;
char *name2;
{
time←t date1;
time←t date2;
date1 = fdate (name1);
date2 = fdate (name2);
if (date1 == -1)
if (date2 == -1)
return(-3);
else
return(-1);
if (date2 == -1)
return(-2);
return(date1 > date2);
}
/* Ce paragraphe contient le mecanisme de wildcarding implemente sur
BSD4.2 (SUN) . Il essaie d'etre relativement efficace. la premiere
invocation cree un sous process cshell par vfork les fois suivantes ,
on se contente de piper les noms a expanser et a recuperer les chaines
expansees, apres quoi, lisp en fait ce qu'il veut....
Auteur : Michel DANA
Date : 26 Aout 1988
Modif : 31 Aout 1988 pour adaptation SYSTEM 5
*/
#define MAXLINE 1024
int llglobb (ll←in←string,ll←out←string,maxline)
char *ll←in←string, *ll←out←string ; {
static int pipe←in[2],pipe←out[2],first←time=0,pid=0;
static int incopy, outcopy;
static char *s;
static FILE *stream←in, *stream←out;
static char buff[MAXLINE];
int i;
/* EN */
if (maxline==0) /* chdir */
{if (chdir(ll←in←string)) return(-1); /* chdir pour le process-meme */
if (first←time==0) return(0); /* pas de sous-shell */
}; /* on en reste la */
if (maxline==-1) /* destruction du sous-shell */
{if (first←time==0) /* meme pas cree encore */
return(0); /* on en reste la */
fclose(stream←out); /* on ferme fd vers le sh */
i=wait(0); /* le sous-sh est mort */
fclose(stream←in); /* on ferme le fd venant du sh */
first←time=0; /* on revient a l'etat */
return(i);}; /* on en reste la */
if (first←time==0){
/* c'est la premiere fois, il y a des choses a initialiser */
if (maxline==0) /* chdir? */
return(chdir(ll←in←string)); /* nouvelle directory */
if (pipe(pipe←in) || pipe(pipe←out)) /* erreur? */
return(-7); /* retour lelisp */
incopy=dup(0); /* copie pour cline .... */
outcopy=dup(1); /* ... redirige par <> dans sh */
first←time=1;
#ifdef BSD4x
pid=vfork(); /* on forke astucieusement */
#endif
#ifdef S5
pid =fork(); /* on ne vforke pas en systeme 5 */
#endif
if (pid<0) return(-8); /* erreur? retour lelisp */
if (pid==0) { /* je suis le fils */
close(pipe←in[1]); /* faut pas oublier */
close(pipe←out[0]); /* ces deux inutiles-la */
#ifdef BSD4x
dup2(pipe←in[0],0); /* je reassigne stdin */
dup2(pipe←out[1],1); /* la meme chose sur stdout */
#endif
#ifdef S5
fclose(stdin);
fclose(stdout);
dup(pipe←in[0]);
dup(pipe←out[1]);
#endif
/* freopen("/dev/null","w",stderr); pour ne pas avoir de messages */
/* bizarres en cas d'echec */
execl ("/bin/sh","sh",0); /* sh existe partout */
}
/* le pere maintenant */
close(pipe←in[0]);
close(pipe←out[1]); /* inutile de conserver des descripteurs */
/* inutiles */
stream←in=fdopen(pipe←out[0],"r");
stream←out=fdopen(pipe←in[1],"w");
#ifdef BSD4x
setlinebuf(stream←out); /* fin des initialisations */
#endif
#ifdef S5
setbuf(stream←out,NULL); /*pas de bufferisation....*/
#endif
fputs("trap '' 2\n", stream←out); /* contre les ↑C de Lelisp */
close(incopy); /* seul utilise par le fils */
close(outcopy);
}
if (kill(pid,0)<0) /* le pid, est-il la? */
{fclose(stream←out); /* non, on ferme */
fclose(stream←in); /* les filedesc */
first←time=0; /* pret a recommencer */
if (maxline == 0) return(0); /* chdir?, pas d'erreur */
return(-9);}; /* retour Lelisp */
if (maxline == 0) /* chdir, suite */
{fprintf( /* on compose une commande cd */
stream←out, /* vers le sous-sh */
"cd %s\n", /* le template */
ll←in←string); /* la directory */
return(0);}; /* on en reste la */
if (maxline==-2) /* on simule cline */
{int←ign(); /* prolog de ... */
unix←stty(); /* .. cline */
fprintf /* on construit la commande */
(stream←out, /* vers le sous-sh */
"sh -c 'exec <&%d >&%d; %s'\n", /* recuperation de ... */
incopy, /* ... stdin ...*/
outcopy, /* ... stdout */
ll←in←string); /* la commande-cline */
fprintf(stream←out,"echo $?\n"); /* imprime exit-status */
fscanf(stream←in,"%d",&i); /* recupere exit-status */
lisp←stty(); /* epilog de ... */
inton(); /* ... cline */
return(i);}; /* synchronise' */
s= & buff[0];
buff[0]='\0';
strcat(&buff[0],"echo ll: ");
strcat(&buff[0],ll←in←string);
strcat(&buff[0],"\n");
/* printf("on passe %s \n",&buff[0]); */
fputs(s ,stream←out);
while (strncmp(s=fgets(buff,maxline,stream←in),"ll: ",4)); /* on */
/* tout */
/* garbage */
s=s+4;
strcpy(ll←out←string,s);
return(strlen(ll←out←string));
}