YAP 7.1.0
load_aout.c
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: load_aout.c *
12* comments: aout based dynamic loader of external routines *
13* *
14*************************************************************************/
15
16#include "Yap.h"
17#include "yapio.h"
18#include "Foreign.h"
19
20#ifdef A_OUT
21this code is no being maintained anymore
22#include <stdio.h>
23#if STDC_HEADERS
24#include <stdlib.h>
25#endif
26#if HAVE_UNISTD_H
27#include <unistd.h>
28#endif
29#if HAVE_FCNTL_H
30#include <fcntl.h>
31#endif
32#if HAVE_SYS_TYPES_H
33#include <sys/types.h>
34#endif
35#if HAVE_SYS_FILE_H
36#include <sys/file.h>
37#endif
38#if HAVE_SYS_PARAM_H
39#include <sys/param.h>
40#endif
41#if HAVE_SYS_STAT_H
42#include <sys/stat.h>
43#endif
44#include <a.out.h>
45
46
47
48#define oktox(n) \
49 (0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFREG&&0==access(n,X_OK))
50#define oktow(n) \
51 (0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFDIR&&0==access(n,W_OK))
52
53/*
54 * YAP_FindExecutable(argv[0]) should be called on yap initialization to
55 * locate the executable of Yap
56*/
57char *
58Yap_FindExecutable(void)
59{
60 register char *cp, *cp2;
61 struct stat stbuf;
62
63
64 cp = (char *)getenv("PATH");
65 if (cp == NULL)
66 cp = ".:/usr/ucb:/bin:/usr/bin:/usr/local/bin";
67 if (*GLOBAL_argv[0] == '/') {
68 if (oktox(GLOBAL_argv[0])) {
69 strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
70 Yap_AbsoluteFileInBuffer(LOCAL_FileNameBuf, true);
71 strncpy( GLOBAL_Executable, LOCAL_FileNameBuf, PATH_MAX);
72 return;
73 }
74 }
75 if (*cp == ':')
76 cp++;
77 for (; *cp;) {
78 /*
79 * copy over current directory and then append
80 * argv[0]
81 */
82
83 for (cp2 = LOCAL_FileNameBuf; (*cp) != 0 && (*cp) != ':';)
84 *cp2++ = *cp++;
85 *cp2++ = '/';
86 strcpy(cp2, GLOBAL_argv[0]);
87 if (*cp)
88 cp++;
89 if (!oktox(LOCAL_FileNameBuf))
90 continue;
91 Yap_AbsoluteFileInBuffer(Yap_AbsoluteFileInBuffer(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
92 return;
93 }
94 /* one last try for dual systems */
95 strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
96 Yap_AbsoluteFileInBuffer(Yap_AbsoluteFileInBuffer(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
97 if (oktox(GLOBAL_Executable))
98 return GLOBAL_Executable;
99 else
100 Yap_Error(SYSTEM_ERROR_INTERNAL,MkAtomTerm(Yap_LookupAtom(GLOBAL_Executable)),
101 "cannot find file being executed");
102}
103
104void *
105Yap_LoadForeignFile(char *file, int flags)
106{
107 /* not implemented */
108 return NULL;
109}
110
111int
112Yap_CallForeignFile(void *handle, char *f)
113{
114 return FALSE;
115}
116
117int
118Yap_CloseForeignFile(void *handle)
119{
120 return -1;
121}
122
123
124/*
125 * LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
126 * code files and libraries and locates an initialization routine
127*/
128static int
129LoadForeign(StringList ofiles,
130 StringList libs,
131 char *proc_name,
132 YapInitProc *init_proc)
133{
134 char command[2*PATH_MAX];
135 char o_files[1024]; /* list of objects we want to load
136 */
137 char l_files[1024]; /* list of libraries we want to
138 load */
139 char tmp_buff[32] = "/tmp/YAP_TMP_XXXXXX"; /* used for
140 mktemp */
141 char *tfile; /* name of temporary file */
142 int fildes; /* temp file descriptor */
143 struct exec header; /* header for loaded file */
144 unsigned long loadImageSize, firstloadImSz; /* size of image we will load */
145 char *FCodeBase; /* where we load foreign code */
146
147 /*
148 * put in a string the names of the files you want to load and of any
149 * libraries you want to use
150 */
151 /* files first */
152 *o_files = '\0';
153 {
154 StringList tmp = ofiles;
155
156 while(tmp != NULL) {
157 strcat(o_files," ");
158 strcat(o_files,AtomName(tmp->name));
159 tmp = tmp->next;
160 }
161 }
162 /* same_trick for libraries */
163 *l_files = '\0';
164 {
165 StringList tmp = libs;
166
167 while(tmp != NULL) {
168 strcat(l_files," ");
169 strcat(l_files,AtomName(tmp->name));
170 tmp = tmp->next;
171 }
172 }
173 /* next, create a temp file to serve as loader output */
174 tfile = mktemp(tmp_buff);
175
176 /* prepare the magic */
177 if (strlen(o_files) + strlen(l_files) + strlen(proc_name) +
178 strlen(GLOBAL_Executable) > 2*PATH_MAX) {
179 strcpy(LOCAL_ErrorSay, " too many parameters in load_foreign/3 ");
180 return LOAD_FAILLED;
181 }
182 sprintf(command, "/usr/bin/ld -N -A %s -o %s -u _%s %s %s -lc",
183 GLOBAL_Executable,
184 tfile, proc_name, o_files, l_files);
185 /* now, do the magic */
186 if (system(command) != 0) {
187 unlink(tfile);
188 strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
189 return LOAD_FAILLED;
190 }
191 /* now check the music has played */
192 if ((fildes = open(tfile, O_RDONLY)) < 0) {
193 strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
194 return LOAD_FAILLED;
195 }
196 /* it did, get the mice */
197 /* first, get the header */
198 read(fildes, (char *) &header, sizeof(header));
199 close(fildes);
200 /* get the full size of what we need to load */
201 loadImageSize = header.a_text + header.a_data + header.a_bss;
202 /* add 16 just to play it safe */
203 loadImageSize += 16;
204 /* keep this copy */
205 firstloadImSz = loadImageSize;
206 /* now fetch the space we need */
207 if (!(FCodeBase = Yap_AllocCodeSpace((int) loadImageSize))) {
208 strcpy(LOCAL_ErrorSay," unable to allocate space for external code ");
209 return LOAD_FAILLED;
210 }
211 /* now, a new incantation to load the new foreign code */
212 sprintf(command, "/usr/bin/ld -N -A %s -T %lx -o %s -u _%s %s %s -lc",
213 GLOBAL_Executable,
214 (unsigned long) FCodeBase,
215 tfile, proc_name, o_files, l_files);
216 /* and do it */
217 if (system(command) != 0) {
218 unlink(tfile);
219 strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
220 return LOAD_FAILLED;
221 }
222 if ((fildes = open(tfile, O_RDONLY)) < 0) {
223 strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
224 return LOAD_FAILLED;
225 }
226 read(fildes, (char *) &header, sizeof(header));
227 loadImageSize = header.a_text + header.a_data + header.a_bss;
228 if (firstloadImSz < loadImageSize) {
229 strcpy(LOCAL_ErrorSay," miscalculation in load_foreign/3 ");
230 return LOAD_FAILLED;
231 }
232 /* now search for our init function */
233 {
234 char entry_fun[256];
235 struct nlist func_info[2];
236 sprintf(entry_fun, "_%s", proc_name);
237 func_info[0].n_un.n_name = entry_fun;
238 func_info[1].n_un.n_name = NULL;
239 if (nlist(tfile, func_info) == -1) {
240 strcpy(LOCAL_ErrorSay," in nlist(3) ");
241 return LOAD_FAILLED;
242 }
243 if (func_info[0].n_type == 0) {
244 strcpy(LOCAL_ErrorSay," in nlist(3) ");
245 return LOAD_FAILLED;
246 }
247 *init_proc = (YapInitProc)(func_info[0].n_value);
248 }
249 /* ok, we got our init point */
250 /* now read our text */
251 lseek(fildes, (long)(N_TXTOFF(header)), 0);
252 {
253 unsigned int u1 = header.a_text + header.a_data;
254 read(fildes, (char *) FCodeBase, u1);
255 /* zero the BSS segment */
256 while (u1 < loadImageSize)
257 FCodeBase[u1++] = 0;
258 }
259 close(fildes);
260 unlink(tfile);
261 return LOAD_SUCCEEDED;
262}
263
264Int
265Yap_LoadForeign(StringList ofiles, StringList libs,
266 char *proc_name, YapInitProc *init_proc)
267{
268 return LoadForeign(ofiles, libs, proc_name, init_proc);
269}
270
271void
272Yap_ShutdownLoadForeign(void)
273{
274}
275
276Int
277Yap_ReLoadForeign(StringList ofiles, StringList libs,
278 char *proc_name, YapInitProc *init_proc)
279{
280 return(LoadForeign(ofiles,libs, proc_name, init_proc));
281}
282
283
284#endif
285
286
287
288
load_foreign_files/3 has works for the following configurations:
Main definitions.