home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / reviewed / volume02 / malloclb / part03 < prev    next >
Encoding:
Internet Message Format  |  1992-03-31  |  56.7 KB

  1. From: Conor P. Cahill <cpcahil%virtech@uunet.UU.NET>
  2. Subject: v02i004: malloclib - Malloc Debugging Library, Part03/05
  3. Newsgroups: comp.sources.reviewed
  4. Approved: csr@calvin.dgbt.doc.ca
  5.  
  6. Submitted-by: Conor P. Cahill <cpcahil%virtech@uunet.UU.NET>
  7. Posting-number: Volume 2, Issue 4
  8. Archive-name: malloclib/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 5)."
  17. # Contents:  malloc.c malloc_chk.c malloc_chn.c mallocint.h mallopt.c
  18. #   testerr.c tostring.c
  19. # Wrapped by cpcahil@virtech on Tue Jan 28 16:46:34 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'malloc.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'malloc.c'\"
  23. else
  24. echo shar: Extracting \"'malloc.c'\" \(27329 characters\)
  25. sed "s/^X//" >'malloc.c' <<'END_OF_FILE'
  26. X/*
  27. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  28. X * You may copy, distribute, and use this software as long as this
  29. X * copyright statement is not removed.
  30. X */
  31. X#include <stdio.h>
  32. X#include <fcntl.h>
  33. X#include <signal.h>
  34. X#include <sys/wait.h>
  35. X
  36. X#include "mallocint.h"
  37. X#include "tostring.h"
  38. X
  39. X#ifndef lint
  40. Xstatic char rcs_header[] = "$Id: malloc.c,v 1.19 1992/01/28 16:35:37 cpcahil Exp $";
  41. X#endif
  42. X
  43. Xint          in_malloc_code;
  44. Xint          malloc_checking;
  45. XDATATYPE    * malloc_data_start;
  46. XDATATYPE    * malloc_data_end;
  47. Xstruct mlist     * malloc_end;
  48. Xint          malloc_errfd = 2;
  49. Xint          malloc_errno;
  50. Xint          malloc_fatal_level = M_HANDLE_ABORT;
  51. Xint          malloc_fill_area = 1;
  52. Xstruct mlist    * malloc_freelist;
  53. Xlong          malloc_hist_id = 0;
  54. Xint          malloc_lowfrag = 0;
  55. Xstruct mlist      malloc_start;
  56. Xint          malloc_warn_level;
  57. X
  58. X/*
  59. X * perform string copy, but make sure that we don't go beyond the end of the
  60. X * buffer (leaving room for trailing info (5 bytes) like the return and a null
  61. X */
  62. X#define COPY(s,t,buf,len)    while( (*(s) = *((t)++) ) \
  63. X                       && ( (s) < ((buf)+(len)-5) ) ) { (s)++; }
  64. X
  65. X#define DUMP_PTR    0
  66. X#define DUMP_NEXT    1
  67. X#define DUMP_PREV    2
  68. X
  69. X#define ERRBUFSIZE    1024
  70. X
  71. X/*
  72. X * Function:    malloc()
  73. X *
  74. X * Purpose:    low-level interface to the debug malloc lib.  This should only
  75. X *         be called from code that is not recompilable.  The recompilable
  76. X *        code should include malloc.h and therefore its calls to malloc
  77. X *        will be #defined to be calls to debug_malloc with the
  78. X *        appropriate arguments.
  79. X *
  80. X * Arguments:    size    - size of data area needed
  81. X *
  82. X * Returns:    whatever debug_malloc returns.
  83. X *
  84. X * Narrative:
  85. X *
  86. X */
  87. XDATATYPE *
  88. Xmalloc(size)
  89. X    SIZETYPE      size;
  90. X{
  91. X    return( debug_malloc(NULL,-1,size) );
  92. X}
  93. X
  94. X/*
  95. X * Function:    debug_malloc()
  96. X *
  97. X * Purpose:    the real memory allocator
  98. X *
  99. X * Arguments:    size    - size of data area needed
  100. X *
  101. X * Returns:    pointer to allocated area, or NULL if unable
  102. X *        to allocate addtional data.
  103. X *
  104. X * Narrative:
  105. X *
  106. X */
  107. XDATATYPE *
  108. Xdebug_malloc(file,line,size)
  109. X    const char    * file;
  110. X    int          line;
  111. X    SIZETYPE      size;
  112. X{
  113. X    static long          call_counter = 0;
  114. X    SIZETYPE          fit;
  115. X    const char        * func = "malloc";
  116. X    char            * getenv();
  117. X    SIZETYPE          lastfit;
  118. X    struct mlist        * lastptr;
  119. X    SIZETYPE          need;
  120. X    register struct mlist    * oldptr;
  121. X    register struct mlist    * ptr;
  122. X    SIZETYPE          r_size;
  123. X    DATATYPE        * sbrk();
  124. X
  125. X    MALLOC_INIT();
  126. X
  127. X    /*
  128. X     * increment the counter for the number of calls to this func.
  129. X     */
  130. X    call_counter++;
  131. X
  132. X    /*
  133. X     * If malloc chain checking is on, go do it.
  134. X     */
  135. X    if( malloc_checking )
  136. X    {
  137. X        if( DBFmalloc_chain_check(func,file,line,1) != 0 )
  138. X        {
  139. X            return(NULL);
  140. X        }
  141. X    }
  142. X
  143. X    /*
  144. X     * save the original requested size;
  145. X     */
  146. X    r_size = size;
  147. X
  148. X    /*
  149. X     * always make sure there is at least on extra byte in the malloc
  150. X     * area so that we can verify that the user does not overrun the
  151. X     * data area.
  152. X     */
  153. X    size++;
  154. X
  155. X    /*
  156. X     * Now look for a free area of memory of size bytes...
  157. X     */
  158. X    oldptr = NULL;
  159. X    ptr = malloc_freelist;
  160. X
  161. X    /*
  162. X     * if low fragmentation has been turned on, look for a best fit
  163. X     * segment (otherwise, for performance reasons, we will look for
  164. X     * a first fit)
  165. X     */
  166. X    if( malloc_lowfrag )
  167. X    {  
  168. X        lastfit = 0;
  169. X        lastptr = NULL;
  170. X        /*
  171. X         * until we run out of segments, or find an exact match
  172. X         */
  173. X        for(; (ptr != NULL) && (ptr->s.size != size); ptr=ptr->freenext)
  174. X        {
  175. X            /*
  176. X             * quick check to make sure our free-list hasn't been
  177. X             * broken.
  178. X             */
  179. X            if((oldptr != NULL) && (ptr->freeprev != oldptr) )
  180. X            {
  181. X                malloc_errno = M_CODE_CHAIN_BROKE;
  182. X                malloc_fatal(func,file,line,oldptr);
  183. X                return(NULL);
  184. X            }
  185. X            /*
  186. X             * if this segment is big enough for our needs
  187. X             */
  188. X            if( ptr->s.size > size )
  189. X            {
  190. X                /*
  191. X                  * calculate how close we fit.  Note that this
  192. X                 * will never be zero because if it was, we 
  193. X                  * would have broken out of the loop.
  194. X                 */
  195. X                fit = ptr->s.size - size;
  196. X                /*
  197. X                  * if this is the first one we fit int, or
  198. X                 * if this a closer fit
  199. X                  */
  200. X                if( (lastfit == 0) || (fit < lastfit) )
  201. X                {
  202. X                    lastptr = ptr;
  203. X                    lastfit = fit;
  204. X                }
  205. X            }
  206. X    
  207. X            oldptr = ptr;
  208. X
  209. X        } /* for(... */
  210. X
  211. X        /*
  212. X         * if we ran out of entries, but we did find one that fit
  213. X         * our needs, us the one we found.
  214. X         */
  215. X        if( (ptr == NULL) && (lastptr != NULL) )
  216. X        {
  217. X            ptr = lastptr;
  218. X        }
  219. X    }
  220. X    else
  221. X    {
  222. X        /*
  223. X         * until we run out of free entries, or find an entry that has
  224. X         * enough room
  225. X         */
  226. X        for( ; (ptr != NULL) && (ptr->s.size < size); ptr=ptr->freenext)
  227. X        {
  228. X            if((oldptr != NULL) && (ptr->freeprev != oldptr) )
  229. X            {
  230. X                malloc_errno = M_CODE_CHAIN_BROKE;
  231. X                malloc_fatal(func,file,line,oldptr);
  232. X                return(NULL);
  233. X            }
  234. X
  235. X            oldptr = ptr;
  236. X
  237. X        } /* for(... */
  238. X    }
  239. X
  240. X    /*
  241. X     * If ptr is null, we have run out of memory and must sbrk more
  242. X     */
  243. X    if( ptr == NULL )
  244. X    {
  245. X        /*
  246. X         * calculate how much space we need.  If they ask for more
  247. X         * than 100k, get exactly what they want.  Otherwise get
  248. X         * twice what they ask for so that we are ready for the
  249. X         * next allocation they ask for
  250. X          */
  251. X        need = size + M_SIZE;
  252. X        if( size < 100*1024 )
  253. X        {
  254. X            need <<= 1;
  255. X        }
  256. X
  257. X        /*
  258. X         * if the need is less than the minimum block size,
  259. X         *     get the minimum block size
  260. X          */
  261. X        if( need < M_BLOCKSIZE )
  262. X        {
  263. X            need = M_BLOCKSIZE;
  264. X        }
  265. X        /*
  266. X         * else if the need is not an even multiple of the block size,
  267. X         *     round it up to an even multiple
  268. X         */
  269. X        else if( need & (M_BLOCKSIZE-1) )
  270. X        {
  271. X            need &= ~(M_BLOCKSIZE-1);
  272. X            need += M_BLOCKSIZE;
  273. X        }
  274. X
  275. X        /*
  276. X         * get the space from the os
  277. X          */
  278. X        ptr = (struct mlist *) sbrk((int)need);
  279. X
  280. X        /*
  281. X         * if we failed to get the space, tell the user about it
  282. X         */
  283. X        if( ptr == (struct mlist *) -1 )
  284. X        {
  285. X            malloc_errno = M_CODE_NOMORE_MEM;
  286. X            malloc_fatal(func,file,line, (struct mlist *)NULL);
  287. X            return(NULL);
  288. X        }
  289. X
  290. X        /*
  291. X         * mark our end point
  292. X         */
  293. X        malloc_data_end = sbrk((int)0);
  294. X
  295. X        /*
  296. X         * hook the new segment into the malloc chain
  297. X         */
  298. X        ptr->prev     = malloc_end;
  299. X        ptr->next     = (struct mlist *) 0;
  300. X        ptr->freenext = (struct mlist *) 0;
  301. X        ptr->s.size   = need - M_SIZE;
  302. X        ptr->flag     = M_MAGIC;
  303. X
  304. X        malloc_end->next = ptr;
  305. X        malloc_end = ptr;
  306. X
  307. X    } /* if( ptr ==... */
  308. X    /*
  309. X     * else we found a free slot that has enough room,
  310. X     *    so take it off the free list
  311. X     */
  312. X    else
  313. X    {
  314. X        /*
  315. X         * if this module is already in use
  316. X         */
  317. X        if( (ptr->flag & M_INUSE) != 0 )
  318. X        {
  319. X            malloc_errno = M_CODE_FREELIST_BAD;
  320. X            malloc_fatal(func,file,line,ptr);
  321. X            return(NULL);
  322. X        }
  323. X        
  324. X        /*
  325. X         * remove the segment from the free list
  326. X         */
  327. X        malloc_freeseg(M_FREE_REMOVE,ptr);
  328. X    }
  329. X        
  330. X
  331. X    /*
  332. X     * Now ptr points to a memory location that can store
  333. X     * this data, so lets go to work.
  334. X     */
  335. X
  336. X    ptr->r_size = size;        /* save requested size    */
  337. X    ptr->flag |= M_INUSE;
  338. X
  339. X    /*
  340. X     * split off unneeded data area in this block, if possible...
  341. X     */
  342. X    malloc_split(ptr);
  343. X
  344. X    /*
  345. X     * save the real requested size
  346. X     */
  347. X    ptr->r_size = r_size;
  348. X
  349. X    /*
  350. X     * just to make sure that noone is misusing malloced
  351. X     * memory without initializing it, lets set it to
  352. X     * all '\01's.  We call local_memset() because memset()
  353. X     * may be checking for malloc'd ptrs and this isn't
  354. X     * a malloc'd ptr yet.
  355. X     */
  356. X    if( malloc_fill_area )
  357. X    {
  358. X        malloc_aligned_memset(ptr->data,M_FILL,(int)ptr->s.size);
  359. X    }
  360. X
  361. X    /*
  362. X     * store the identification information
  363. X     */
  364. X    ptr->file    = file;
  365. X    ptr->line    = line;
  366. X    ptr->id      = call_counter;
  367. X    ptr->hist_id = malloc_hist_id++;
  368. X
  369. X    SETTYPE(ptr,M_T_MALLOC);
  370. X
  371. X    /*
  372. X     * return the pointer to the data area for the user.
  373. X     */
  374. X    return( ptr->data );
  375. X
  376. X
  377. X} /* malloc(... */
  378. X
  379. X/*
  380. X * Function:    malloc_split()
  381. X *
  382. X * Purpose:    to split a malloc segment if there is enough room at the
  383. X *        end of the segment that isn't being used
  384. X *
  385. X * Arguments:    ptr    - pointer to segment to split
  386. X *
  387. X * Returns:    nothing of any use.
  388. X *
  389. X * Narrative:
  390. X *        get the needed size of the module
  391. X *         round the size up to appropriat boundry
  392. X *        calculate amount of left over space
  393. X *        if there is enough left over space
  394. X *            create new malloc block out of remainder
  395. X *            if next block is free 
  396. X *            join the two blocks together
  397. X *            fill new empty block with free space filler
  398. X *             re-adjust pointers and size of current malloc block
  399. X *        
  400. X *        
  401. X *
  402. X * Mod History:    
  403. X *   90/01/27    cpcahil        Initial revision.
  404. X */
  405. XVOIDTYPE
  406. Xmalloc_split(ptr)
  407. X    struct mlist        * ptr;
  408. X{
  409. X    SIZETYPE          rest;
  410. X    SIZETYPE          size;
  411. X    struct mlist        * tptr;
  412. X
  413. X    size = ptr->r_size;
  414. X
  415. X    /*
  416. X     * roundup size to the appropriate boundry
  417. X     */
  418. X    M_ROUNDUP(size);
  419. X
  420. X    /*
  421. X     * figure out how much room is left in the array.
  422. X     * if there is enough room, create a new mlist 
  423. X     *     structure there.
  424. X     */
  425. X    if( ptr->s.size > size )
  426. X    {
  427. X        rest = ptr->s.size - size;
  428. X    }
  429. X    else
  430. X    {
  431. X        rest = 0;
  432. X    }
  433. X
  434. X    /*
  435. X     * if there is at least enough room to create another malloc block
  436. X     */
  437. X    if( rest > (M_SIZE+M_RND) )
  438. X    {
  439. X        tptr = (struct mlist *) (ptr->data+size);
  440. X        tptr->file = NULL;
  441. X        SETTYPE(tptr,M_T_SPLIT);
  442. X        tptr->id   = 0;
  443. X        tptr->prev = ptr;
  444. X        tptr->next = ptr->next;
  445. X        tptr->flag = M_MAGIC;
  446. X        tptr->s.size = rest - M_SIZE;
  447. X
  448. X        /*
  449. X         * If possible, join this segment with the next one
  450. X         */
  451. X        malloc_join(tptr, tptr->next,0,0);
  452. X
  453. X        if( tptr->next )
  454. X        {
  455. X            tptr->next->prev = tptr;
  456. X        }
  457. X
  458. X        /*
  459. X         * if we are filling in areas
  460. X         */
  461. X        if( malloc_fill_area )
  462. X        {
  463. X            malloc_aligned_memset(tptr->data,M_FREE_FILL,
  464. X                          (int)tptr->s.size);
  465. X        }
  466. X
  467. X        ptr->next = tptr;
  468. X        ptr->s.size = size;
  469. X
  470. X        if( malloc_end == ptr )
  471. X        {
  472. X            malloc_end = tptr;
  473. X        }
  474. X
  475. X        /*
  476. X         * add the new segment to the free list
  477. X         */
  478. X        malloc_freeseg(M_FREE_ADD,tptr);
  479. X    }
  480. X
  481. X} /* malloc_split(... */
  482. X
  483. X/*
  484. X * Function:    malloc_join()
  485. X *
  486. X * Purpose:    to join two malloc segments together (if possible)
  487. X *
  488. X * Arguments:    ptr    - pointer to segment to join to.
  489. X *         nextptr    - pointer to next segment to join to ptr.
  490. X *
  491. X * Returns:    nothing of any values.
  492. X *
  493. X * Narrative:
  494. X *
  495. X * Mod History:    
  496. X *   90/01/27    cpcahil        Initial revision.
  497. X */
  498. XVOIDTYPE
  499. Xmalloc_join(ptr,nextptr, inuse_override, fill_flag)
  500. X    struct mlist    * ptr;
  501. X    struct mlist    * nextptr;
  502. X    int          inuse_override;
  503. X    int          fill_flag;
  504. X{
  505. X    SIZETYPE      newsize;
  506. X
  507. X    /*
  508. X     * if      the current segment exists
  509. X     *    AND  it is not inuse (or if we don't are that it is inuse)
  510. X      *    AND  the next segment exits
  511. X     *    AND  it is not in use
  512. X     *    AND  it is adjacent to this segment
  513. X     *    THEN we can join the two together
  514. X     */
  515. X    if(     ptr     && ! (inuse_override || (ptr->flag & M_INUSE)) && 
  516. X        nextptr && ! (nextptr->flag & M_INUSE) &&
  517. X        ((ptr->data+ptr->s.size) == (char *) nextptr) )
  518. X    {
  519. X        /*
  520. X         * remove nextptr from the freelist
  521. X         */
  522. X        malloc_freeseg(M_FREE_REMOVE,nextptr);
  523. X
  524. X        /*
  525. X         * if the segment was the end pointer
  526. X         */
  527. X        if( malloc_end == nextptr )
  528. X        {
  529. X            malloc_end = ptr;
  530. X        }
  531. X        ptr->next = nextptr->next;
  532. X        newsize = nextptr->s.size + M_SIZE;
  533. X
  534. X        /*
  535. X         * if we are to fill and this segment is in use,
  536. X         *   fill in with M_FILL newly added space...
  537. X          */
  538. X        if(fill_flag && (ptr->flag & M_INUSE) && malloc_fill_area )
  539. X        {
  540. X            malloc_aligned_memset(ptr->data+ptr->s.size,
  541. X                      M_FILL, (int)(nextptr->s.size + M_SIZE));
  542. X        }
  543. X
  544. X        ptr->s.size += newsize;
  545. X        if( ptr->next )
  546. X        {
  547. X            ptr->next->prev = ptr;
  548. X        }
  549. X    }
  550. X
  551. X} /* malloc_join(... */
  552. X
  553. X
  554. X/*
  555. X * The following mess is just to ensure that the versions of these functions in
  556. X * the current library are included (to make sure that we don't accidentaly get 
  557. X * the libc versions. (This is the lazy man's -u ld directive)
  558. X */
  559. X
  560. XVOIDTYPE    (*malloc_void_funcs[])() =
  561. X{
  562. X    free,
  563. X};
  564. X
  565. Xint        (*malloc_int_funcs[])() =
  566. X{
  567. X    strcmp,
  568. X    memcmp,
  569. X};
  570. X
  571. XDATATYPE    * (*malloc_char_star_funcs[])() =
  572. X{
  573. X    debug_realloc,
  574. X    debug_calloc,
  575. X};
  576. X
  577. X/*
  578. X * This is malloc's own memset which is used without checking the parameters.
  579. X *
  580. X * NOTE: in order to increase performance this function takes advantage of
  581. X *     the fact that it is always called with an aligned pointer AND the
  582. X *     length is always a multiple of sizeof(long)
  583. X */
  584. XVOIDTYPE
  585. Xmalloc_aligned_memset(ptr,byte,len)
  586. X    DATATYPE    * ptr;
  587. X    char          byte;
  588. X    register int      len;
  589. X{
  590. X    register long      fill_int;
  591. X    int          i;
  592. X    register long    * myptr;
  593. X
  594. X    /*
  595. X     * fill in the fill integer
  596. X     */
  597. X    fill_int = 0;
  598. X    for(i=0; i < sizeof(long); i++)
  599. X    {
  600. X        fill_int |= (byte << (i << 3));
  601. X    }
  602. X
  603. X    /*
  604. X     * get pointer to begining of data
  605. X     */    
  606. X    myptr = (long *) ptr;
  607. X
  608. X    /*
  609. X     * adjust byte lengt to longword length
  610. X     */
  611. X    len /= sizeof(long);
  612. X
  613. X    /*
  614. X     * now fill in the data
  615. X     */
  616. X    while(len-- > 0)
  617. X    {
  618. X        *myptr++ = fill_int;
  619. X    }
  620. X
  621. X} /* malloc_aligned_memset(... */
  622. X
  623. X/*
  624. X * malloc_safe_memset() - works on any alignment, but is much slower than
  625. X *              malloc_aligned_memset();
  626. X */
  627. XVOIDTYPE
  628. Xmalloc_safe_memset(ptr,byte,len)
  629. X    DATATYPE    * ptr;
  630. X    char          byte;
  631. X    register int      len;
  632. X{
  633. X    register char    * myptr;
  634. X
  635. X    myptr = (char *) ptr;
  636. X
  637. X    while( len-- > 0 )
  638. X    {
  639. X        *myptr++ = byte;
  640. X    }
  641. X}
  642. X
  643. X/*
  644. X * Function:    malloc_fatal()
  645. X *
  646. X * Purpose:    to display fatal error message and take approrpriate action
  647. X *
  648. X * Arguments:    funcname - name of function calling this routine
  649. X *        mptr     - pointer to malloc block associated with error
  650. X *
  651. X * Returns:    nothing of any value
  652. X *
  653. X * Narrative:
  654. X *
  655. X * Notes:    This routine does not make use of any libc functions to build
  656. X *        and/or disply the error message.  This is due to the fact that
  657. X *        we are probably at a point where malloc is having a real problem
  658. X *        and we don't want to call any function that may use malloc.
  659. X */
  660. XVOIDTYPE
  661. Xmalloc_fatal(funcname,file,line,mptr)
  662. X    const char        * funcname;
  663. X    const char        * file;
  664. X    int              line;
  665. X    const struct mlist    * mptr;
  666. X{
  667. X    char          errbuf[ERRBUFSIZE];
  668. X    VOIDTYPE      exit();
  669. X    VOIDTYPE      malloc_err_handler();
  670. X    char        * s;
  671. X    char        * t;
  672. X
  673. X    s = errbuf;
  674. X    t = "MALLOC Fatal error from ";
  675. X    COPY(s,t,errbuf,ERRBUFSIZE);
  676. X
  677. X    t = (char *) funcname;
  678. X    COPY(s,t,errbuf,ERRBUFSIZE);
  679. X
  680. X    t = "()";
  681. X    COPY(s,t,errbuf,ERRBUFSIZE);
  682. X
  683. X    /*
  684. X     * if we have a file and line number, show it
  685. X      */
  686. X    if( file != NULL )
  687. X    {
  688. X        t = " (called from ";
  689. X        COPY(s,t,errbuf,ERRBUFSIZE);
  690. X        
  691. X        t = (char *) file;
  692. X        COPY(s,t,errbuf,ERRBUFSIZE);
  693. X
  694. X        t = " line ";
  695. X        COPY(s,t,errbuf,ERRBUFSIZE);
  696. X
  697. X        s += tostring(s,(long)line,0,10,' ');
  698. X
  699. X        *s++ = ')';
  700. X
  701. X    }
  702. X
  703. X    *s++ = ':';
  704. X    *s++ = '\n';
  705. X
  706. X    t = malloc_err_strings[malloc_errno];
  707. X    COPY(s,t,errbuf,ERRBUFSIZE);
  708. X
  709. X    *(s++) = '\n';
  710. X
  711. X    if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  712. X    {
  713. X        VOIDCAST write(2,"I/O error to error file\n",(unsigned)24);
  714. X        exit(110);
  715. X    }
  716. X
  717. X    /*
  718. X     * if this error was associated with an identified malloc block,
  719. X     * dump the malloc info for the block.
  720. X     */
  721. X    if( mptr )
  722. X    {
  723. X        malloc_dump_info_block(mptr,DUMP_PTR);
  724. X    }
  725. X
  726. X    malloc_err_handler(malloc_fatal_level);
  727. X
  728. X} /* malloc_fatal(... */
  729. X
  730. X/*
  731. X * Function:    malloc_warning()
  732. X *
  733. X * Purpose:    to display warning error message and take approrpriate action
  734. X *
  735. X * Arguments:    funcname - name of function calling this routine
  736. X *        mptr     - pointer to malloc block associated with error
  737. X *
  738. X * Returns:    nothing of any value
  739. X *
  740. X * Narrative:
  741. X *
  742. X * Notes:    This routine does not make use of any libc functions to build
  743. X *        and/or disply the error message.  This is due to the fact that
  744. X *        we are probably at a point where malloc is having a real problem
  745. X *        and we don't want to call any function that may use malloc.
  746. X */
  747. XVOIDTYPE
  748. Xmalloc_warning(funcname,file,line,mptr)
  749. X    const char        * funcname;
  750. X    const char        * file;
  751. X    int              line;
  752. X    const struct mlist    * mptr;
  753. X{
  754. X    char          errbuf[ERRBUFSIZE];
  755. X    VOIDTYPE      exit();
  756. X    char        * s;
  757. X    char        * t;
  758. X
  759. X    s = errbuf;
  760. X    t = "MALLOC Warning from ";
  761. X    COPY(s,t,errbuf,ERRBUFSIZE);
  762. X
  763. X    t = (char *) funcname;
  764. X    COPY(s,t,errbuf,ERRBUFSIZE);
  765. X
  766. X    t = "()";
  767. X    COPY(s,t,errbuf,ERRBUFSIZE);
  768. X
  769. X    /*
  770. X     * if we have a file and line number, show it
  771. X      */
  772. X    if( file != NULL )
  773. X    {
  774. X        t = " (called from ";
  775. X        COPY(s,t,errbuf,ERRBUFSIZE);
  776. X        
  777. X        t = (char *) file;
  778. X        COPY(s,t,errbuf,ERRBUFSIZE);
  779. X
  780. X        t = " line ";
  781. X        COPY(s,t,errbuf,ERRBUFSIZE);
  782. X
  783. X        s += tostring(s,(long)line,0,10,' ');
  784. X
  785. X        *s++ = ')';
  786. X
  787. X    }
  788. X
  789. X    *s++ = ':';
  790. X    *s++ = '\n';
  791. X
  792. X    t = malloc_err_strings[malloc_errno];
  793. X    COPY(s,t,errbuf,ERRBUFSIZE);
  794. X
  795. X    *(s++) = '\n';
  796. X
  797. X    if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  798. X    {
  799. X        VOIDCAST write(2,"I/O error to error file\n",(unsigned)24);
  800. X        exit(110);
  801. X    }
  802. X
  803. X    /*
  804. X     * if this error was associated with an identified malloc block,
  805. X     * dump the malloc info for the block.
  806. X     */
  807. X    if( mptr )
  808. X    {
  809. X        malloc_dump_info_block(mptr,DUMP_PTR);
  810. X    }
  811. X
  812. X        
  813. X    malloc_err_handler(malloc_warn_level);
  814. X
  815. X} /* malloc_warning(... */
  816. X
  817. X/*
  818. X * Function:    malloc_dump_info_block()
  819. X *
  820. X * Purpose:    to display identifying information on an offending malloc
  821. X *        block to help point the user in the right direction
  822. X *
  823. X * Arguments:    mptr - pointer to malloc block
  824. X *
  825. X * Returns:    nothing of any value
  826. X *
  827. X * Narrative:
  828. X *
  829. X * Notes:    This routine does not make use of any libc functions to build
  830. X *        and/or disply the error message.  This is due to the fact that
  831. X *        we are probably at a point where malloc is having a real problem
  832. X *        and we don't want to call any function that may use malloc.
  833. X */
  834. XVOIDTYPE
  835. Xmalloc_dump_info_block(mptr,id)
  836. X    const struct mlist    * mptr;
  837. X    int              id;
  838. X{
  839. X    char          errbuf[ERRBUFSIZE];
  840. X    VOIDTYPE      exit();
  841. X    char        * getenv();
  842. X    char        * funcname;
  843. X    char        * s;
  844. X    static int      show_links = -1;
  845. X    char        * t;
  846. X
  847. X    /*
  848. X     * if the mlist struct does not have a valid magic number, skip it
  849. X     * because we probably have gotten clobbered.
  850. X     */
  851. X    if( (mptr->flag&M_MAGIC_BITS) != M_MAGIC )
  852. X    {
  853. X        return;
  854. X    }
  855. X
  856. X    s = errbuf;
  857. X
  858. X    if( id == DUMP_PTR )
  859. X    {
  860. X        t = "This error is *probably* associated with the following";
  861. X        COPY(s,t,errbuf,ERRBUFSIZE);
  862. X
  863. X        t = " allocation:\n\n\tA call to ";
  864. X    }
  865. X    else if( id == DUMP_PREV )
  866. X    {
  867. X        if( mptr == NULL || (mptr == &malloc_start) )
  868. X        {
  869. X            t = "\tThere is no malloc chain element prior to the";
  870. X            COPY(s,t,errbuf,ERRBUFSIZE);
  871. X
  872. X            t = " suspect\n\t element identified above";
  873. X        }
  874. X        else
  875. X        {
  876. X            t = "\tThe malloc chain element prior to the suspect";
  877. X            COPY(s,t,errbuf,ERRBUFSIZE);
  878. X
  879. X            t = " allocation is from:\n\n\tA call to ";
  880. X        }
  881. X    }
  882. X    else
  883. X    {
  884. X        if( (mptr == NULL) ||
  885. X            ((mptr == malloc_end) && (GETTYPE(mptr) == M_T_SPLIT)) )
  886. X        {
  887. X            t = "\tThere is no malloc chain element after the";
  888. X            COPY(s,t,errbuf,ERRBUFSIZE);
  889. X
  890. X            t = " suspect\n\t element identified above";
  891. X        }
  892. X        else
  893. X        {
  894. X            t ="\tThe malloc chain element following the suspect";
  895. X            COPY(s,t,errbuf,ERRBUFSIZE);
  896. X        
  897. X            t = " allocation is from:\n\n\tA call to ";
  898. X        }
  899. X    }
  900. X    COPY(s,t,errbuf,ERRBUFSIZE);
  901. X
  902. X    /*
  903. X     * if this is a real-live malloc block (the starting block and
  904. X     * the last block (if it was generated by a malloc split) don't
  905. X     * count as real blocks since the user never allocated them.
  906. X     */
  907. X    if( (mptr != NULL) && (mptr != &malloc_start)  &&
  908. X        ((mptr != malloc_end) || (GETTYPE(mptr) != M_T_SPLIT)) )
  909. X    {
  910. X
  911. X        /*
  912. X         * get the function name 
  913. X          */
  914. X        switch(GETTYPE(mptr))
  915. X        {
  916. X            case M_T_MALLOC:
  917. X                t = "malloc";
  918. X                break;
  919. X            case M_T_REALLOC:
  920. X                t = "realloc";
  921. X                break;
  922. X            case M_T_CALLOC:
  923. X                t = "calloc";
  924. X                break;
  925. X            case M_T_SPLIT:
  926. X                t = "internal malloc func";
  927. X                break;
  928. X            default:
  929. X                t = "Unknown";
  930. X                break;
  931. X        }
  932. X        funcname = t;
  933. X        COPY(s,t,errbuf,ERRBUFSIZE);
  934. X
  935. X        t = " for ";
  936. X        COPY(s,t,errbuf,ERRBUFSIZE);
  937. X
  938. X        s += tostring(s,(long)mptr->r_size,0,10,' ');
  939. X
  940. X        t = " bytes in ";
  941. X        COPY(s,t,errbuf,ERRBUFSIZE);
  942. X
  943. X        /*
  944. X         * if we don't have file info
  945. X          */
  946. X        if( (mptr->file == NULL) || (mptr->file[0] == EOS) )
  947. X        {
  948. X            t = "an unknown file";
  949. X            COPY(s,t,errbuf,ERRBUFSIZE);
  950. X        }
  951. X        else
  952. X        {
  953. X            t = (char *) mptr->file;
  954. X            COPY(s,t,errbuf,ERRBUFSIZE);
  955. X
  956. X            t = " on line ";
  957. X            COPY(s,t,errbuf,ERRBUFSIZE);
  958. X            
  959. X            s += tostring(s,(long)mptr->line,0,10,' ');
  960. X        }
  961. X
  962. X        t = ".\n\tThis was the ";
  963. X        COPY(s,t,errbuf,ERRBUFSIZE);
  964. X
  965. X        s += tostring(s,(long)mptr->id,0,10,' ');
  966. X
  967. X        t = malloc_int_suffix(mptr->id);
  968. X        COPY(s,t,errbuf,ERRBUFSIZE);
  969. X
  970. X        t = " call to ";
  971. X        COPY(s,t,errbuf,ERRBUFSIZE);
  972. X
  973. X        t = funcname;
  974. X        COPY(s,t,errbuf,ERRBUFSIZE);
  975. X
  976. X        /*
  977. X         * if the block is not currently in use
  978. X         */
  979. X        if(  (mptr->flag & M_INUSE) == 0 )
  980. X        {
  981. X            t = ". This block has been freed";
  982. X            COPY(s,t,errbuf,ERRBUFSIZE);
  983. X        }
  984. X        
  985. X    }
  986. X
  987. X    t = ".\n\n";
  988. X    COPY(s,t,errbuf,ERRBUFSIZE);
  989. X        
  990. X    if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  991. X    {
  992. X        VOIDCAST write(2,"I/O error to error file\n",(unsigned)24);
  993. X        exit(110);
  994. X    }
  995. X
  996. X    /*
  997. X     * if we haven't set show_links yet,
  998. X     */
  999. X    if( show_links == -1 )
  1000. X    {
  1001. X        /*
  1002. X         *  see if the environment variable is specified 
  1003. X         */
  1004. X        t = getenv("MALLOC_SHOW_LINKS");
  1005. X        if( t == NULL )
  1006. X        {
  1007. X            show_links = 0;
  1008. X        }
  1009. X        else
  1010. X        {
  1011. X            show_links = 1;
  1012. X        }
  1013. X    }
  1014. X
  1015. X    /*
  1016. X     * if this is the primary suspect and we are showing links
  1017. X     */
  1018. X    if( (show_links != 0 ) && (id == DUMP_PTR ) )
  1019. X    {
  1020. X        /*
  1021. X         * show the previous and next malloc regions.
  1022. X         */
  1023. X        malloc_dump_info_block(mptr->prev,DUMP_PREV);
  1024. X        malloc_dump_info_block(mptr->next,DUMP_NEXT);
  1025. X    }
  1026. X        
  1027. X} /* malloc_dump_info_block(... */
  1028. X
  1029. X/*
  1030. X * Function:    malloc_err_handler()
  1031. X *
  1032. X * Purpose:    to take the appropriate action for warning and/or fatal 
  1033. X *        error conditions.
  1034. X *
  1035. X * Arguments:    level - error handling level 
  1036. X *
  1037. X * Returns:    nothing of any value
  1038. X *
  1039. X * Narrative:
  1040. X *
  1041. X * Notes:    This routine does not make use of any libc functions to build
  1042. X *        and/or disply the error message.  This is due to the fact that
  1043. X *        we are probably at a point where malloc is having a real problem
  1044. X *        and we don't want to call any function that may use malloc.
  1045. X */
  1046. XVOIDTYPE
  1047. Xmalloc_err_handler(level)
  1048. X    int          level;
  1049. X{
  1050. X    VOIDTYPE      exit();
  1051. X
  1052. X    if( level & M_HANDLE_DUMP )
  1053. X    {
  1054. X        malloc_dump(malloc_errfd);
  1055. X    }
  1056. X
  1057. X    switch( level & ~M_HANDLE_DUMP )
  1058. X    {
  1059. X        /*
  1060. X         * If we are to drop a core file and exit
  1061. X         */
  1062. X        case M_HANDLE_ABORT:
  1063. X            VOIDCAST abort();
  1064. X            break;
  1065. X
  1066. X        /*
  1067. X         * If we are to exit..
  1068. X         */
  1069. X        case M_HANDLE_EXIT:
  1070. X            exit(200);
  1071. X            break;
  1072. X
  1073. X        /*
  1074. X         * If we are to dump a core, but keep going on our merry way
  1075. X         */
  1076. X        case M_HANDLE_CORE:
  1077. X            {
  1078. X                int      pid;
  1079. X
  1080. X                /*
  1081. X                 * fork so child can abort (and dump core)
  1082. X                 */
  1083. X                if( (pid = fork()) == 0 )
  1084. X                {
  1085. X                    VOIDCAST write(2,"Child dumping core\n",
  1086. X                            (unsigned)19);
  1087. X                    VOIDCAST signal(SIGIOT, SIG_DFL);
  1088. X                    VOIDCAST abort();
  1089. X                }
  1090. X
  1091. X                /*
  1092. X                  * wait for child to finish dumping core
  1093. X                 */
  1094. X                while( wait((int *)0) != pid)
  1095. X                {
  1096. X                }
  1097. X
  1098. X                /*
  1099. X                 * Move core file to core.pid.cnt so 
  1100. X                 * multiple cores don't overwrite each
  1101. X                 * other.
  1102. X                 */
  1103. X                if( access("core",0) == 0 )
  1104. X                {
  1105. X                    static int      corecnt;
  1106. X                    char            filenam[32];
  1107. X                    filenam[0] = 'c';
  1108. X                    filenam[1] = 'o';
  1109. X                    filenam[2] = 'r';
  1110. X                    filenam[3] = 'e';
  1111. X                    filenam[4] = '.';
  1112. X                    VOIDCAST tostring(filenam+5,
  1113. X                        (long)getpid(),
  1114. X                        5, B_DEC, '0');
  1115. X                    filenam[10] = '.';
  1116. X                    VOIDCAST tostring(filenam+11,
  1117. X                        (long)corecnt++,
  1118. X                        3, B_DEC, '0');
  1119. X                    filenam[14] = '\0';
  1120. X                    VOIDCAST unlink(filenam);
  1121. X                    if( link("core",filenam) == 0)
  1122. X                    {
  1123. X                        VOIDCAST unlink("core");
  1124. X                    }
  1125. X                }
  1126. X            }
  1127. X
  1128. X
  1129. X        /* 
  1130. X         * If we are to just ignore the error and keep on processing
  1131. X         */
  1132. X        case M_HANDLE_IGNORE:
  1133. X            break;
  1134. X
  1135. X    } /* switch(... */
  1136. X
  1137. X} /* malloc_err_handler(... */
  1138. X
  1139. X/*
  1140. X * Function:    malloc_int_suffix()
  1141. X *
  1142. X * Purpose:    determine the correct suffix for the integer passed 
  1143. X *        (i.e. the st on 1st, nd on 2nd).
  1144. X *
  1145. X * Arguments:    i - the integer whose suffix is desired.
  1146. X *
  1147. X * Returns:    pointer to the suffix
  1148. X *
  1149. X * Narrative:
  1150. X *
  1151. X */
  1152. Xchar *
  1153. Xmalloc_int_suffix(i)
  1154. X    long      i;
  1155. X{
  1156. X    int      j;
  1157. X    char    * rtn;
  1158. X    /*
  1159. X     * since the suffixes repeat for the same number within a
  1160. X     * given 100 block (i.e. 111 and 211 use the same suffix), get the 
  1161. X     * integer moded by 100.
  1162. X     */
  1163. X    i = i % 100;
  1164. X    j = i % 10;
  1165. X
  1166. X    /*
  1167. X     * if the number is 11, or 12, or 13 or its singles digit is
  1168. X     * not a 1, 2, or 3, the suffix must be th.
  1169. X     */
  1170. X    if( (i == 11) || (i == 12) || (i == 13) ||
  1171. X        ( (j != 1) && (j != 2) && (j != 3) ) )
  1172. X    {
  1173. X        rtn = "th";
  1174. X    }
  1175. X    else 
  1176. X    {
  1177. X        switch(j)
  1178. X        {
  1179. X            case 1:
  1180. X                rtn = "st";
  1181. X                break;
  1182. X            case 2:
  1183. X                rtn = "nd";
  1184. X                break;
  1185. X            case 3:
  1186. X                rtn = "rd";
  1187. X                break;
  1188. X            default:
  1189. X                rtn = "th";
  1190. X                break;
  1191. X        }
  1192. X    }
  1193. X
  1194. X    return(rtn);
  1195. X    
  1196. X} /* malloc_int_suffix(... */
  1197. X
  1198. X/*
  1199. X * Function:    malloc_freeseg()
  1200. X *
  1201. X * Purpose:    to add or remove a segment from the list of free segments
  1202. X *
  1203. X * Arguments:    op  - operation (M_FREE_REMOVE or M_FREE_ADD)
  1204. X *        ptr - ptr to segment to be added/removed
  1205. X *
  1206. X * Returns:    nothing of any value
  1207. X *
  1208. X * Narrative:
  1209. X *
  1210. X */
  1211. XVOIDTYPE
  1212. Xmalloc_freeseg(op,ptr)
  1213. X    int          op;
  1214. X    struct mlist    * ptr;
  1215. X{
  1216. X
  1217. X    /*
  1218. X     * if we are to remove it from the list
  1219. X     */
  1220. X    if( op == M_FREE_REMOVE )
  1221. X    {
  1222. X        /*
  1223. X         * if this is the head of the list, get a new head pointer
  1224. X         */
  1225. X        if( ptr == malloc_freelist )
  1226. X        {
  1227. X            malloc_freelist = malloc_freelist->freenext;
  1228. X        }
  1229. X
  1230. X        /*
  1231. X         * if there is an item after this one in the free list,
  1232. X         *    link it to our prev item (which may be null)
  1233. X         */
  1234. X        if( ptr->freenext != (struct mlist *) NULL)
  1235. X        {
  1236. X            ptr->freenext->freeprev = ptr->freeprev;
  1237. X        }
  1238. X
  1239. X        /*
  1240. X         * if there is an item before this one in the free list,
  1241. X         *    link it to the next item (which may also be NULL)
  1242. X          */
  1243. X        if( ptr->freeprev != (struct mlist *) NULL)
  1244. X        {
  1245. X            ptr->freeprev->freenext = ptr->freenext;
  1246. X        }
  1247. X
  1248. X        /*
  1249. X         * disable the free list pointers on the segment that was
  1250. X         * removed from the list.
  1251. X         */
  1252. X        ptr->freenext = ptr->freeprev = (struct mlist *) NULL;
  1253. X
  1254. X    }
  1255. X    else /* it is an add */
  1256. X    {
  1257. X        /*
  1258. X         * setup the new links for the new head pointer (new items are
  1259. X          * always placed at the begining of the list.  However, they may
  1260. X         * be removed from anywhere in the list (hence the double
  1261. X         * linking))
  1262. X         */
  1263. X        ptr->freeprev = (struct mlist *) NULL;
  1264. X        ptr->freenext = malloc_freelist;
  1265. X        
  1266. X
  1267. X        /*
  1268. X          * if there was already a valid head pointer
  1269. X         */
  1270. X        if( malloc_freelist != (struct mlist *) NULL )
  1271. X        {
  1272. X            /*
  1273. X             * link it back to the new head pointer
  1274. X             */
  1275. X            malloc_freelist->freeprev = ptr;
  1276. X        }
  1277. X        /*
  1278. X         * store the new head pointer
  1279. X         */
  1280. X        malloc_freelist = ptr;
  1281. X
  1282. X    }
  1283. X
  1284. X} /* malloc_freeseg(... */
  1285. X
  1286. X/*
  1287. X * $Log: malloc.c,v $
  1288. X * Revision 1.19  1992/01/28  16:35:37  cpcahil
  1289. X * increased size of error string buffers and added overflow checks
  1290. X *
  1291. X * Revision 1.18  1992/01/10  17:51:03  cpcahil
  1292. X * more void stuff that slipped by
  1293. X *
  1294. X * Revision 1.17  1992/01/10  17:28:03  cpcahil
  1295. X * Added support for overriding void datatype
  1296. X *
  1297. X * Revision 1.16  1992/01/08  19:40:07  cpcahil
  1298. X * fixed write() count to display entire message.
  1299. X *
  1300. X * Revision 1.15  1991/12/31  21:31:26  cpcahil
  1301. X * changes for patch 6.  See CHANGES file for more info
  1302. X *
  1303. X * Revision 1.14  1991/12/06  08:50:48  cpcahil
  1304. X * fixed bug in malloc_safe_memset introduced in last change.
  1305. X *
  1306. X * Revision 1.13  91/12/04  18:01:21  cpcahil
  1307. X * cleand up some aditional warnings from gcc -Wall
  1308. X * 
  1309. X * Revision 1.12  91/12/04  09:23:39  cpcahil
  1310. X * several performance enhancements including addition of free list
  1311. X * 
  1312. X * Revision 1.11  91/12/02  19:10:10  cpcahil
  1313. X * changes for patch release 5
  1314. X * 
  1315. X * Revision 1.10  91/11/25  14:41:59  cpcahil
  1316. X * Final changes in preparation for patch 4 release
  1317. X * 
  1318. X * Revision 1.9  91/11/24  16:56:41  cpcahil
  1319. X * porting changes for patch level 4
  1320. X * 
  1321. X * Revision 1.8  91/11/24  00:49:27  cpcahil
  1322. X * first cut at patch 4
  1323. X * 
  1324. X * Revision 1.7  91/11/20  11:54:09  cpcahil
  1325. X * interim checkin
  1326. X * 
  1327. X * Revision 1.6  90/05/11  00:13:09  cpcahil
  1328. X * added copyright statment
  1329. X * 
  1330. X * Revision 1.5  90/02/25  11:01:18  cpcahil
  1331. X * added support for malloc chain checking.
  1332. X * 
  1333. X * Revision 1.4  90/02/24  21:50:21  cpcahil
  1334. X * lots of lint fixes
  1335. X * 
  1336. X * Revision 1.3  90/02/24  14:51:18  cpcahil
  1337. X * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
  1338. X *    the function name as a parameter.
  1339. X * 2. Added several function headers.
  1340. X * 3. Changed uses of malloc_fatal/warning to conform to new usage.
  1341. X * 
  1342. X * Revision 1.2  90/02/23  18:05:23  cpcahil
  1343. X * fixed open of error log to use append mode.
  1344. X * 
  1345. X * Revision 1.1  90/02/22  23:17:43  cpcahil
  1346. X * Initial revision
  1347. X * 
  1348. X */
  1349. END_OF_FILE
  1350. if test 27329 -ne `wc -c <'malloc.c'`; then
  1351.     echo shar: \"'malloc.c'\" unpacked with wrong size!
  1352. fi
  1353. # end of 'malloc.c'
  1354. fi
  1355. if test -f 'malloc_chk.c' -a "${1}" != "-c" ; then 
  1356.   echo shar: Will not clobber existing file \"'malloc_chk.c'\"
  1357. else
  1358. echo shar: Extracting \"'malloc_chk.c'\" \(7689 characters\)
  1359. sed "s/^X//" >'malloc_chk.c' <<'END_OF_FILE'
  1360. X/*
  1361. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  1362. X * You may copy, distribute, and use this software as long as this
  1363. X * copyright statement is not removed.
  1364. X */
  1365. X
  1366. X#include <stdio.h>
  1367. X#include "mallocint.h"
  1368. X#include "debug.h"
  1369. X
  1370. X#ifndef lint
  1371. Xstatic
  1372. Xchar rcs_hdr[] = "$Id: malloc_chk.c,v 1.12 1992/01/10 17:51:03 cpcahil Exp $";
  1373. X#endif
  1374. X
  1375. X
  1376. X/*
  1377. X * Function:    malloc_in_arena()
  1378. X *
  1379. X * Purpose:    to verify address is within malloc arena.
  1380. X *
  1381. X * Arguments:    ptr    - pointer to verify
  1382. X *
  1383. X * Returns:    TRUE    - if pointer is within malloc area
  1384. X *        FALSE    - otherwise
  1385. X *
  1386. X * Narrative:
  1387. X *   IF pointer is >= malloc area start AND <= malloc area end
  1388. X *      return TRUE
  1389. X *   ELSE
  1390. X *      return FALSE
  1391. X *
  1392. X * Mod History:    
  1393. X *   90/01/24    cpcahil        Initial revision.
  1394. X */
  1395. Xint
  1396. Xmalloc_in_arena(ptr)
  1397. X    const DATATYPE    * ptr;
  1398. X{
  1399. X    int          rtn = 0;
  1400. X
  1401. X    if( ptr >= malloc_data_start && ptr <= malloc_data_end )
  1402. X    {
  1403. X        rtn = 1;
  1404. X    }
  1405. X    
  1406. X    return(rtn);
  1407. X}
  1408. X
  1409. X/*
  1410. X * Function:    malloc_check_str()
  1411. X *
  1412. X * Arguments:    func    - name of function calling this routine
  1413. X *        str    - pointer to area to check
  1414. X *
  1415. X * Purpose:    to verify that if str is within the malloc arena, the data 
  1416. X *        it points to does not extend beyond the applicable region.
  1417. X *
  1418. X * Returns:    Nothing of any use (function is void).
  1419. X *
  1420. X * Narrative:
  1421. X *   IF pointer is within malloc arena
  1422. X *      determin length of string
  1423. X *      call malloc_verify() to verify data is withing applicable region
  1424. X *   return 
  1425. X *
  1426. X * Mod History:    
  1427. X *   90/01/24    cpcahil        Initial revision.
  1428. X *   90/01/29    cpcahil        Added code to ignore recursive calls.
  1429. X */
  1430. XVOIDTYPE
  1431. Xmalloc_check_str(func,file,line,str)
  1432. X    const char        * func;
  1433. X    const char        * file;
  1434. X    int              line;
  1435. X    const char        * str;
  1436. X{
  1437. X    static int          layers;
  1438. X    register const char    * s;
  1439. X
  1440. X    MALLOC_INIT();
  1441. X
  1442. X    /*
  1443. X     * if we are already in the malloc library somewhere, don't check
  1444. X     * things again.
  1445. X     */
  1446. X    if( in_malloc_code )
  1447. X    {
  1448. X        return;
  1449. X    }
  1450. X
  1451. X    if( (layers++ == 0) &&  malloc_in_arena((DATATYPE *)str) )
  1452. X    {
  1453. X        for( s=str; *s; s++)
  1454. X        {
  1455. X        }
  1456. X        
  1457. X        malloc_verify(func,file,line,str,s-str+1);
  1458. X    }
  1459. X
  1460. X    layers--;
  1461. X}
  1462. X
  1463. X/*
  1464. X * Function:    malloc_check_strn()
  1465. X *
  1466. X * Arguments:    func    - name of function calling this routine
  1467. X *        str    - pointer to area to check
  1468. X *         len     - max length of string
  1469. X *
  1470. X * Purpose:    to verify that if str is within the malloc arena, the data 
  1471. X *        it points to does not extend beyond the applicable region.
  1472. X *
  1473. X * Returns:    Nothing of any use (function is void).
  1474. X *
  1475. X * Narrative:
  1476. X *   IF pointer is within malloc arena
  1477. X *      determin length of string
  1478. X *      call malloc_verify() to verify data is withing applicable region
  1479. X *   return 
  1480. X *
  1481. X * Mod History:    
  1482. X *   90/01/24    cpcahil        Initial revision.
  1483. X *   90/01/29    cpcahil        Added code to ignore recursive calls.
  1484. X *   90/08/29    cpcahil        added length (for strn* functions)
  1485. X */
  1486. XVOIDTYPE
  1487. Xmalloc_check_strn(func,file,line,str,len)
  1488. X    const char    * func;
  1489. X    const char     * file;
  1490. X    int          line;
  1491. X    const char    * str;
  1492. X    int          len;
  1493. X{
  1494. X    register int          i;
  1495. X    static int          layers;
  1496. X    register const char    * s;
  1497. X
  1498. X    MALLOC_INIT();
  1499. X
  1500. X    /*
  1501. X     * if we are already in the malloc library somewhere, don't check
  1502. X     * things again.
  1503. X     */
  1504. X    if( in_malloc_code )
  1505. X    {
  1506. X        return;
  1507. X    }
  1508. X
  1509. X    if( (layers++ == 0) &&  malloc_in_arena(str) )
  1510. X    {
  1511. X        for( s=str,i=0; (i < len) && *(char *)s; i++,s++)
  1512. X        {
  1513. X        }
  1514. X
  1515. X        /*
  1516. X         * if we found a null byte before len, add one to s so
  1517. X         * that we ensure that the null is counted in the bytes to
  1518. X         * check.
  1519. X         */
  1520. X        if( i < len )
  1521. X        {
  1522. X            s++;
  1523. X        }
  1524. X        malloc_verify(func,file,line,str,s-str);
  1525. X    }
  1526. X
  1527. X    layers--;
  1528. X}
  1529. X
  1530. X/*
  1531. X * Function:    malloc_check_data()
  1532. X *
  1533. X * Arguments:    func    - name of function calling this routine
  1534. X *        ptr    - pointer to area to check
  1535. X *        len     - length to verify
  1536. X *
  1537. X * Purpose:    to verify that if ptr is within the malloc arena, the data 
  1538. X *        it points to does not extend beyond the applicable region.
  1539. X *
  1540. X * Returns:    Nothing of any use (function is void).
  1541. X *
  1542. X * Narrative:
  1543. X *   IF pointer is within malloc arena
  1544. X *      call malloc_verify() to verify data is withing applicable region
  1545. X *   return 
  1546. X *
  1547. X * Mod History:    
  1548. X *   90/01/24    cpcahil        Initial revision.
  1549. X *   90/01/29    cpcahil        Added code to ignore recursive calls.
  1550. X */
  1551. XVOIDTYPE
  1552. Xmalloc_check_data(func,file,line,ptr,len)
  1553. X    const char    * func;
  1554. X    const char    * file;
  1555. X    int          line;
  1556. X    const DATATYPE    * ptr;
  1557. X    SIZETYPE      len;
  1558. X{
  1559. X    static int      layers;
  1560. X
  1561. X    MALLOC_INIT();
  1562. X
  1563. X    /*
  1564. X     * if we are already in the malloc library somewhere, don't check
  1565. X     * things again.
  1566. X     */
  1567. X    if( in_malloc_code )
  1568. X    {
  1569. X        return;
  1570. X    }
  1571. X
  1572. X    if( layers++ == 0 )
  1573. X    {
  1574. X        DEBUG3(40,"malloc_check_data(%s,0x%x,%d) called...",
  1575. X            func,ptr,len);
  1576. X        if( malloc_in_arena(ptr) )
  1577. X        {
  1578. X            DEBUG0(10,"pointer in malloc arena, verifying...");
  1579. X            malloc_verify(func,file,line,ptr,len);
  1580. X        }
  1581. X    }
  1582. X
  1583. X    layers--;
  1584. X}
  1585. X
  1586. X/*
  1587. X * Function:    malloc_verify()
  1588. X *
  1589. X * Arguments:    func    - name of function calling the malloc check routines
  1590. X *        ptr    - pointer to area to check
  1591. X *        len     - length to verify
  1592. X *
  1593. X * Purpose:    to verify that the data ptr points to does not extend beyond
  1594. X *        the applicable malloc region.  This function is only called 
  1595. X *        if it has been determined that ptr points into the malloc arena.
  1596. X *
  1597. X * Returns:    Nothing of any use (function is void).
  1598. X *
  1599. X * Narrative:
  1600. X *
  1601. X * Mod History:    
  1602. X *   90/01/24    cpcahil        Initial revision.
  1603. X */
  1604. XVOIDTYPE
  1605. Xmalloc_verify(func,file,line,ptr,len)
  1606. X    const char    * func;
  1607. X    const char    * file;
  1608. X    int          line;
  1609. X    const DATATYPE    * ptr;
  1610. X    int          len;
  1611. X{
  1612. X    struct mlist        * mptr;
  1613. X    
  1614. X    DEBUG5(40,"malloc_verify(%s, %s, %s, 0x%x,%d) called...",
  1615. X        func, file, line, ptr, len);
  1616. X    /*
  1617. X     * Find the malloc block that includes this pointer
  1618. X     */
  1619. X    mptr = &malloc_start;
  1620. X    while( mptr
  1621. X        && ! ((((DATATYPE *)mptr) < ptr)
  1622. X        &&   (((DATATYPE *)(mptr->data+mptr->s.size)) > ptr) ) )
  1623. X    {
  1624. X        mptr = mptr->next;
  1625. X    }
  1626. X
  1627. X    /*
  1628. X     * if ptr was not in a malloc block, it must be part of
  1629. X     *    some direct sbrk() stuff, so just return.
  1630. X     */
  1631. X    if( ! mptr )
  1632. X    {
  1633. X        DEBUG1(10,"ptr (0x%x) not found in malloc search", ptr);
  1634. X        return;
  1635. X    }
  1636. X    
  1637. X    /*
  1638. X      * Now we have a valid malloc block that contains the indicated
  1639. X     * pointer.  We must verify that it is withing the requested block
  1640. X     * size (as opposed to the real block size which is rounded up to
  1641. X     * allow for correct alignment).
  1642. X     */
  1643. X
  1644. X    DEBUG4(60,"Checking  0x%x-0x%x, 0x%x-0x%x",
  1645. X            ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
  1646. X    
  1647. X    if(    (ptr < (DATATYPE *)mptr->data)
  1648. X          || ((((char *)ptr)+len) > (char *)(mptr->data+mptr->r_size)) )
  1649. X    {
  1650. X        DEBUG4(0,"pointer not within region 0x%x-0x%x, 0x%x-0x%x",
  1651. X            ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
  1652. X
  1653. X        malloc_errno = M_CODE_OUTOF_BOUNDS;
  1654. X        malloc_warning(func,file,line,mptr);
  1655. X    }
  1656. X
  1657. X    return;
  1658. X}
  1659. X
  1660. X/*
  1661. X * $Log: malloc_chk.c,v $
  1662. X * Revision 1.12  1992/01/10  17:51:03  cpcahil
  1663. X * more void stuff that slipped by
  1664. X *
  1665. X * Revision 1.11  1992/01/10  17:28:03  cpcahil
  1666. X * Added support for overriding void datatype
  1667. X *
  1668. X * Revision 1.10  1991/12/31  02:23:29  cpcahil
  1669. X * fixed verify bug of strncpy when len was exactly same as strlen
  1670. X *
  1671. X * Revision 1.9  91/12/02  19:10:12  cpcahil
  1672. X * changes for patch release 5
  1673. X * 
  1674. X * Revision 1.8  91/11/25  14:42:01  cpcahil
  1675. X * Final changes in preparation for patch 4 release
  1676. X * 
  1677. X * Revision 1.7  91/11/24  00:49:29  cpcahil
  1678. X * first cut at patch 4
  1679. X * 
  1680. X * Revision 1.6  91/11/20  11:54:11  cpcahil
  1681. X * interim checkin
  1682. X * 
  1683. X * Revision 1.5  90/08/29  22:23:48  cpcahil
  1684. X * added new function to check on strings up to a specified length 
  1685. X * and used it within several strn* functions.
  1686. X * 
  1687. X * Revision 1.4  90/05/11  00:13:09  cpcahil
  1688. X * added copyright statment
  1689. X * 
  1690. X * Revision 1.3  90/02/24  21:50:22  cpcahil
  1691. X * lots of lint fixes
  1692. X * 
  1693. X * Revision 1.2  90/02/24  17:29:38  cpcahil
  1694. X * changed $Header to $Id so full path wouldnt be included as part of rcs 
  1695. X * id string
  1696. X * 
  1697. X * Revision 1.1  90/02/24  14:57:03  cpcahil
  1698. X * Initial revision
  1699. X * 
  1700. X */
  1701. END_OF_FILE
  1702. if test 7689 -ne `wc -c <'malloc_chk.c'`; then
  1703.     echo shar: \"'malloc_chk.c'\" unpacked with wrong size!
  1704. fi
  1705. # end of 'malloc_chk.c'
  1706. fi
  1707. if test -f 'malloc_chn.c' -a "${1}" != "-c" ; then 
  1708.   echo shar: Will not clobber existing file \"'malloc_chn.c'\"
  1709. else
  1710. echo shar: Extracting \"'malloc_chn.c'\" \(5933 characters\)
  1711. sed "s/^X//" >'malloc_chn.c' <<'END_OF_FILE'
  1712. X/*
  1713. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  1714. X * You may copy, distribute, and use this software as long as this
  1715. X * copyright statement is not removed.
  1716. X */
  1717. X#include <stdio.h>
  1718. X#include <fcntl.h>
  1719. X#include "mallocint.h"
  1720. X
  1721. X/*
  1722. X * Function:    malloc_chain_check()
  1723. X *
  1724. X * Purpose:    to verify malloc chain is intact
  1725. X *
  1726. X * Arguments:    todo    - 0 - just check and return status
  1727. X *              1 - call malloc_warn if error detected
  1728. X *
  1729. X * Returns:    0    - malloc chain intact & no overflows
  1730. X *        other    - problems detected in malloc chain
  1731. X *
  1732. X * Narrative:
  1733. X *
  1734. X * Notes:    If todo is non-zero the malloc_warn function, when called
  1735. X *        may not return (i.e. it may exit)
  1736. X *
  1737. X */
  1738. X#ifndef lint
  1739. Xstatic
  1740. Xchar rcs_hdr[] = "$Id: malloc_chn.c,v 1.9 1991/12/04 09:23:41 cpcahil Exp $";
  1741. X#endif
  1742. X
  1743. X
  1744. Xint
  1745. Xmalloc_chain_check(todo)
  1746. X    int          todo;
  1747. X{
  1748. X    return( DBmalloc_chain_check( (char *)NULL, 0, todo) );
  1749. X}
  1750. X
  1751. Xint
  1752. XDBmalloc_chain_check(file,line,todo)
  1753. X    const char    * file;
  1754. X    int          line;
  1755. X    int          todo;
  1756. X{
  1757. X    return( DBFmalloc_chain_check("malloc_chain_check",file,line,todo) );
  1758. X}
  1759. X
  1760. Xint
  1761. XDBFmalloc_chain_check(func,file,line,todo)
  1762. X    const char    * func;
  1763. X    const char    * file;
  1764. X    int          line;
  1765. X    int          todo;
  1766. X{
  1767. X    int              i;
  1768. X    register struct mlist    * oldptr;
  1769. X    register struct mlist    * ptr;
  1770. X    int              rtn = 0;
  1771. X
  1772. X    MALLOC_INIT();
  1773. X
  1774. X    /*
  1775. X     * first check the full malloc chain
  1776. X     */
  1777. X    oldptr = &malloc_start;
  1778. X    for(ptr = malloc_start.next; ; oldptr = ptr, ptr = ptr->next)
  1779. X    {
  1780. X        /*
  1781. X         * Since the malloc chain is a forward only chain, any
  1782. X         * pointer that we get should always be positioned in 
  1783. X         * memory following the previous pointer.  If this is not
  1784. X         * so, we must have a corrupted chain.
  1785. X         */
  1786. X        if( ptr )
  1787. X        {
  1788. X            if(ptr < oldptr )
  1789. X            {
  1790. X                malloc_errno = M_CODE_CHAIN_BROKE;
  1791. X                if( todo )
  1792. X                {
  1793. X                    malloc_fatal(func,file,line,oldptr);
  1794. X                }
  1795. X                rtn++;
  1796. X                break;
  1797. X            }
  1798. X        }
  1799. X        else
  1800. X        {
  1801. X            if( malloc_end && (oldptr != malloc_end) )
  1802. X            {
  1803. X                /*
  1804. X                 * This should never happen.  If it does, then
  1805. X                 * we got a real problem.
  1806. X                 */
  1807. X                malloc_errno = M_CODE_NO_END;
  1808. X                if( todo )
  1809. X                {
  1810. X                    malloc_fatal(func,file,line,oldptr);
  1811. X                }
  1812. X                rtn++;
  1813. X            }
  1814. X            break;
  1815. X        }
  1816. X        
  1817. X        /*
  1818. X         * verify that ptr is within the malloc region...
  1819. X         * since we started within the malloc chain this should never
  1820. X         * happen.
  1821. X         */
  1822. X        if( ((DATATYPE *)ptr < malloc_data_start) ||
  1823. X            ((DATATYPE *)ptr > malloc_data_end) )
  1824. X        {
  1825. X            malloc_errno = M_CODE_BAD_PTR;
  1826. X            if( todo )
  1827. X            {
  1828. X                malloc_fatal(func,file,line,oldptr);
  1829. X            }
  1830. X            rtn++;
  1831. X            break;
  1832. X        }
  1833. X
  1834. X        /* 
  1835. X         * verify magic flag is set
  1836. X         */
  1837. X        
  1838. X        if( (ptr->flag&M_MAGIC_BITS) != M_MAGIC )
  1839. X        {
  1840. X            malloc_errno = M_CODE_BAD_MAGIC;
  1841. X            if( todo )
  1842. X            {
  1843. X                malloc_warning(func,file,line,
  1844. X                        (struct mlist *)NULL);
  1845. X            }
  1846. X            rtn++;
  1847. X            continue;
  1848. X        }
  1849. X
  1850. X        /* 
  1851. X         * verify segments are correctly linked together
  1852. X         */
  1853. X        if( (ptr->prev && (ptr->prev->next != ptr) ) ||
  1854. X            (ptr->next && (ptr->next->prev != ptr) ) ||
  1855. X            ((ptr->next == NULL) && (ptr->prev == NULL)) )
  1856. X        {
  1857. X            malloc_errno = M_CODE_BAD_CONNECT;
  1858. X            if( todo )
  1859. X            {
  1860. X                malloc_warning(func,file,line,ptr);
  1861. X            }
  1862. X            rtn++;
  1863. X            continue;
  1864. X        }
  1865. X
  1866. X        /*
  1867. X         * If this segment is allocated
  1868. X         */
  1869. X        if( (ptr->flag & M_INUSE) != 0 )
  1870. X        {
  1871. X            /*
  1872. X             * verify no overflow of data area
  1873. X             */
  1874. X
  1875. X            for(i=ptr->r_size; i < ptr->s.size; i++)
  1876. X            {
  1877. X                if( ptr->data[i] != M_FILL )
  1878. X                {
  1879. X                    malloc_errno = M_CODE_OVERRUN;
  1880. X                    if( todo )
  1881. X                    {
  1882. X                        malloc_warning(func,file,
  1883. X                                line,ptr);
  1884. X                    }
  1885. X                    rtn++;
  1886. X                    break;
  1887. X                }
  1888. X            }
  1889. X        }
  1890. X        else /* it's not allocated so */
  1891. X        {
  1892. X            /*
  1893. X             * verify no reuse of freed data blocks
  1894. X             */
  1895. X
  1896. X            for(i=0; i < ptr->s.size; i++)
  1897. X            {
  1898. X                if( ptr->data[i] != M_FREE_FILL )
  1899. X                {
  1900. X                    malloc_errno = M_CODE_REUSE;
  1901. X                    if( todo )
  1902. X                    {
  1903. X                        malloc_warning(func,file,
  1904. X                                line,ptr);
  1905. X                    }
  1906. X                    rtn++;
  1907. X                    break;
  1908. X                }
  1909. X            }
  1910. X        }
  1911. X
  1912. X    } /* for(... */
  1913. X
  1914. X    /*
  1915. X     * and now check the free list
  1916. X     */
  1917. X    oldptr = NULL;
  1918. X    for(ptr = malloc_freelist; (rtn == 0) && (ptr != NULL); ptr = ptr->freenext)
  1919. X    {
  1920. X        /*
  1921. X         * Since the malloc chain is a forward only chain, any
  1922. X         * pointer that we get should always be positioned in 
  1923. X         * memory following the previous pointer.  If this is not
  1924. X         * so, we must have a corrupted chain.
  1925. X         */
  1926. X        if( (oldptr != NULL) && (ptr < oldptr) )
  1927. X        {
  1928. X            malloc_errno = M_CODE_CHAIN_BROKE;
  1929. X            if( todo )
  1930. X            {
  1931. X                malloc_fatal(func,file,line,oldptr);
  1932. X            }
  1933. X            rtn++;
  1934. X        }
  1935. X        /*
  1936. X         * verify that ptr is within the malloc region...
  1937. X         * since we started within the malloc chain this should never
  1938. X         * happen.
  1939. X         */
  1940. X        else if( ((DATATYPE *)ptr < malloc_data_start) ||
  1941. X            ((DATATYPE *)ptr > malloc_data_end) )
  1942. X        {
  1943. X            malloc_errno = M_CODE_BAD_PTR;
  1944. X            if( todo )
  1945. X            {
  1946. X                malloc_fatal(func,file,line,oldptr);
  1947. X            }
  1948. X            rtn++;
  1949. X        }
  1950. X        /* 
  1951. X         * verify magic flag is set
  1952. X         */
  1953. X        else if( (ptr->flag&M_MAGIC_BITS) != M_MAGIC )
  1954. X        {
  1955. X            malloc_errno = M_CODE_BAD_MAGIC;
  1956. X            if( todo )
  1957. X            {
  1958. X                malloc_warning(func,file,line,
  1959. X                        (struct mlist *)NULL);
  1960. X            }
  1961. X            rtn++;
  1962. X        }
  1963. X        /* 
  1964. X         * verify segments are correctly linked together
  1965. X         */
  1966. X        else if(   (ptr->freeprev && (ptr->freeprev->freenext != ptr) )
  1967. X            || (ptr->freenext && (ptr->freenext->freeprev != ptr) ) )
  1968. X        {
  1969. X            malloc_errno = M_CODE_BAD_CONNECT;
  1970. X            if( todo )
  1971. X            {
  1972. X                malloc_warning(func,file,line,ptr);
  1973. X            }
  1974. X            rtn++;
  1975. X        }
  1976. X        /*
  1977. X         * else if this segment is in use
  1978. X         */
  1979. X        else if( (ptr->flag & M_INUSE) != 0 )
  1980. X        {
  1981. X            malloc_errno = M_CODE_FREELIST_BAD;
  1982. X            if( todo )
  1983. X            {
  1984. X                malloc_warning(func,file, line,ptr);
  1985. X            }
  1986. X            rtn++;
  1987. X        }
  1988. X        /*
  1989. X         * else if we are filling in areas, check to make sure
  1990. X         * that the free fill bytes are still set
  1991. X         */
  1992. X        else if( malloc_fill_area )
  1993. X        {
  1994. X            /*
  1995. X             * verify no reuse of freed data blocks
  1996. X             */
  1997. X            for(i=0; i < ptr->s.size; i++)
  1998. X            {
  1999. X                if( ptr->data[i] != M_FREE_FILL )
  2000. X                {
  2001. X                    malloc_errno = M_CODE_REUSE;
  2002. X                    if( todo )
  2003. X                    {
  2004. X                        malloc_warning(func,file,
  2005. X                                line,ptr);
  2006. X                    }
  2007. X                    rtn++;
  2008. X                    break;
  2009. X                }
  2010. X            }
  2011. X        }
  2012. X
  2013. X    } /* for(... */
  2014. X    return(rtn);
  2015. X
  2016. X} /* malloc_chain_check(... */
  2017. END_OF_FILE
  2018. if test 5933 -ne `wc -c <'malloc_chn.c'`; then
  2019.     echo shar: \"'malloc_chn.c'\" unpacked with wrong size!
  2020. fi
  2021. # end of 'malloc_chn.c'
  2022. fi
  2023. if test -f 'mallocint.h' -a "${1}" != "-c" ; then 
  2024.   echo shar: Will not clobber existing file \"'mallocint.h'\"
  2025. else
  2026. echo shar: Extracting \"'mallocint.h'\" \(3686 characters\)
  2027. sed "s/^X//" >'mallocint.h' <<'END_OF_FILE'
  2028. X/*
  2029. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  2030. X * You may copy, distribute, and use this software as long as this
  2031. X * copyright statement is not removed.
  2032. X */
  2033. X/*
  2034. X * $Id: mallocint.h,v 1.7 1991/12/31 21:31:26 cpcahil Exp $
  2035. X */
  2036. X
  2037. X/*
  2038. X * this file contains macros that are internal to the malloc library
  2039. X * and therefore, are not needed in malloc.h.
  2040. X */
  2041. X#include <string.h>
  2042. X#include <memory.h>
  2043. X
  2044. X#if __STDC__
  2045. X#include <unistd.h>
  2046. X#include <stdlib.h>
  2047. X#endif
  2048. X
  2049. X#define IN_MALLOC_CODE    1
  2050. X#include "malloc.h"
  2051. X
  2052. X#define IDTYPE unsigned long
  2053. X
  2054. X#if ! __STDC__
  2055. X#define const
  2056. X#endif
  2057. X
  2058. X/*
  2059. X * minimum round up to get to a doubleword boundry, assuming it is the
  2060. X * strictest alignment requirement on the system.  If not, the union s
  2061. X * in struct mlist will also have to be changed.
  2062. X */
  2063. X#define M_RND        0x08
  2064. X
  2065. Xstruct mlist
  2066. X{
  2067. X    struct mlist    * next;            /* next entry in chain    */
  2068. X    struct mlist    * prev;            /* prev entry in chain    */
  2069. X    struct mlist    * freenext;        /* next ent in free chn */
  2070. X    struct mlist    * freeprev;        /* prev ent in free chn */
  2071. X    int           flag;            /* inuse flag        */
  2072. X    const char    * file;            /* file where called fm    */
  2073. X    int          line;            /* line where called fm    */
  2074. X    IDTYPE          hist_id;        /* historical id    */
  2075. X    IDTYPE          id;            /* malloc call number    */
  2076. X    SIZETYPE      r_size;        /* requested size    */
  2077. X    union
  2078. X    {
  2079. X        SIZETYPE      size;        /* actual size        */
  2080. X        double          unused_just_for_alignment;
  2081. X    } s;
  2082. X    char          data[M_RND];
  2083. X};
  2084. X
  2085. X/*
  2086. X * kludge to get offsetof the data element for the mlist structure
  2087. X */
  2088. X#define M_SIZE        ((int)(char *)((struct mlist *)0)->data)
  2089. X
  2090. X#define M_INUSE     0x01
  2091. X#define M_MAGIC     0x03156100
  2092. X#define M_MAGIC_BITS    0xffffff00
  2093. X
  2094. X#define M_BLOCKSIZE    (1024*8)
  2095. X
  2096. X#define EOS        '\0'
  2097. X#define M_FILL        '\01'
  2098. X#define M_FREE_FILL    '\02'
  2099. X
  2100. X#define MALLOC_INIT()    if( malloc_data_start == (DATATYPE *)0 ) malloc_init()
  2101. X
  2102. X/*
  2103. X * malloc_freeseg() operation arguments
  2104. X */
  2105. X#define M_FREE_REMOVE    1
  2106. X#define M_FREE_ADD    2
  2107. X/*
  2108. X * Malloc types
  2109. X */
  2110. X#define M_T_MALLOC    0x10
  2111. X#define M_T_REALLOC    0x20
  2112. X#define M_T_CALLOC    0x30
  2113. X#define M_T_SPLIT    0x40
  2114. X#define M_T_BITS    0x70
  2115. X
  2116. X#define GETTYPE(_ptr)        (_ptr->flag & M_T_BITS)
  2117. X#define SETTYPE(_ptr,_type)     (_ptr->flag = ((_ptr->flag & ~M_T_BITS)|_type))
  2118. X
  2119. X#define M_ROUNDUP(size)    {\
  2120. X                if( size & (M_RND-1) ) \
  2121. X                { \
  2122. X                    size += (M_RND-1); \
  2123. X                    size &= ~(M_RND-1); \
  2124. X                } \
  2125. X            }
  2126. X
  2127. Xvoid          exit __stdcargs((int));
  2128. Xchar        * getenv __stdcargs((const char *));
  2129. XDATATYPE    * sbrk __stdcargs((SIZETYPE));
  2130. X
  2131. X#undef __stdcargs
  2132. X#include "prototypes.h"
  2133. X
  2134. X/*
  2135. X * global variables
  2136. X */
  2137. Xextern int          in_malloc_code;
  2138. Xextern int          malloc_checking;
  2139. Xextern DATATYPE        * malloc_data_start;
  2140. Xextern DATATYPE        * malloc_data_end;
  2141. Xextern struct mlist     * malloc_end;
  2142. Xextern int          malloc_errfd;
  2143. Xextern int          malloc_errno;
  2144. Xextern char        * malloc_err_strings[];
  2145. Xextern int          malloc_fatal_level;
  2146. Xextern int          malloc_fill_area;
  2147. Xextern struct mlist    * malloc_freelist;
  2148. Xextern long          malloc_hist_id;
  2149. Xextern int          malloc_lowfrag;
  2150. Xextern struct mlist      malloc_start;
  2151. Xextern int          malloc_warn_level;
  2152. X
  2153. X/*
  2154. X * $Log: mallocint.h,v $
  2155. X * Revision 1.7  1991/12/31  21:31:26  cpcahil
  2156. X * changes for patch 6.  See CHANGES file for more info
  2157. X *
  2158. X * Revision 1.6  1991/12/06  08:54:18  cpcahil
  2159. X * cleanup of __STDC__ usage and addition of CHANGES file
  2160. X *
  2161. X * Revision 1.5  91/12/04  18:01:22  cpcahil
  2162. X * cleand up some aditional warnings from gcc -Wall
  2163. X * 
  2164. X * Revision 1.4  91/12/04  09:23:42  cpcahil
  2165. X * several performance enhancements including addition of free list
  2166. X * 
  2167. X * Revision 1.3  91/12/02  19:10:12  cpcahil
  2168. X * changes for patch release 5
  2169. X * 
  2170. X * Revision 1.2  91/11/25  14:42:02  cpcahil
  2171. X * Final changes in preparation for patch 4 release
  2172. X * 
  2173. X * Revision 1.1  91/11/24  00:49:30  cpcahil
  2174. X * first cut at patch 4
  2175. X * 
  2176. X */
  2177. END_OF_FILE
  2178. if test 3686 -ne `wc -c <'mallocint.h'`; then
  2179.     echo shar: \"'mallocint.h'\" unpacked with wrong size!
  2180. fi
  2181. # end of 'mallocint.h'
  2182. fi
  2183. if test -f 'mallopt.c' -a "${1}" != "-c" ; then 
  2184.   echo shar: Will not clobber existing file \"'mallopt.c'\"
  2185. else
  2186. echo shar: Extracting \"'mallopt.c'\" \(2654 characters\)
  2187. sed "s/^X//" >'mallopt.c' <<'END_OF_FILE'
  2188. X/*
  2189. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  2190. X * You may copy, distribute, and use this software as long as this
  2191. X * copyright statement is not removed.
  2192. X */
  2193. X#include <stdio.h>
  2194. X#include <fcntl.h>
  2195. X#include "mallocint.h"
  2196. X
  2197. X/*
  2198. X * Function:    mallopt()
  2199. X *
  2200. X * Purpose:    to set options for the malloc debugging library
  2201. X *
  2202. X * Arguments:    none
  2203. X *
  2204. X * Returns:    nothing of any value
  2205. X *
  2206. X * Narrative:    
  2207. X *
  2208. X */
  2209. X
  2210. X#ifndef lint
  2211. Xstatic
  2212. Xchar rcs_hdr[] = "$Id: mallopt.c,v 1.11 1992/01/10 17:28:03 cpcahil Exp $";
  2213. X#endif
  2214. X
  2215. Xint
  2216. Xmallopt(cmd,value)
  2217. X    int              cmd;
  2218. X    union malloptarg      value;
  2219. X{
  2220. X    int              i;
  2221. X    register char        * s;
  2222. X
  2223. X    MALLOC_INIT();
  2224. X
  2225. X    switch(cmd)
  2226. X    {
  2227. X        case MALLOC_WARN:
  2228. X            malloc_warn_level = value.i;
  2229. X            break;
  2230. X
  2231. X        case MALLOC_FATAL:
  2232. X            malloc_fatal_level = value.i;
  2233. X            break;
  2234. X
  2235. X        case MALLOC_CKCHAIN:
  2236. X            malloc_checking = value.i;
  2237. X            break;
  2238. X
  2239. X        case MALLOC_LOWFRAG:
  2240. X            malloc_lowfrag = value.i;
  2241. X            break;
  2242. X
  2243. X        case MALLOC_FILLAREA:
  2244. X            malloc_fill_area = value.i;
  2245. X            break;
  2246. X
  2247. X        case MALLOC_ERRFILE:
  2248. X            
  2249. X            i = open(value.str,O_CREAT|O_APPEND|O_WRONLY,0666);
  2250. X            if( i == -1 )
  2251. X            {
  2252. X                VOIDCAST write(2,
  2253. X                      "Unable to open malloc error file: ",
  2254. X                      (unsigned) 34);
  2255. X                for(s=value.str; *s; s++)
  2256. X                {
  2257. X                    /* do nothing */;
  2258. X                }
  2259. X                VOIDCAST write(2,value.str,
  2260. X                         (unsigned)(s-value.str));
  2261. X                VOIDCAST write(2,"\n",(unsigned)1);
  2262. X            }
  2263. X            else
  2264. X            {
  2265. X                if( malloc_errfd != 2 )
  2266. X                {
  2267. X                    VOIDCAST close(malloc_errfd);
  2268. X                }
  2269. X                malloc_errfd = i;
  2270. X            }
  2271. X            
  2272. X            break;
  2273. X
  2274. X        default:
  2275. X            return(1);
  2276. X    }
  2277. X
  2278. X    return(0);
  2279. X}
  2280. X
  2281. X/*
  2282. X * $Log: mallopt.c,v $
  2283. X * Revision 1.11  1992/01/10  17:28:03  cpcahil
  2284. X * Added support for overriding void datatype
  2285. X *
  2286. X * Revision 1.10  1991/12/31  21:31:26  cpcahil
  2287. X * changes for patch 6.  See CHANGES file for more info
  2288. X *
  2289. X * Revision 1.9  1991/12/04  09:23:42  cpcahil
  2290. X * several performance enhancements including addition of free list
  2291. X *
  2292. X * Revision 1.8  91/11/25  14:42:03  cpcahil
  2293. X * Final changes in preparation for patch 4 release
  2294. X * 
  2295. X * Revision 1.7  91/11/24  00:49:30  cpcahil
  2296. X * first cut at patch 4
  2297. X * 
  2298. X * Revision 1.6  90/08/29  22:23:36  cpcahil
  2299. X * fixed mallopt to use a union as an argument.
  2300. X * 
  2301. X * Revision 1.5  90/08/29  21:22:51  cpcahil
  2302. X * miscellaneous lint fixes
  2303. X * 
  2304. X * Revision 1.4  90/05/11  00:13:10  cpcahil
  2305. X * added copyright statment
  2306. X * 
  2307. X * Revision 1.3  90/02/25  11:03:26  cpcahil
  2308. X * changed to return int so that it agrees with l libmalloc.a's mallopt()
  2309. X * 
  2310. X * Revision 1.2  90/02/25  11:01:21  cpcahil
  2311. X * added support for malloc chain checking.
  2312. X * 
  2313. X * Revision 1.1  90/02/24  21:50:24  cpcahil
  2314. X * Initial revision
  2315. X * 
  2316. X * Revision 1.1  90/02/24  17:10:53  cpcahil
  2317. X * Initial revision
  2318. X * 
  2319. X */
  2320. END_OF_FILE
  2321. if test 2654 -ne `wc -c <'mallopt.c'`; then
  2322.     echo shar: \"'mallopt.c'\" unpacked with wrong size!
  2323. fi
  2324. # end of 'mallopt.c'
  2325. fi
  2326. if test -f 'testerr.c' -a "${1}" != "-c" ; then 
  2327.   echo shar: Will not clobber existing file \"'testerr.c'\"
  2328. else
  2329. echo shar: Extracting \"'testerr.c'\" \(1529 characters\)
  2330. sed "s/^X//" >'testerr.c' <<'END_OF_FILE'
  2331. X#include <stdio.h>
  2332. X#if __STDC__
  2333. X#include <stdlib.h>
  2334. X#endif
  2335. X#include "malloc.h"
  2336. X
  2337. Xint
  2338. Xmain(argc,argv)
  2339. X    int              argc;
  2340. X    char            **argv[];
  2341. X{
  2342. X
  2343. X    char            * s;
  2344. X    char            * t;
  2345. X    union malloptarg      m;
  2346. X
  2347. X    m.i = 1;
  2348. X    mallopt(MALLOC_CKCHAIN,m);
  2349. X
  2350. X
  2351. X    t = malloc(20);
  2352. X
  2353. X    s = malloc(10);
  2354. X
  2355. X    fprintf(stderr,"-------------------------------------\n");
  2356. X    fprintf(stderr,"Error from strcpy() - out of bounds\n");
  2357. X    strncpy(s,t,11);
  2358. X
  2359. X    fprintf(stderr,"-------------------------------------\n");
  2360. X    fprintf(stderr,"Error from memset() - out of bounds\n");
  2361. X    memset(t,' ',21);
  2362. X
  2363. X    fprintf(stderr,"-------------------------------------\n");
  2364. X    fprintf(stderr,"Error from free() - overrun\n");
  2365. X    free(t);
  2366. X
  2367. X    fprintf(stderr,"-------------------------------------\n");
  2368. X    fprintf(stderr,"NO error from bzero\n");
  2369. X    bzero(s,10);
  2370. X
  2371. X    fprintf(stderr,"-------------------------------------\n");
  2372. X    fprintf(stderr,"Error from bzero() - out of bounds\n");
  2373. X    bzero(s,11);
  2374. X
  2375. X    fprintf(stderr,"-------------------------------------\n");
  2376. X    fprintf(stderr,"Error from free() - overrun\n");
  2377. X    free(s);
  2378. X
  2379. X    fprintf(stderr,"-------------------------------------\n");
  2380. X    fprintf(stderr,"Error from free() - invalid magic\n");
  2381. X    free(s);
  2382. X
  2383. X    s = malloc(10);
  2384. X    t = malloc(500);     /* do this to make sure memset doesnt core */
  2385. X
  2386. X    fprintf(stderr,"-------------------------------------\n");
  2387. X    fprintf(stderr,"Error from memset() - out of bounds\n");
  2388. X    memset(s,'1',100);
  2389. X    
  2390. X    fprintf(stderr,"-------------------------------------\n");
  2391. X    fprintf(stderr,"Error from malloc() - chain broken\n");
  2392. X    t = malloc(10);
  2393. X    
  2394. X    return(0);
  2395. X}
  2396. X
  2397. END_OF_FILE
  2398. if test 1529 -ne `wc -c <'testerr.c'`; then
  2399.     echo shar: \"'testerr.c'\" unpacked with wrong size!
  2400. fi
  2401. # end of 'testerr.c'
  2402. fi
  2403. if test -f 'tostring.c' -a "${1}" != "-c" ; then 
  2404.   echo shar: Will not clobber existing file \"'tostring.c'\"
  2405. else
  2406. echo shar: Extracting \"'tostring.c'\" \(2892 characters\)
  2407. sed "s/^X//" >'tostring.c' <<'END_OF_FILE'
  2408. X/*
  2409. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  2410. X * You may copy, distribute, and use this software as long as this
  2411. X * copyright statement is not removed.
  2412. X */
  2413. X#include "tostring.h"
  2414. X
  2415. X/*
  2416. X * Function:    tostring()
  2417. X *
  2418. X * Purpose:    to convert an integer to an ascii display string
  2419. X *
  2420. X * Arguments:    buf    - place to put the 
  2421. X *        val    - integer to convert
  2422. X *        len    - length of output field (0 if just enough to hold data)
  2423. X *        base    - base for number conversion (only works for base <= 16)
  2424. X *        fill    - fill char when len > # digits
  2425. X *
  2426. X * Returns:    length of string
  2427. X *
  2428. X * Narrative:    IF fill character is non-blank
  2429. X *            Determine base
  2430. X *                If base is HEX
  2431. X *                    add "0x" to begining of string
  2432. X *                IF base is OCTAL
  2433. X *                    add "0" to begining of string
  2434. X *
  2435. X *        While value is greater than zero
  2436. X *            use val % base as index into xlation str to get cur char
  2437. X *            divide val by base
  2438. X *
  2439. X *        Determine fill-in length
  2440. X *
  2441. X *        Fill in fill chars
  2442. X *
  2443. X *        Copy in number
  2444. X *        
  2445. X *
  2446. X * Mod History:    
  2447. X *   90/01/24    cpcahil        Initial revision.
  2448. X */
  2449. X
  2450. X#ifndef lint
  2451. Xstatic
  2452. Xchar rcs_hdr[] = "$Id: tostring.c,v 1.5 1991/11/25 14:42:06 cpcahil Exp $";
  2453. X#endif
  2454. X
  2455. X#define T_LEN 15
  2456. X
  2457. Xint
  2458. Xtostring(buf,val,len,base,fill)
  2459. X    int      base;
  2460. X    char    * buf;
  2461. X    char      fill;
  2462. X    int      len;
  2463. X    long      val;
  2464. X    
  2465. X{
  2466. X    char    * bufstart = buf;
  2467. X    int      i = T_LEN;
  2468. X    char    * xbuf = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  2469. X    char      tbuf[T_LEN];
  2470. X
  2471. X    /*
  2472. X     * if we are filling with non-blanks, make sure the
  2473. X     * proper start string is added
  2474. X     */
  2475. X    if( fill != ' ' )
  2476. X    {
  2477. X        switch(base)
  2478. X        {
  2479. X            case B_HEX:
  2480. X                if( (len == 0) ||  (len > 2) )
  2481. X                {
  2482. X                    *(buf++) = '0';
  2483. X                    *(buf++) = 'x';
  2484. X                    if( len )
  2485. X                    {
  2486. X                        len -= 2;
  2487. X                    }
  2488. X                }
  2489. X                break;
  2490. X            case B_OCTAL:
  2491. X                *(buf++) = fill;
  2492. X                if( len )
  2493. X                {
  2494. X                    len--;
  2495. X                }
  2496. X                break;
  2497. X            default:
  2498. X                break;
  2499. X        }
  2500. X    }
  2501. X
  2502. X    while( val > 0 )
  2503. X    {
  2504. X        tbuf[--i] = xbuf[val % (long)base];
  2505. X        val = val / (long)base;
  2506. X    }
  2507. X
  2508. X    if( len )
  2509. X    {
  2510. X        len -= (T_LEN - i);
  2511. X
  2512. X        if( len > 0 )
  2513. X        {
  2514. X            while(len-- > 0)
  2515. X            {
  2516. X                *(buf++) = fill;
  2517. X            }
  2518. X        }
  2519. X        else
  2520. X        {
  2521. X            /* 
  2522. X             * string is too long so we must truncate
  2523. X             * off some characters.  We do this the easiest
  2524. X             * way by just incrementing i.  This means the
  2525. X             * most significant digits are lost.
  2526. X             */
  2527. X            while( len++ < 0 )
  2528. X            {
  2529. X                i++;
  2530. X            }
  2531. X        }
  2532. X    }
  2533. X
  2534. X    while( i < T_LEN )
  2535. X    {
  2536. X        *(buf++) = tbuf[i++];
  2537. X    }
  2538. X
  2539. X    return( (int) (buf - bufstart) );
  2540. X
  2541. X} /* tostring(... */
  2542. X
  2543. X/*
  2544. X * $Log: tostring.c,v $
  2545. X * Revision 1.5  1991/11/25  14:42:06  cpcahil
  2546. X * Final changes in preparation for patch 4 release
  2547. X *
  2548. X * Revision 1.4  90/05/11  00:13:11  cpcahil
  2549. X * added copyright statment
  2550. X * 
  2551. X * Revision 1.3  90/02/24  21:50:33  cpcahil
  2552. X * lots of lint fixes
  2553. X * 
  2554. X * Revision 1.2  90/02/24  17:29:42  cpcahil
  2555. X * changed $Header to $Id so full path wouldnt be included as part of rcs 
  2556. X * id string
  2557. X * 
  2558. X * Revision 1.1  90/02/22  23:17:44  cpcahil
  2559. X * Initial revision
  2560. X * 
  2561. X */
  2562. END_OF_FILE
  2563. if test 2892 -ne `wc -c <'tostring.c'`; then
  2564.     echo shar: \"'tostring.c'\" unpacked with wrong size!
  2565. fi
  2566. # end of 'tostring.c'
  2567. fi
  2568. echo shar: End of archive 3 \(of 5\).
  2569. cp /dev/null ark3isdone
  2570. MISSING=""
  2571. for I in 1 2 3 4 5 ; do
  2572.     if test ! -f ark${I}isdone ; then
  2573.     MISSING="${MISSING} ${I}"
  2574.     fi
  2575. done
  2576. if test "${MISSING}" = "" ; then
  2577.     echo You have unpacked all 5 archives.
  2578.     rm -f ark[1-9]isdone
  2579. else
  2580.     echo You still need to unpack the following archives:
  2581.     echo "        " ${MISSING}
  2582. fi
  2583. ##  End of shell archive.
  2584. exit 0
  2585.  
  2586. exit 0 # Just in case...
  2587.