home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / emacs / 2841 < prev    next >
Encoding:
Text File  |  1992-08-12  |  15.9 KB  |  689 lines

  1. Newsgroups: comp.emacs
  2. Path: sparky!uunet!usc!rpi!ghost.dsi.unimi.it!itnsg1.cineca.it!lele
  3. From: lele@itnsg1.cineca.it (Lele Gaifax)
  4. Subject: Re: Building Emacs on a NeXT
  5. Message-ID: <1992Aug13.092902.5260@itnsg1.cineca.it>
  6. Organization: Laboratorio di Fisica Computazionale, INFM. Trento Italia
  7. References: <1992Aug12.192846.13997@ctr.columbia.edu>
  8. Date: Thu, 13 Aug 1992 09:29:02 GMT
  9. Lines: 678
  10.  
  11. Here is the patches I used to compile 18.58 on my NeXTstation with NeXTstep 2.2.
  12. I extracted them from an emacs-18.57.tar.Z available on several NeXT archives.
  13. Apply it to a fresh 18.58 distribution, modify src/config.h to use s-mach.h and
  14. m-NeXT.h, then do a make... That's it.
  15. I did not write a single bit of this code, I just produced it diff-ing the
  16. 18.57 sources against 18.58....
  17. bye, lele.
  18.  
  19. --- src/emacs.c.orig    Sat Jun 15 04:52:00 1991
  20. +++ src/emacs.c    Sat Jun 15 04:56:55 1991
  21. @@ -178,6 +178,9 @@
  22.  #endif /* LINK_CRTL_SHARE */
  23.  #endif /* VMS */
  24.  
  25. +#ifdef NeXT
  26. +int malloc_cookie;
  27. +#endif /* NeXT */
  28.  /* ARGSUSED */
  29.  main (argc, argv, envp)
  30.       int argc;
  31. @@ -187,6 +190,13 @@
  32.    int skip_args = 0;
  33.    extern int errno;
  34.    extern void malloc_warning ();
  35. +
  36. +#ifdef NeXT
  37. +   /* this helps out unexNeXT.c */
  38. +   if (initialized)
  39. +     if (malloc_jumpstart(malloc_cookie) != 0)
  40. +       printf("malloc jumpstart failed!\n");
  41. +#endif /* NeXT */
  42.  
  43.  /* Map in shared memory, if we are using that.  */
  44.  #ifdef HAVE_SHM
  45. --- src/fns.c.orig    Sat Jun 15 04:52:03 1991
  46. +++ src/fns.c    Sat Jun 15 04:53:01 1991
  47. @@ -1204,8 +1204,13 @@
  48.        nl[0].n_un.n_name = LDAV_SYMBOL;
  49.        nl[1].n_un.n_name = 0;
  50.  #else /* not convex */
  51. +#ifdef NEXT_KERNEL_FILE
  52. +      nl[0].n_un.n_name = LDAV_SYMBOL;
  53. +      nl[1].n_un.n_name = 0;
  54. +#else
  55.        nl[0].n_name = LDAV_SYMBOL;
  56.        nl[1].n_name = 0;
  57. +#endif /* not NEXT_KERNEL_FILE */
  58.  #endif /* not convex */
  59.  #endif /* NLIST_STRUCT */
  60.  
  61. @@ -1217,7 +1222,11 @@
  62.          nl[0].n_value &= 0x7fffffff;
  63.      }
  64.  #else
  65. +#ifdef NEXT_KERNEL_FILE
  66. +      nlist (NEXT_KERNEL_FILE, nl);
  67. +#else
  68.        nlist (KERNEL_FILE, nl);
  69. +#endif
  70.  #endif /* IRIS */
  71.  
  72.  #ifdef FIXUP_KERNEL_SYMBOL_ADDR
  73. --- src/sysdep.c.orig    Sat Jun 15 04:52:04 1991
  74. +++ src/sysdep.c    Sat Jun 15 04:53:03 1991
  75. @@ -1472,8 +1472,12 @@
  76.    extern csrt();
  77.    return ((char *) csrt);
  78.  #else /* not GOULD */
  79. +#ifdef NeXT
  80. +  return ((char *)0); /* wrong: but nobody uses it anyway */
  81. +#else
  82.    extern int _start ();
  83.    return ((char *) _start);
  84. +#endif /* NeXT */
  85.  #endif /* GOULD */
  86.  #endif /* TEXT_START */
  87.  }
  88. @@ -1531,7 +1535,13 @@
  89.  #ifdef TEXT_END
  90.    return ((char *) TEXT_END);
  91.  #else
  92. +#ifdef __NeXT__
  93. +  static int etext;
  94. +
  95. +  etext = get_etext();
  96. +#else
  97.    extern int etext;
  98. +#endif
  99.    return ((char *) &etext);
  100.  #endif
  101.  }
  102. @@ -1547,7 +1557,13 @@
  103.  #ifdef DATA_END
  104.    return ((char *) DATA_END);
  105.  #else
  106. +#ifdef __NeXT__
  107. +  static int edata;
  108. +
  109. +  edata = get_edata();
  110. +#else
  111.    extern int edata;
  112. +#endif
  113.    return ((char *) &edata);
  114.  #endif
  115.  }
  116. --- src/x11term.c.orig    Sat Jun 15 04:52:02 1991
  117. +++ src/x11term.c    Sat Jun 15 04:53:05 1991
  118. @@ -273,7 +273,9 @@
  119.  
  120.  static void x_init_1 ();
  121.  
  122. +#ifndef rindex
  123.  char *rindex();
  124. +#endif /* rindex */
  125.  
  126.  /* HLmode -- Changes the GX function for output strings.  Could be used to
  127.   * change font.  Check an XText library function call.
  128. --- /dev/null    Wed Jul 15 18:14:58 1992
  129. +++ src/s-mach.h    Sat Jun 15 04:58:01 1991
  130. @@ -0,0 +1,28 @@
  131. +/* Definitions file for GNU Emacs running on bsd 4.3
  132. +   Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  133. +
  134. +This file is part of GNU Emacs.
  135. +
  136. +GNU Emacs is distributed in the hope that it will be useful,
  137. +but WITHOUT ANY WARRANTY.  No author or distributor
  138. +accepts responsibility to anyone for the consequences of using it
  139. +or for whether it serves any particular purpose or works at all,
  140. +unless he says so in writing.  Refer to the GNU Emacs General Public
  141. +License for full details.
  142. +
  143. +Everyone is granted permission to copy, modify and redistribute
  144. +GNU Emacs, but only under the conditions described in the
  145. +GNU Emacs General Public License.   A copy of this license is
  146. +supposed to have been given to you along with GNU Emacs so you
  147. +can know your rights and responsibilities.  It should be in a
  148. +file named COPYING.  Among other things, the copyright notice
  149. +and this notice must be preserved on all copies.  */
  150. +
  151. +
  152. +#include "s-bsd4-3.h"
  153. +#define NEXT_KERNEL_FILE "/mach"
  154. +/* #define NEXT_KERNEL_FILE "/vmunix" */
  155. +#undef KERNEL_FILE
  156. +
  157. +#define LD_SWITCH_SYSTEM -X -noseglinkedit
  158. +
  159. --- /dev/null    Wed Jul 15 18:14:58 1992
  160. +++ src/m-NeXT.h    Sat Jun 15 04:52:36 1991
  161. @@ -0,0 +1,98 @@
  162. +/* Configuration file for the NeXT machine. */
  163. +/*    Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  164. +
  165. +This file is part of GNU Emacs.
  166. +
  167. +GNU Emacs is distributed in the hope that it will be useful,
  168. +but WITHOUT ANY WARRANTY.  No author or distributor
  169. +accepts responsibility to anyone for the consequences of using it
  170. +or for whether it serves any particular purpose or works at all,
  171. +unless he says so in writing.  Refer to the GNU Emacs General Public
  172. +License for full details.
  173. +
  174. +Everyone is granted permission to copy, modify and redistribute
  175. +GNU Emacs, but only under the conditions described in the
  176. +GNU Emacs General Public License.   A copy of this license is
  177. +supposed to have been given to you along with GNU Emacs so you
  178. +can know your rights and responsibilities.  It should be in a
  179. +file named COPYING.  Among other things, the copyright notice
  180. +and this notice must be preserved on all copies.  */
  181. +
  182. +
  183. +
  184. +
  185. +
  186. +
  187. +
  188. +/* The following three symbols give information on
  189. + the size of various data types.  */
  190. +
  191. +#define SHORTBITS 16        /* Number of bits in a short */
  192. +
  193. +#define INTBITS 32        /* Number of bits in an int */
  194. +
  195. +#define LONGBITS 32        /* Number of bits in a long */
  196. +
  197. +/* 68000 has lowest-numbered byte as most significant */
  198. +
  199. +#define BIG_ENDIAN
  200. +
  201. +/* Define how to take a char and sign-extend into an int.
  202. +   On machines where char is signed, this is a no-op.  */
  203. +
  204. +#define SIGN_EXTEND_CHAR(c) (c)
  205. +
  206. +/* Say this machine is a 68000 */
  207. +
  208. +#ifndef m68000
  209. +#define m68000
  210. +#endif
  211. +
  212. +/* Use type int rather than a union, to represent Lisp_Object */
  213. +
  214. +#define NO_UNION_TYPE
  215. +
  216. +/* XINT must explicitly sign-extend */
  217. +
  218. +#define EXPLICIT_SIGN_EXTEND
  219. +
  220. +#define LIB_STANDARD -lsys_s
  221. +
  222. +/* Data type of load average, as read out of kmem.  */
  223. +
  224. +#define LOAD_AVE_TYPE long
  225. +
  226. +/* Convert that into an integer that is 100 for a load average of 1.0  */
  227. +
  228. +#define environ _environ
  229. +
  230. +#define NO_REMAP
  231. +#define UNEXEC unexNeXT.o
  232. +
  233. +#ifndef FSCALE
  234. +#define FSCALE 256
  235. +#endif
  236. +#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
  237. +
  238. +/* Say that the text segment of a.out includes the header;
  239. +   the header actually occupies the first few bytes of the text segment
  240. +   and is counted in hdr.a_text.  */
  241. +
  242. +#define A_TEXT_OFFSET(HDR) sizeof (HDR)
  243. +
  244. +/* #define _setjmp setjmp */
  245. +/* #define _longjmp longjmp */
  246. +
  247. +/* Use dk.h, not dkstat.h, in loadst.c.  */
  248. +
  249. +#define DK_HEADER_FILE
  250. +/* Mask for address bits within a memory segment */
  251. +
  252. +#define SEGSIZ 0x20000
  253. +#define SEGMENT_MASK (SEGSIZ - 1)
  254. +
  255. +#define HAVE_ALLOCA
  256. +
  257. +#define SYSTEM_MALLOC
  258. +
  259. +#define HAVE_UNIX_DOMAIN
  260. --- /dev/null    Wed Jul 15 18:14:58 1992
  261. +++ src/unexNeXT.c    Sat Jun 15 04:52:35 1991
  262. @@ -0,0 +1,422 @@
  263. +/*
  264. + * unexec for the NeXT Mach environment.
  265. + *
  266. + * Bradley Taylor (btaylor@NeXT.COM) 
  267. + * February 28, 1990
  268. + */
  269. +#ifdef NeXT
  270. +
  271. +#undef __STRICT_BSD__
  272. +
  273. +#include <stdio.h>
  274. +#include <stdlib.h>
  275. +#include <stdarg.h>
  276. +#include <mach.h>
  277. +#include <sys/loader.h>
  278. +#include <sys/file.h>
  279. +#include <sys/stat.h>
  280. +#include <libc.h>
  281. +
  282. +
  283. +extern struct section *getsectbyname(char *, char *);
  284. +
  285. +/*
  286. + * Kludge: we don't expect any program data beyond VM_HIGHDATA
  287. + * What is really needed is a way to find out from malloc() which
  288. + * pages it vm_allocated and write only those out into the data segment.
  289. + *
  290. + * This kludge may break when we stop using fixed virtual address
  291. + * shared libraries. Actually, emacs will probably continue working, but be 
  292. + * much larger on disk than it needs to be (because non-malloced data will
  293. + * be in the file).
  294. + */
  295. +static const unsigned VM_HIGHDATA = 0x2000000;
  296. +
  297. +typedef struct region_t {
  298. +    vm_address_t address;
  299. +    vm_size_t size;
  300. +    vm_prot_t protection;
  301. +    vm_prot_t max_protection;
  302. +    vm_inherit_t inheritance;
  303. +    boolean_t shared;
  304. +    port_t object_name;
  305. +    vm_offset_t offset;
  306. +} region_t;
  307. +
  308. +
  309. +static void
  310. +grow(
  311. +     struct load_command ***the_commands,
  312. +     unsigned *the_commands_len
  313. +     )
  314. +{
  315. +    if (*the_commands == NULL) {
  316. +        *the_commands_len = 1;
  317. +        *the_commands = malloc(sizeof(*the_commands));
  318. +    } else {
  319. +        (*the_commands_len)++;
  320. +        *the_commands = realloc(*the_commands, 
  321. +                    (*the_commands_len *
  322. +                     sizeof(**the_commands)));
  323. +    }
  324. +}
  325. +
  326. +
  327. +static void
  328. +save_command(
  329. +         struct load_command *command,
  330. +         struct load_command ***the_commands,
  331. +         unsigned *the_commands_len
  332. +         )
  333. +{
  334. +    struct load_command **tmp;
  335. +
  336. +    grow(the_commands, the_commands_len);
  337. +    tmp = &(*the_commands)[*the_commands_len - 1];
  338. +    *tmp = malloc(command->cmdsize);
  339. +    bcopy(command, *tmp, command->cmdsize);
  340. +}
  341. +
  342. +static void
  343. +fatal_unexec(char *format, ...)
  344. +{
  345. +    va_list ap;
  346. +
  347. +    va_start(ap, format);
  348. +    fprintf(stderr, "unexec: ");
  349. +    vfprintf(stderr, format, ap);
  350. +    fprintf(stderr, "\n");
  351. +    va_end(ap);
  352. +}
  353. +
  354. +static int
  355. +read_macho(
  356. +       int fd,
  357. +       struct mach_header *the_header,
  358. +       struct load_command ***the_commands,
  359. +       unsigned *the_commands_len
  360. +       )
  361. +{
  362. +    struct load_command command;
  363. +    struct load_command *buf;
  364. +    int i;
  365. +    int size;
  366. +
  367. +    if (read(fd, the_header, sizeof(*the_header)) != sizeof(*the_header)) {
  368. +        fatal_unexec("cannot read macho header");
  369. +        return (0);
  370. +    }
  371. +    for (i = 0; i < the_header->ncmds; i++) {
  372. +        if (read(fd, &command, sizeof(struct load_command)) != 
  373. +            sizeof(struct load_command)) {
  374. +              fatal_unexec("cannot read macho load command header");
  375. +            return (0);
  376. +        }
  377. +        size = command.cmdsize - sizeof(struct load_command);
  378. +        if (size < 0) {
  379. +              fatal_unexec("bogus load command size");
  380. +            return (0);
  381. +        }
  382. +        buf = malloc(command.cmdsize);
  383. +        buf->cmd = command.cmd;
  384. +        buf->cmdsize = command.cmdsize;
  385. +        if (read(fd, ((char *)buf + 
  386. +                  sizeof(struct load_command)), 
  387. +             size) != size) {
  388. +              fatal_unexec("cannot read load command data");
  389. +            return (0);
  390. +        }
  391. +        save_command(buf, the_commands, the_commands_len);
  392. +    }
  393. +    return (1);
  394. +}
  395. +
  396. +static int
  397. +filldatagap(
  398. +        vm_address_t start_address,
  399. +        vm_size_t *size,
  400. +        vm_address_t end_address
  401. +        )
  402. +{
  403. +    vm_address_t address;
  404. +    vm_size_t gapsize;
  405. +
  406. +    address = (start_address + *size);
  407. +    gapsize = end_address - address;
  408. +    *size += gapsize;
  409. +    if (vm_allocate(task_self(), &address, gapsize,
  410. +            FALSE) != KERN_SUCCESS) {
  411. +        fatal_unexec("cannot vm_allocate");
  412. +            return (0);
  413. +    }
  414. +    return (1);
  415. +}
  416. +
  417. +static int
  418. +get_data_region(
  419. +        vm_address_t *address,
  420. +        vm_size_t *size
  421. +        )
  422. +{
  423. +    region_t region;
  424. +    kern_return_t ret;
  425. +    struct section *sect;
  426. +
  427. +    sect = getsectbyname(SEG_DATA, SECT_DATA);
  428. +    region.address = 0;
  429. +    *address = 0;
  430. +    for (;;) {
  431. +        ret = vm_region(task_self(), 
  432. +                ®ion.address, 
  433. +                ®ion.size, 
  434. +                ®ion.protection, 
  435. +                ®ion.max_protection, 
  436. +                ®ion.inheritance,
  437. +                ®ion.shared, 
  438. +                ®ion.object_name, 
  439. +                ®ion.offset);
  440. +        if (ret != KERN_SUCCESS || region.address >= VM_HIGHDATA) {
  441. +            break;
  442. +        }
  443. +        if (*address != 0) {
  444. +            if (region.address > *address + *size) {
  445. +                if (!filldatagap(*address, size, 
  446. +                         region.address)) {
  447. +                    return (0);
  448. +                }
  449. +            } 
  450. +            *size += region.size;
  451. +        } else {
  452. +            if (region.address == sect->addr) {
  453. +                *address = region.address;
  454. +                *size = region.size;
  455. +            } 
  456. +        }
  457. +        region.address += region.size;
  458. +    }
  459. +    return (1);
  460. +}
  461. +
  462. +static char *
  463. +my_malloc(
  464. +      vm_size_t size
  465. +      )
  466. +{
  467. +    vm_address_t address;
  468. +
  469. +    if (vm_allocate(task_self(), &address, size, TRUE) != KERN_SUCCESS) {
  470. +        return (NULL);
  471. +    }
  472. +    return ((char *)address);
  473. +}
  474. +
  475. +static void
  476. +my_free(
  477. +    char *buf,
  478. +    vm_size_t size
  479. +    )
  480. +{
  481. +    vm_deallocate(task_self(), (vm_address_t)buf, size);
  482. +}
  483. +
  484. +static int
  485. +unexec_doit(
  486. +        int infd,
  487. +        int outfd
  488. +        )
  489. +{
  490. +    int i;
  491. +    struct load_command **the_commands = NULL;
  492. +    unsigned the_commands_len;
  493. +    struct mach_header the_header;
  494. +    int fgrowth;
  495. +    int fdatastart;
  496. +    int fdatasize;
  497. +    int size;
  498. +    struct stat st;
  499. +    char *buf;
  500. +    vm_address_t data_address;
  501. +    vm_size_t data_size;
  502. +
  503. +    struct segment_command *segment;
  504. +
  505. +    if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) {
  506. +        return (0);
  507. +    }
  508. +
  509. +
  510. +    {
  511. +      extern int malloc_cookie;
  512. +      malloc_cookie = malloc_freezedry();
  513. +    }
  514. +    if (!get_data_region(&data_address, &data_size)) {
  515. +        return (0);
  516. +    }
  517. +
  518. +
  519. +    /*
  520. +     * DO NOT USE MALLOC IN THIS SECTION
  521. +     */
  522. +    {
  523. +        /*
  524. +         * Fix offsets
  525. +         */
  526. +        for (i = 0; i < the_commands_len; i++) {
  527. +            switch (the_commands[i]->cmd) {
  528. +            case LC_SEGMENT:
  529. +                segment = ((struct segment_command *)
  530. +                       the_commands[i]);
  531. +                if (strcmp(segment->segname, SEG_DATA) == 0) {
  532. +                    fdatastart = segment->fileoff;
  533. +                    fdatasize = segment->filesize;
  534. +                    fgrowth = (data_size - 
  535. +                           segment->filesize);
  536. +                    segment->vmsize = data_size;
  537. +                    segment->filesize = data_size;
  538. +                }
  539. +                break;
  540. +            case LC_SYMTAB:
  541. +                ((struct symtab_command *)
  542. +                 the_commands[i])->symoff += fgrowth;
  543. +                ((struct symtab_command *)
  544. +                 the_commands[i])->stroff += fgrowth;
  545. +                break;
  546. +            case LC_SYMSEG:
  547. +                ((struct symseg_command *)
  548. +                 the_commands[i])->offset += fgrowth;
  549. +                break;
  550. +            default:
  551. +                break;
  552. +            }
  553. +        }
  554. +        
  555. +        /*
  556. +         * Write header
  557. +         */
  558. +        if (write(outfd, &the_header, 
  559. +              sizeof(the_header)) != sizeof(the_header)) {
  560. +            fatal_unexec("cannot write output file");
  561. +            return (0);
  562. +        }
  563. +        
  564. +        /*
  565. +         * Write commands
  566. +         */
  567. +        for (i = 0; i < the_commands_len; i++) {
  568. +            if (write(outfd, the_commands[i], 
  569. +                  the_commands[i]->cmdsize) != 
  570. +                the_commands[i]->cmdsize) {
  571. +                  fatal_unexec("cannot write output file");
  572. +                return (0);
  573. +            }
  574. +        }
  575. +        
  576. +        /*
  577. +         * Write original text
  578. +         */
  579. +        if (lseek(infd, the_header.sizeofcmds + sizeof(the_header), 
  580. +              L_SET) < 0) {
  581. +              fatal_unexec("cannot seek input file");
  582. +            return (0);
  583. +        }
  584. +        size = fdatastart - (sizeof(the_header) + 
  585. +                     the_header.sizeofcmds);
  586. +        buf = my_malloc(size);
  587. +        if (read(infd, buf, size) != size) {
  588. +            my_free(buf, size);
  589. +              fatal_unexec("cannot read input file");
  590. +        }
  591. +        if (write(outfd, buf, size) != size) {
  592. +            my_free(buf, size);
  593. +            fatal_unexec("cannot write output file");
  594. +            return (0);
  595. +        }
  596. +        my_free(buf, size);
  597. +        
  598. +        
  599. +        /*
  600. +         * Write new data
  601. +         */
  602. +        if (write(outfd, (char *)data_address, 
  603. +              data_size) != data_size) {
  604. +            fatal_unexec("cannot write output file");
  605. +            return (0);
  606. +        }
  607. +        
  608. +    }
  609. +
  610. +    /*
  611. +     * OKAY TO USE MALLOC NOW
  612. +     */
  613. +
  614. +    /*
  615. +     * Write rest of file
  616. +     */
  617. +    fstat(infd, &st);
  618. +    if (lseek(infd, fdatasize, L_INCR) < 0) {
  619. +        fatal_unexec("cannot seek input file");
  620. +        return (0);
  621. +    }
  622. +    size = st.st_size - lseek(infd, 0, L_INCR);
  623. +
  624. +    buf = malloc(size);
  625. +    if (read(infd, buf, size) != size) {
  626. +        free(buf);
  627. +        fatal_unexec("cannot read input file");
  628. +        return (0);
  629. +    }
  630. +    if (write(outfd, buf, size) != size) {
  631. +        free(buf);
  632. +        fatal_unexec("cannot write output file");
  633. +        return (0);
  634. +    }
  635. +    free(buf);
  636. +    return (1);
  637. +}
  638. +
  639. +void
  640. +unexec(
  641. +       char *outfile,
  642. +       char *infile
  643. +       )
  644. +{
  645. +    int infd;
  646. +    int outfd;
  647. +    char tmpbuf[L_tmpnam];
  648. +    char *tmpfile;
  649. +
  650. +    infd = open(infile, O_RDONLY, 0);
  651. +    if (infd < 0) {
  652. +          fatal_unexec("cannot open input file `%s'", infile);
  653. +        exit(1);
  654. +    }
  655. +    
  656. +    tmpnam(tmpbuf);
  657. +    tmpfile = rindex(tmpbuf, '/');
  658. +    if (tmpfile == NULL) {
  659. +        tmpfile = tmpbuf;
  660. +    } else {
  661. +        tmpfile++;
  662. +    }
  663. +    outfd = open(tmpfile, O_WRONLY|O_TRUNC|O_CREAT, 0755);
  664. +    if (outfd < 0) {
  665. +        close(infd);
  666. +        fatal_unexec("cannot open tmp file `%s'", tmpfile);
  667. +        exit(1);
  668. +    }
  669. +    if (!unexec_doit(infd, outfd)) {
  670. +        close(infd);
  671. +        close(outfd);
  672. +        unlink(tmpfile);
  673. +        exit(1);
  674. +    }
  675. +    close(infd);
  676. +    close(outfd);
  677. +    if (rename(tmpfile, outfile) < 0) {
  678. +        unlink(tmpfile);
  679. +        fatal_unexec("cannot rename `%s' to `%s'", tmpfile, outfile);
  680. +        exit(1);
  681. +    }
  682. +}
  683. +#endif
  684. +
  685. -- 
  686. Lele Gaifax - lele@itnsg1.cineca.it
  687. Sicuramente i cattivi hanno scoperto qualche cosa che i buoni ignorano.
  688.                         - Woody Allen
  689.