sysunix.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. /* sysunix.c Copyright (C) 1989-96 Codemist Ltd */
  2. /*
  3. * General Unix system-specific code
  4. */
  5. /* Signature: 76ef626e 07-Mar-2000 */
  6. #include "machine.h"
  7. #include <sys/stat.h>
  8. #ifndef NO_UNISTD_AVAILABLE
  9. /*
  10. * Posix mandates a header <unistd.h>, which is why I feel entitled to
  11. * include it here. But for systems that do not I can assert
  12. * NO_UNISTD_AVAILABLE in machine.h and worry about other ways to
  13. * reference the relevant facilities...
  14. */
  15. #include <unistd.h>
  16. #endif
  17. #ifdef __hpux
  18. /*
  19. * Get the regular headers to define a few more things...
  20. */
  21. #define _SYSCALL_INCLUDED
  22. #endif
  23. #include <stdarg.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <sys/types.h>
  28. #include <dirent.h>
  29. #include <errno.h>
  30. #include "tags.h"
  31. #include "externs.h"
  32. #include "sys.h"
  33. #ifdef TIMEOUT
  34. #include "timeout.h"
  35. #endif
  36. #include "filename.c"
  37. int change_directory(char *filename, char *old, size_t n)
  38. {
  39. process_file_name(filename, old, n);
  40. if (*filename == 0) return 1;
  41. if (chdir(filename))
  42. { char err_buf[LONGEST_LEGAL_FILENAME+100];
  43. char *msg;
  44. switch (errno)
  45. {
  46. case ENOTDIR:
  47. msg = "A component of %s is not a directory.";
  48. break;
  49. case ENOENT:
  50. msg = "The directory %s does not exist.";
  51. break;
  52. case EACCES:
  53. msg = "Insufficient permission for %s.";
  54. break;
  55. #ifndef HP_UNIX
  56. /*
  57. * This symbol seems not to be available under HP versions of Unix.
  58. * Since I am just producing pretty error messages here the loss of
  59. * functionality missing it out is pretty minor...
  60. */
  61. case ELOOP:
  62. msg = "Pathname %s has too many symbolic links.";
  63. break;
  64. #endif
  65. case ENAMETOOLONG:
  66. msg = "The pathname %s is too long.";
  67. break;
  68. default:
  69. msg = "Cannot change directory to %s.";
  70. break;
  71. }
  72. sprintf(err_buf, msg, filename);
  73. aerror0(err_buf);
  74. return 1;
  75. }
  76. else return 0;
  77. }
  78. int create_directory(char *filename, char *old, size_t n)
  79. {
  80. process_file_name(filename, old, n);
  81. if (*filename == 0) return 1;
  82. return mkdir(filename, 0770);
  83. }
  84. static void remove_files(char *name, int dirp, long int size)
  85. /* Remove a file, or a directory and all its contents */
  86. {
  87. switch (dirp)
  88. {
  89. case 0: /* SCAN_FILE */
  90. remove(name);
  91. return;
  92. case 2: /* SCAN_ENDDIR */
  93. rmdir(name);
  94. return;
  95. default: /* 1 == SCAN_STARTDIR */
  96. return;
  97. }
  98. }
  99. int delete_file(char *filename, char *old, size_t n)
  100. {
  101. process_file_name(filename, old, n);
  102. if (*filename == 0) return 0;
  103. /*
  104. * We cannot simply use remove here, since this will not
  105. * work with directories and their contents. Hence the
  106. * use of scan_directory.
  107. */
  108. scan_directory(filename, remove_files);
  109. return 0;
  110. }
  111. /* extern char *getcwd(char *s, size_t n); in case unistd not used */
  112. int get_current_directory(char *s, int n)
  113. {
  114. #ifdef NO_GETCWD
  115. aerror0("cannot get current directory name.");
  116. *s = 0;
  117. return 0;
  118. #else
  119. if (getcwd(s, n) == 0)
  120. { switch(errno)
  121. {
  122. case ERANGE:
  123. aerror0("the pathname of the current directory is too long.");
  124. break;
  125. case EACCES:
  126. aerror0("insufficient permission to get pathname.");
  127. break;
  128. default:
  129. aerror0("cannot get current directory name.");
  130. break;
  131. }
  132. *s = 0;
  133. return 0;
  134. }
  135. else return strlen(s);
  136. #endif
  137. }
  138. #ifndef S_IFMT
  139. #ifdef __S_IFMT
  140. #define S_IFMT __S_IFMT
  141. #endif
  142. #endif
  143. #ifndef S_IFDIR
  144. #ifdef __S_IFDIR
  145. #define S_IFDIR __S_IFDIR
  146. #endif
  147. #endif
  148. #ifndef S_IFLNK
  149. #ifdef __S_IFLNK
  150. #define S_IFLNK __S_IFLNK
  151. #endif
  152. #endif
  153. #ifndef S_ISLNK
  154. #ifdef S_IFLNK
  155. #ifdef S_IFMT
  156. #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
  157. #endif
  158. #endif
  159. #endif
  160. int directoryp(char *filename, char *old, size_t n)
  161. {
  162. struct stat buf;
  163. process_file_name(filename, old, n);
  164. if (*filename == 0) return 0;
  165. if (stat(filename,&buf) == -1) return 0;
  166. return ((buf.st_mode & S_IFMT) == S_IFDIR);
  167. }
  168. char *get_truename(char *filename, char *old, size_t n)
  169. {
  170. struct stat buf;
  171. char *temp, *fn, *dir, *pwd;
  172. process_file_name(filename, old, n);
  173. if (*filename == 0) aerror("truename");
  174. /* Find out whether we have a file or a directory */
  175. if (stat(filename,&buf) == -1) aerror0("truename: cannot stat file");
  176. /* Store current directory */
  177. /* /*
  178. * The next line is UNSATISFACTORY because Posix explicitly says (at least in
  179. * in the copy of 1003.1 that I have) that getcwd has undefined behaviour
  180. * if its first argument is NULL.
  181. */
  182. if ((pwd = (char *)getcwd((char *)NULL, LONGEST_LEGAL_FILENAME)) == NULL)
  183. aerror0("truename: cannot get current working directory");
  184. if ((buf.st_mode & S_IFMT) == S_IFDIR)
  185. { /* We have a directory */
  186. char *dir = (char*) malloc(LONGEST_LEGAL_FILENAME);
  187. if (chdir(filename) != 0)
  188. aerror0("truename: cannot change directory");
  189. if (getcwd(dir,LONGEST_LEGAL_FILENAME) == NULL)
  190. aerror0("truename: cannot get current working directory");
  191. if (chdir(pwd) != 0)
  192. aerror0("truename: cannot change directory");
  193. free(pwd);
  194. /*
  195. * Axiom-specific hack: truename preserves '/' at the end of
  196. * a path
  197. */
  198. if (old[n-1] == '/' && dir[strlen(dir)-1] != '/')
  199. { n = strlen(dir);
  200. dir[n] = '/';
  201. dir[n+1] = '\0';
  202. }
  203. return dir;
  204. }
  205. else
  206. { /* Assume we have some kind of file */
  207. temp = strrchr(filename,'/');
  208. if (temp)
  209. { /* Found a directory component */
  210. fn = (char *)malloc(1+strlen(temp));
  211. strcpy(fn, temp); /* strdup(temp); */
  212. *temp = '\0';
  213. /* fn is now "/file" and filename is the directory */
  214. if (chdir(filename) != 0)
  215. aerror0("truename: cannot change directory");
  216. /* /* getcwd(NULL,...) invalid */
  217. if ((temp = (char *)getcwd((char *)NULL,LONGEST_LEGAL_FILENAME)) == NULL)
  218. aerror0("truename: cannot get current working directory");
  219. if (chdir(pwd) != 0)
  220. aerror0("truename: cannot change directory");
  221. dir = (char *)malloc((strlen(temp) + strlen(fn) + 1)*sizeof(char));
  222. /* /*
  223. * No check for malloc failure...
  224. */
  225. strcpy(dir, temp);
  226. free(temp);
  227. free(pwd);
  228. strcat(dir, fn);
  229. free(fn);
  230. return dir;
  231. }
  232. else
  233. { dir = (char *)malloc((strlen(pwd) + strlen(filename) + 2)*sizeof(char));
  234. /* /* No check for malloc failure */
  235. strcpy(dir,pwd);
  236. strcat(dir, "/");
  237. strcat(dir, filename);
  238. free(pwd);
  239. return dir;
  240. }
  241. }
  242. }
  243. #ifndef DO_NOT_USE_STAT
  244. int file_readable(char *filename, char *old, size_t n)
  245. {
  246. struct stat buf;
  247. process_file_name(filename, old, n);
  248. if (*filename == 0) return 0;
  249. if (stat(filename,&buf) == -1)
  250. return 0; /* File probably does not exist */
  251. else if (geteuid() == buf.st_uid)
  252. return (buf.st_mode & S_IRUSR);
  253. else if (getegid() == buf.st_gid)
  254. return (buf.st_mode & S_IRGRP);
  255. else
  256. return (buf.st_mode & S_IROTH);
  257. }
  258. int file_writeable(char *filename, char *old, size_t n)
  259. {
  260. struct stat buf;
  261. process_file_name(filename, old, n);
  262. if (*filename == 0) return 0;
  263. if (stat(filename,&buf) == -1)
  264. return 0; /* Should we check to see if the directory is writeable? */
  265. else if (geteuid() == buf.st_uid)
  266. return (buf.st_mode & S_IWUSR);
  267. else if (getegid() == buf.st_gid)
  268. return (buf.st_mode & S_IWGRP);
  269. else
  270. return (buf.st_mode & S_IWOTH);
  271. }
  272. #else
  273. int file_readable(char *filename, char *old, size_t n)
  274. {
  275. FILE *fp;
  276. process_file_name(filename, old, n);
  277. if (*filename == 0) return 0;
  278. /* The "correct" way to do this is via stat, but this is much simpler! */
  279. fp = fopen(filename,"r");
  280. if (fp == NULL) return 0;
  281. else
  282. { fclose(fp);
  283. return 1;
  284. }
  285. }
  286. int file_writeable(char *filename, char *old, size_t n)
  287. {
  288. FILE *fp;
  289. process_file_name(filename, old, n);
  290. if (*filename == 0) return 0;
  291. fp = fopen(filename,"a");
  292. if (fp == NULL) return 0;
  293. else
  294. { fclose(fp);
  295. return 1;
  296. }
  297. }
  298. #endif
  299. int rename_file(char *from_name, char *from_old, size_t from_size,
  300. char *to_name, char *to_old, size_t to_size)
  301. {
  302. process_file_name(from_name, from_old, from_size);
  303. process_file_name(to_name, to_old, to_size);
  304. if (*from_name == 0 || *to_name == 0) return 0;
  305. return rename(from_name,to_name);
  306. }
  307. #ifdef NAG_VERSION
  308. int list_directory_members(char *filename, char *old, char **filelist[],
  309. size_t n)
  310. { struct dirent **namelist;
  311. int number_of_entries, i;
  312. char **files;
  313. process_file_name(filename, old, n);
  314. /* scandir expects "." for the current directory */
  315. if (*filename == 0) number_of_entries = scandir(".",&namelist,NULL,NULL);
  316. else number_of_entries = scandir(filename,&namelist,NULL,NULL);
  317. /*
  318. * If the scandir failed then return now, since we make an assumption later
  319. * that we found at least two entries: "." and "..".
  320. */
  321. if (number_of_entries == -1) return -1;
  322. files=(char **)malloc(number_of_entries*sizeof(char *));
  323. for (i=0;i<number_of_entries;++i)
  324. { files[i] = strdup(namelist[i]->d_name);
  325. free(namelist[i]);
  326. }
  327. free(namelist);
  328. *filelist = files;
  329. /*
  330. * When we return we will prepend the directory name to the files, so we
  331. * must make sure it is suitable for that. This is done here since it is
  332. * platform dependent (i.e. in DOS we would need to ensure the last
  333. * character was "\").
  334. */
  335. /*
  336. i=strlen(filename);
  337. if (i > 0 && filename[i-1] != '/')
  338. { filename[i]='/';
  339. filename[i+1]='\0';
  340. }
  341. */
  342. return number_of_entries;
  343. }
  344. #else
  345. void list_directory_members(char *filename, char *old,
  346. size_t n, directory_callback *fn)
  347. {
  348. process_file_name(filename, old, n);
  349. scan_files(filename, fn);
  350. }
  351. #endif
  352. CSLbool file_exists(char *filename, char *old, size_t n, char *tt)
  353. /*
  354. * This returns YES if the file exists, and as a side-effect copies a
  355. * textual form of the last-changed-time of the file into the buffer tt.
  356. */
  357. {
  358. struct stat statbuff;
  359. process_file_name(filename, old, n);
  360. if (*filename == 0) return NO;
  361. if (stat(filename, &statbuff) != 0) return NO;
  362. strcpy(tt, ctime(&(statbuff.st_mtime)));
  363. return YES;
  364. }
  365. /*
  366. * getenv() is a mild pain in two respects - firstly Ultrix uses
  367. * a non-ANSI definition (using 2 args not 1), and the MSDOS seems
  368. * to have a strong preference for upper case names. To allow for
  369. * all this I do not call getenv() directly but go via the following
  370. * code that can patch things up.
  371. */
  372. #ifdef TWO_ARG_GETENV
  373. char *my_getenv(char *s)
  374. {
  375. static char value[LONGEST_LEGAL_FILENAME];
  376. getenv(s, value);
  377. return value;
  378. }
  379. #else
  380. char *my_getenv(char *s)
  381. {
  382. return getenv(s);
  383. }
  384. #endif
  385. int my_system(char *s)
  386. {
  387. return system(s);
  388. }
  389. FILE *my_popen(char *a, char *b)
  390. {
  391. #ifdef NCC_LIB
  392. return NULL;
  393. #else
  394. return (FILE *)popen(a, b);
  395. #endif
  396. }
  397. void my_pclose(FILE *a)
  398. {
  399. #ifndef NCC_LIB
  400. pclose(a);
  401. #endif
  402. }
  403. #ifndef DO_NOT_USE_GETUID
  404. /*
  405. * "machine.h" should set DO_NOT_USE_GETUID if that function is not
  406. * properly available. Not having it will make the treatment of
  407. * (eg) "~xxx/..." in filenames less satisfactory.
  408. */
  409. #include <pwd.h>
  410. int get_home_directory(char *b, int len)
  411. {
  412. int i;
  413. struct passwd *pw = getpwuid(getuid());
  414. strcpy(b, pw->pw_dir);
  415. i = strlen(b);
  416. /* Here the directory handed back has "/" forced in as its final character */
  417. if ( b[i-1] != '/')
  418. { b[i++] = '/';
  419. b[i] = 0;
  420. }
  421. return i;
  422. }
  423. int get_users_home_directory(char *b, int len)
  424. {
  425. struct passwd *pw = getpwnam(b);
  426. if (pw != NULL) strcpy(b, pw->pw_dir);
  427. else strcpy(b, "."); /* use current directory if getpwnam() fails */
  428. return strlen(b);
  429. }
  430. #else /* USE_GETUID */
  431. int get_home_directory(char *b, int len)
  432. {
  433. int i;
  434. strcpy(b, getenv("HOME")); /* Probably works with most shells */
  435. i = strlen(b);
  436. if ( b[i-1] != '/')
  437. { b[i++] = '/';
  438. b[i] = 0;
  439. }
  440. return i;
  441. }
  442. int get_users_home_directory(char *b, int len)
  443. {
  444. strcpy(b, "."); /* use current directory if getpwnam() no available */
  445. return 1;
  446. }
  447. #endif /* USE_GETUID */
  448. #ifdef UNIX_TIMES
  449. /*
  450. * This is a BSD-style clock facility, possibly giving a resolution of
  451. * only 1/100 second. I believe that Portable Standard Lisp typically
  452. * reports user time, which is why I do this. A further nasty here
  453. * is that I am probably compiling this file in ANSI mode, and on
  454. * at least some computers this makes #include <sys/times.h> fairly
  455. * ineffective (ugh), so I declare all the structures and functions I
  456. * want directly (ugh ugh) and hope they are as needed. Consider this
  457. * when you port to a new machine.
  458. */
  459. clock_t read_clock(void)
  460. {
  461. struct my_tms {
  462. clock_t tms_utime;
  463. clock_t tms_stime;
  464. clock_t tms_cutime;
  465. clock_t tms_cstime;
  466. } tmsbuf;
  467. clock_t w1, w2, w3;
  468. extern void times(/*struct my_tms * */);
  469. times(&tmsbuf);
  470. w1 = tmsbuf.tms_utime; /* User time in UNIX_TIMES ticks */
  471. w2 = CLOCKS_PER_SEC;
  472. w3 = UNIX_TIMES;
  473. return (clock_t)((double)w1 * ((double)w2/(double)w3));
  474. }
  475. #endif
  476. void accept_tick()
  477. {
  478. }
  479. #ifdef __kcm
  480. extern int _ttyhandle;
  481. int batchp()
  482. {
  483. return (_ttyhandle != 0);
  484. }
  485. #else
  486. #ifdef NCC_LIB
  487. int batchp()
  488. {
  489. extern int _fisatty(FILE*);
  490. return !_fisatty(stdin);
  491. }
  492. #else
  493. #if BSD_LIB
  494. int batchp()
  495. {
  496. return !isatty(fileno(stdin));
  497. }
  498. #else
  499. #error "Unknown Library type"
  500. #endif /* BSD_LIB */
  501. #endif /* NCC_LIB */
  502. #endif /* __kcm */
  503. /*
  504. * The next procedure is responsible for establishing information about
  505. * where the main checkpoint image should be recovered from, and where
  506. * and fasl files should come from.
  507. */
  508. char *find_image_directory(int argc, char *argv[])
  509. {
  510. char image[LONGEST_LEGAL_FILENAME];
  511. char pgmname[LONGEST_LEGAL_FILENAME];
  512. char *w;
  513. /*
  514. * If the main reduce executable is has a full path-name /xxx/yyy/zzz then
  515. * I will try to make /xxx/yyy/zzz.img the default image file. To do
  516. * this I need to find the full path for the executable. I ATTEMPT to follow
  517. * the bahaviour of "sh", "bash" and "csh". But NOTE WELL that if anybody
  518. * launches this code in an unusual manner (eg using an "exec" style
  519. * function) that could confuse it substantially. Thus users are expected
  520. * EITHER to run this code directly via the shell OR to provide explicit
  521. * command-line options specifying what image files should be used.
  522. */
  523. char *myname = argv[0];
  524. /*
  525. * If the name of the executable starts with a "/" it is already an
  526. * absolute path name. I believe that if the user types (to the shell)
  527. * something like $REDUCE/bin/reduce or ~user/subdir/csl then the environment
  528. * variable or user-name key gets expanded out by the shell before the command
  529. * is actually launched.
  530. */
  531. if (myname == NULL || myname[0] == 0) pgmname[0] = 0;
  532. else if (myname[0] == '/')
  533. {
  534. #ifdef TRACE_NAME
  535. printf("Absolute path executable %s\n", myname);
  536. #endif
  537. strcpy(pgmname, myname);
  538. }
  539. else
  540. { int n;
  541. for (w=myname; *w!=0; w++)
  542. if (*w == '/') break;
  543. /*
  544. * Now if the program name has a "/" anywhere within it it is treated as
  545. * a path starting from the current directory.
  546. */
  547. if (*w == '/')
  548. {
  549. if (myname[0] == '.' && myname[1] == '/') myname += 2;
  550. #ifdef TRACE_NAME
  551. printf("local path with \"/\" in it %s\n", myname);
  552. #endif
  553. n = get_current_directory(pgmname, sizeof(pgmname));
  554. if (n + strlen(myname) + 2 >= sizeof(pgmname) ||
  555. pgmname[0] == 0)
  556. pgmname[0] = 0;
  557. /* Current dir unavailable or full name is too long */
  558. else
  559. { pgmname[n] = '/';
  560. strcpy(&pgmname[n+1], myname);
  561. #ifdef TRACE_NAME
  562. printf("Full name: %s\n", pgmname);
  563. #endif
  564. }
  565. }
  566. else
  567. { char *path = my_getenv("PATH");
  568. /*
  569. * I omit checks for names of shell built-in functions, since my code is
  570. * actually being executed by here. So I get my search path and look
  571. * for an executable file somewhere on it. I note that the shells back this
  572. * up with hash tables, and so in cases where "rehash" might be needed this
  573. * code may become confused.
  574. */
  575. struct stat buf;
  576. uid_t myuid = geteuid(), hisuid;
  577. gid_t mygid = getegid(), hisgid;
  578. int protection;
  579. int ok = 0;
  580. if (path != NULL)
  581. { while (*path != 0)
  582. { while (*path == ':') path++;
  583. n = 0;
  584. while (*path != 0 && *path != ':') pgmname[n++] = *path++;
  585. /* Here I have separated off the next segment of my PATH */
  586. pgmname[n++] = '/';
  587. strcpy(&pgmname[n], myname);
  588. #ifdef TRACE_NAME
  589. printf("Try looking for %s\n", pgmname);
  590. #endif
  591. if (stat(pgmname, &buf) == -1) continue;
  592. hisuid = buf.st_uid;
  593. hisgid = buf.st_gid;
  594. protection = buf.st_mode;
  595. #ifdef TRACE_NAME
  596. printf("uids %d %d gids %d %d protection %o\n",
  597. myuid, hisuid, mygid, hisgid, protection);
  598. #endif
  599. /*
  600. * I now want to check if there is a file of the right name that is
  601. * executable by the current (effective) user.
  602. */
  603. if (protection & S_IXOTH ||
  604. mygid == hisgid && protection & S_IXGRP ||
  605. myuid == hisuid && protection & S_IXUSR)
  606. { ok = 1;
  607. break;
  608. }
  609. }
  610. }
  611. if (ok)
  612. {
  613. #ifdef TRACE_NAME
  614. printf("Success %s\n", pgmname);
  615. #endif
  616. }
  617. else pgmname[0] = 0;
  618. }
  619. }
  620. #ifndef DO_NOT_FOLLOW_SYMBOLIC_LINKS
  621. #ifdef S_ISLNK
  622. /*
  623. * Now if I have a program name I will try to see if it is a symbolic link
  624. * and if so I will follow it.
  625. */
  626. if (pgmname[0] != 0)
  627. { struct stat buf;
  628. int n1;
  629. if (lstat(pgmname, &buf) != -1 &&
  630. S_ISLNK(buf.st_mode) &&
  631. (n1 = readlink(pgmname, image, sizeof(image)-1)) > 0)
  632. { image[n1] = 0;
  633. #ifdef TRACE_NAME
  634. printf("Symbolic link to: %s\n", image);
  635. #endif
  636. strcpy(pgmname, image);
  637. }
  638. }
  639. #endif /* S_ISLNK */
  640. #endif /* DO_NOT_FOLLOW_SYMBOLIC_LINKS */
  641. if (pgmname[0] == 0)
  642. {
  643. /*
  644. * If I could not find the name of the current executable I will
  645. * look in a shell variable "reduceimg". If that is not set I will
  646. * really consider that I have failed and use an image "csl.img" in the
  647. * current dircectory.
  648. */
  649. w = my_getenv("reduceimg");
  650. if (w != NULL) strcpy(image, w);
  651. else strcpy(image, "csl.img");
  652. }
  653. else
  654. { strcpy(image, pgmname);
  655. /*
  656. * If the fully-rooted name of the program was available I just
  657. * append ".img" to get the default image name.
  658. */
  659. w = image + strlen(image);
  660. strcpy(w, ".img");
  661. }
  662. #ifdef OLD_CODE_NOW_REPLACED
  663. /*
  664. * Here I assume Unix, or something sufficiently like it, and
  665. * if the current program is called xxx, then I want an environment
  666. * variable called xxx.img to tell me where to find the image file
  667. * and the fasl directory.
  668. */
  669. #ifdef PUBLIC
  670. strcpy(pgmname, "/usr/local/lib/reduce"); /* fixed name */
  671. w = my_getenv("reduceimg");
  672. if (w != NULL) strcpy(image, w);
  673. else strcpy(image, pgmname);
  674. #else
  675. if (argc > 0 && argv[0] != NULL)
  676. { int i;
  677. w = argv[0];
  678. i = strlen(w);
  679. while (i > 0 && w[i-1] != '/') i--;
  680. sprintf(pgmname, "%s.img", &w[i]); /* final component of argv[0] */
  681. strncpy(program_name, &w[i], 63);
  682. program_name[63] = 0;
  683. }
  684. else strcpy(pgmname, "csl.img"); /* even argv[0] is not available! */
  685. w = my_getenv(pgmname);
  686. #endif
  687. if (w != NULL) strcpy(image, w);
  688. else strcpy(image, pgmname);
  689. #endif /* OLD_CODE_NOW_REPLACED */
  690. /*
  691. * I copy from local vectors into malloc'd space to hand my
  692. * answer back.
  693. */
  694. w = (char *)malloc(1+strlen(image));
  695. /*
  696. * The error exit here seem unsatisfactory...
  697. */
  698. if (w == NULL)
  699. { fprintf(stderr, "\n+++ Panic - run out of space\n");
  700. exit(EXIT_FAILURE);
  701. }
  702. strcpy(w, image);
  703. return w;
  704. }
  705. /*
  706. * The following function controls memory allocation policy
  707. */
  708. int32 ok_to_grab_memory(int32 current)
  709. {
  710. #ifdef COMMON
  711. return current;
  712. #else
  713. return 3*current + 2;
  714. #endif
  715. }
  716. #include "fileops.c"
  717. #include "scandir.c"
  718. /* end of sysunix.c */