1: /* pathalias -- by steve bellovin, as told to peter honeyman */ 2: #ifndef lint 3: static char *sccsid = "@(#)mem.c 9.1 87/10/04"; 4: #endif 5: 6: #include "def.h" 7: 8: /* exports */ 9: extern void freelink(), wasted(), nomem(); 10: extern long allocation(); 11: long Ncount; 12: 13: /* imports */ 14: extern char *sbrk(); 15: extern char *Netchars; 16: extern int Vflag; 17: extern void die(); 18: #ifdef TMPFILES 19: extern off_t lseek(); 20: extern int fdnode, fdlink, fdname; 21: extern node *getnode(), nullnode; 22: extern link *getlink(), nulllink; 23: #else /*TMPFILES*/ 24: 25: /* privates */ 26: static link *Lcache; 27: #endif /*TMPFILES*/ 28: static unsigned int Memwaste; 29: 30: #ifndef TMPFILES 31: p_link 32: newlink() 33: { register link *rval; 34: 35: if (Lcache) { 36: rval = Lcache; 37: Lcache = Lcache->l_next; 38: strclear((char *) rval, sizeof(link)); 39: } else if ((rval = (link * ) calloc(1, sizeof(link))) == 0) 40: nomem(); 41: return rval; 42: } 43: #else /*TMPFILES*/ 44: p_link 45: newlink() 46: { 47: p_link l_seq; 48: 49: /* 50: * We find the end of the file, use it to get the sequence number of 51: * the link (which we use instead of an offset, since the offset would 52: * have to be long and the sequence number can be short), and 53: * finally zero out the appropriate spot in the link temporary file. 54: * We then fill in and return the sequence number. 55: */ 56: l_seq = lseek(fdlink, (off_t) 0, L_XTND) / sizeof(link); 57: 58: if (write(fdlink, (char *) &nulllink, sizeof(link)) < 0) { 59: perror("newlink"); 60: exit(1); 61: } 62: getlink(l_seq)->l_seq = l_seq; 63: 64: return l_seq; 65: } 66: #endif /*TMPFILES*/ 67: 68: /* caution: this destroys the contents of l_next */ 69: /*ARGSUSED*/ 70: void 71: freelink(l) 72: p_link l; 73: { 74: #ifndef TMPFILES 75: l->l_next = Lcache; 76: Lcache = l; 77: #else /*TMPFILES*/ 78: #endif /*TMPFILES*/ 79: } 80: 81: #ifndef TMPFILES 82: p_node 83: newnode() 84: { 85: register node *rval; 86: 87: if ((rval = (node * ) calloc(1, sizeof(node))) == 0) 88: nomem(); 89: Ncount++; 90: return rval; 91: } 92: #else /*TMPFILES*/ 93: p_node 94: newnode() 95: { 96: register p_node n_seq; 97: 98: /* 99: * We find the end of the file, use it to get the sequence number of 100: * the node (which we use instead of an offset, since the offset would 101: * have to be long and the sequence number can be short), and 102: * finally zero out the appropriate spot in the node temporary file. 103: * We then fill in and return the sequence number. 104: */ 105: n_seq = lseek(fdnode, (off_t) 0, L_XTND) / sizeof(node); 106: 107: if (write(fdnode, (char *) &nullnode, sizeof(node)) < 0) { 108: perror("newnode"); 109: exit(1); 110: } 111: getnode(n_seq)->n_seq = n_seq; 112: 113: Ncount++; 114: return n_seq; 115: } 116: #endif /*TMPFILES*/ 117: 118: char * 119: strsave(s) 120: char *s; 121: { register char *r; 122: 123: if ((r = malloc((unsigned) strlen(s) + 1)) == 0) 124: nomem(); 125: (void) strcpy(r, s); 126: return r; 127: } 128: 129: #ifndef strclear 130: void 131: strclear(str, len) 132: register char *str; 133: register long len; 134: { 135: while (--len >= 0) 136: *str++ = 0; 137: } 138: #endif /*strclear*/ 139: 140: p_node * 141: newtable(size) 142: long size; 143: { register p_node *rval; 144: 145: if ((rval = (p_node *) calloc(1, (unsigned int) size * sizeof(p_node))) == 0) 146: nomem(); 147: return rval; 148: } 149: 150: /*ARGSUSED*/ 151: freetable(t, size) 152: p_node *t; 153: long size; 154: { 155: #ifdef MYMALLOC 156: addtoheap((char *) t, size * sizeof(p_node)); 157: #else 158: free((char *) t); 159: #endif 160: } 161: 162: void 163: nomem() 164: { 165: static char epitaph[128]; 166: 167: sprintf(epitaph, "out of memory (%ldk allocated)", allocation()); 168: die(epitaph); 169: } 170: 171: /* data space allocation -- main sets `dataspace' very early */ 172: long 173: allocation() 174: { 175: static char *dataspace; 176: long rval; 177: 178: if (dataspace == 0) { /* first time */ 179: dataspace = sbrk(0); /* &end? */ 180: return 0; 181: } 182: #ifndef TMPFILES 183: rval = (sbrk(0) - dataspace)/1024; 184: #else /*TMPFILES*/ 185: rval = (long) sbrk(0)/1024; /* break is useful on small machines */ 186: #endif /*TMPFILES*/ 187: if (rval < 0) /* funny architecture? */ 188: rval = -rval; 189: return rval; 190: } 191: 192: /* how much memory has been wasted? */ 193: void 194: wasted() 195: { 196: if (Memwaste == 0) 197: return; 198: vprintf(stderr, "memory allocator wasted %ld bytes\n", Memwaste); 199: } 200: 201: #ifdef MYMALLOC 202: 203: /* use c library malloc/calloc here, and here only */ 204: #undef malloc 205: #undef calloc 206: extern char *malloc(), *calloc(); 207: 208: /* allocate in MBUFSIZ chunks. 4k works ok (less 16 for malloc quirks). */ 209: #define MBUFSIZ (4 * 1024 - 16) 210: 211: /* 212: * mess with ALIGN at your peril. longword (== 0 mod 4) 213: * alignment seems to work everywhere. 214: */ 215: 216: #define ALIGN 2 217: 218: typedef struct heap heap; 219: struct heap { 220: heap *h_next; 221: long h_size; 222: }; 223: 224: static heap *Mheap; /* not to be confused with a priority queue */ 225: 226: addtoheap(p, size) 227: char *p; 228: long size; 229: { int adjustment; 230: heap *pheap; 231: 232: /* p is aligned, but it doesn't hurt to check */ 233: adjustment = align(p); 234: p += adjustment; 235: size -= adjustment; 236: 237: if (size < 1024) 238: return; /* can't happen */ 239: pheap = (heap *) p; /* pheap is shorthand */ 240: pheap->h_next = Mheap; 241: pheap->h_size = size; 242: Mheap = pheap; 243: } 244: 245: /* 246: * buffered malloc() 247: * returns space initialized to 0. calloc isn't used, since 248: * strclear can be faster. 249: * 250: * free is ignored, except for very large objects, 251: * which are returned to the heap with addtoheap(). 252: */ 253: 254: char * 255: mymalloc(n) 256: register unsigned int n; 257: { static unsigned int size; /* how much do we have on hand? */ 258: static char *mstash; /* where is it? */ 259: register char *rval; 260: 261: if (n >= 1024) { /* for hash table */ 262: rval = malloc(n); /* aligned */ 263: if (rval) 264: strclear(rval, n); 265: return rval; 266: } 267: 268: n += align((char *) n); /* keep everything aligned */ 269: 270: if (n > size) { 271: Memwaste += size; /* toss the fragment */ 272: /* look in the heap */ 273: if (Mheap) { 274: mstash = (char *) Mheap; /* aligned */ 275: size = Mheap->h_size; 276: Mheap = Mheap->h_next; 277: } else { 278: mstash = malloc(MBUFSIZ); /* aligned */ 279: if (mstash == 0) { 280: size = 0; 281: return 0; 282: } 283: size = MBUFSIZ; 284: } 285: strclear(mstash, size); /* what if size > 2^16? */ 286: } 287: rval = mstash; 288: mstash += n; 289: size -= n; 290: return rval; 291: } 292: 293: /* 294: * what's the (mis-)alignment of n? return the complement of 295: * n mod 2^ALIGN 296: */ 297: align(n) 298: char *n; 299: { register int abits; /* misalignment bits in n */ 300: 301: abits = (int) n & ~(0xff << ALIGN) & 0xff; 302: if (abits == 0) 303: return 0; 304: return (1 << ALIGN) - abits; 305: } 306: 307: #endif /*MYMALLOC*/