10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright(c) 1988 AT&T 240Sstevel@tonic-gate * All Rights Reserved 250Sstevel@tonic-gate * 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 29*1282Sab196087 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 300Sstevel@tonic-gate * Use is subject to license terms. 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include "mcs.h" 360Sstevel@tonic-gate #include "extern.h" 370Sstevel@tonic-gate #include "gelf.h" 380Sstevel@tonic-gate 390Sstevel@tonic-gate /* 400Sstevel@tonic-gate * Function prototypes. 410Sstevel@tonic-gate */ 420Sstevel@tonic-gate static void docompress(section_info_table *); 430Sstevel@tonic-gate static char *compress(char *, size_t *); 440Sstevel@tonic-gate static void doappend(char *, section_info_table *); 450Sstevel@tonic-gate static void doprint(char *, section_info_table *); 460Sstevel@tonic-gate static void dozap(section_info_table *); 470Sstevel@tonic-gate static int dohash(char *); 480Sstevel@tonic-gate 490Sstevel@tonic-gate 500Sstevel@tonic-gate 510Sstevel@tonic-gate /* 520Sstevel@tonic-gate * Apply the actions specified by the user. 530Sstevel@tonic-gate */ 540Sstevel@tonic-gate int 550Sstevel@tonic-gate apply_action(section_info_table *info, char *cur_file, Cmd_Info *cmd_info) 560Sstevel@tonic-gate { 570Sstevel@tonic-gate int act_index; 580Sstevel@tonic-gate int ret = 0; 590Sstevel@tonic-gate GElf_Shdr shdr; 600Sstevel@tonic-gate 610Sstevel@tonic-gate (void) gelf_getshdr(info->scn, &shdr); 620Sstevel@tonic-gate for (act_index = 0; act_index < actmax; act_index++) { 630Sstevel@tonic-gate Action[act_index].a_cnt++; 640Sstevel@tonic-gate switch (Action[act_index].a_action) { 650Sstevel@tonic-gate case ACT_ZAP: 660Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 670Sstevel@tonic-gate break; 680Sstevel@tonic-gate dozap(info); 690Sstevel@tonic-gate SET_ACTION(info->flags, ACT_ZAP); 700Sstevel@tonic-gate SET_MODIFIED(info->flags); 710Sstevel@tonic-gate break; 720Sstevel@tonic-gate case ACT_PRINT: 730Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 740Sstevel@tonic-gate break; 750Sstevel@tonic-gate if (shdr.sh_type == SHT_NOBITS) { 760Sstevel@tonic-gate error_message(ACT_PRINT_ERROR, 770Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 780Sstevel@tonic-gate prog, cur_file, SECT_NAME); 790Sstevel@tonic-gate break; 800Sstevel@tonic-gate } 810Sstevel@tonic-gate doprint(cur_file, info); 820Sstevel@tonic-gate break; 830Sstevel@tonic-gate case ACT_DELETE: 840Sstevel@tonic-gate /* 850Sstevel@tonic-gate * If I am strip command, this is the 860Sstevel@tonic-gate * only action I can take. 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 890Sstevel@tonic-gate break; 900Sstevel@tonic-gate if (GET_LOC(info->flags) == IN) { 910Sstevel@tonic-gate /* 920Sstevel@tonic-gate * If I am 'strip', I have to 930Sstevel@tonic-gate * unset the candidate flag and 940Sstevel@tonic-gate * unset the error return code. 950Sstevel@tonic-gate */ 960Sstevel@tonic-gate if (CHK_OPT(info, I_AM_STRIP)) { 970Sstevel@tonic-gate ret = 0; 980Sstevel@tonic-gate UNSET_CANDIDATE(info->flags); 990Sstevel@tonic-gate } else { 1000Sstevel@tonic-gate ret++; 1010Sstevel@tonic-gate error_message(ACT_DELETE1_ERROR, 1020Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 1030Sstevel@tonic-gate prog, cur_file, info->name); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate break; 1060Sstevel@tonic-gate } else if (info->rel_loc == IN) { 1070Sstevel@tonic-gate /* 1080Sstevel@tonic-gate * If I am 'strip', I have to 1090Sstevel@tonic-gate * unset the candidate flag and 1100Sstevel@tonic-gate * unset the error return code. 1110Sstevel@tonic-gate */ 1120Sstevel@tonic-gate if (CHK_OPT(info, I_AM_STRIP)) { 1130Sstevel@tonic-gate ret = 0; 1140Sstevel@tonic-gate UNSET_CANDIDATE(info->flags); 1150Sstevel@tonic-gate } else { 1160Sstevel@tonic-gate ret++; 1170Sstevel@tonic-gate error_message(ACT_DELETE2_ERROR, 1180Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 1190Sstevel@tonic-gate prog, cur_file, SECT_NAME, 1200Sstevel@tonic-gate info->rel_name); 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate break; 1230Sstevel@tonic-gate } else if (GET_LOC(info->flags) == PRIOR) { 1240Sstevel@tonic-gate /* 1250Sstevel@tonic-gate * I can not delete this 1260Sstevel@tonic-gate * section. I can only NULL 1270Sstevel@tonic-gate * this out. 1280Sstevel@tonic-gate */ 1290Sstevel@tonic-gate info->secno = (GElf_Word)NULLED; 1300Sstevel@tonic-gate (cmd_info->no_of_nulled)++; 1310Sstevel@tonic-gate } else { 1320Sstevel@tonic-gate info->secno = (GElf_Word)DELETED; 1330Sstevel@tonic-gate (cmd_info->no_of_delete)++; 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate SET_ACTION(info->flags, ACT_DELETE); 1360Sstevel@tonic-gate SET_MODIFIED(info->flags); 1370Sstevel@tonic-gate break; 1380Sstevel@tonic-gate case ACT_APPEND: 1390Sstevel@tonic-gate if (shdr.sh_type == SHT_NOBITS) { 1400Sstevel@tonic-gate ret++; 1410Sstevel@tonic-gate error_message(ACT_APPEND1_ERROR, 1420Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 1430Sstevel@tonic-gate prog, cur_file, SECT_NAME); 1440Sstevel@tonic-gate break; 1450Sstevel@tonic-gate } else if (GET_LOC(info->flags) == IN) { 1460Sstevel@tonic-gate ret++; 1470Sstevel@tonic-gate error_message(ACT_APPEND2_ERROR, 1480Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 1490Sstevel@tonic-gate prog, cur_file, SECT_NAME); 1500Sstevel@tonic-gate break; 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate doappend(Action[act_index].a_string, info); 1530Sstevel@tonic-gate (cmd_info->no_of_append)++; 1540Sstevel@tonic-gate info->secno = info->osecno; 1550Sstevel@tonic-gate SET_ACTION(info->flags, ACT_APPEND); 1560Sstevel@tonic-gate SET_MODIFIED(info->flags); 1570Sstevel@tonic-gate if (GET_LOC(info->flags) == PRIOR) 1580Sstevel@tonic-gate info->secno = (GElf_Word)EXPANDED; 1590Sstevel@tonic-gate break; 1600Sstevel@tonic-gate case ACT_COMPRESS: 1610Sstevel@tonic-gate /* 1620Sstevel@tonic-gate * If this section is already deleted, 1630Sstevel@tonic-gate * don't do anything. 1640Sstevel@tonic-gate */ 1650Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 1660Sstevel@tonic-gate break; 1670Sstevel@tonic-gate if (shdr.sh_type == SHT_NOBITS) { 1680Sstevel@tonic-gate ret++; 1690Sstevel@tonic-gate error_message(ACT_COMPRESS1_ERROR, 1700Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 1710Sstevel@tonic-gate prog, cur_file, SECT_NAME); 1720Sstevel@tonic-gate break; 1730Sstevel@tonic-gate } else if (GET_LOC(info->flags) == IN) { 1740Sstevel@tonic-gate ret++; 1750Sstevel@tonic-gate error_message(ACT_COMPRESS2_ERROR, 1760Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 1770Sstevel@tonic-gate prog, cur_file, SECT_NAME); 1780Sstevel@tonic-gate break; 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate docompress(info); 1820Sstevel@tonic-gate (cmd_info->no_of_compressed)++; 1830Sstevel@tonic-gate SET_ACTION(info->flags, ACT_COMPRESS); 1840Sstevel@tonic-gate SET_MODIFIED(info->flags); 1850Sstevel@tonic-gate if (GET_LOC(info->flags) == PRIOR) 1860Sstevel@tonic-gate info->secno = (GElf_Word)SHRUNK; 1870Sstevel@tonic-gate break; 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate return (ret); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate /* 1940Sstevel@tonic-gate * ACT_ZAP 1950Sstevel@tonic-gate */ 1960Sstevel@tonic-gate static void 1970Sstevel@tonic-gate dozap(section_info_table *info) 1980Sstevel@tonic-gate { 1990Sstevel@tonic-gate Elf_Data *data; 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate info->mdata = data = malloc(sizeof (Elf_Data)); 2020Sstevel@tonic-gate if (data == NULL) { 2030Sstevel@tonic-gate error_message(MALLOC_ERROR, 2040Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 2050Sstevel@tonic-gate prog); 2060Sstevel@tonic-gate exit(1); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate *data = *info->data; 2090Sstevel@tonic-gate data->d_buf = calloc(1, data->d_size); 2100Sstevel@tonic-gate if (data->d_buf == NULL) { 2110Sstevel@tonic-gate error_message(MALLOC_ERROR, 2120Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 2130Sstevel@tonic-gate prog); 2140Sstevel@tonic-gate exit(1); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* 2190Sstevel@tonic-gate * ACT_PRINT 2200Sstevel@tonic-gate */ 2210Sstevel@tonic-gate static void 2220Sstevel@tonic-gate doprint(char *cur_file, section_info_table *info) 2230Sstevel@tonic-gate { 2240Sstevel@tonic-gate Elf_Data *data; 2250Sstevel@tonic-gate size_t temp_size; 2260Sstevel@tonic-gate char *temp_string; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate if (GET_MODIFIED(info->flags) == 0) 2290Sstevel@tonic-gate data = info->data; 2300Sstevel@tonic-gate else 2310Sstevel@tonic-gate data = info->mdata; 2320Sstevel@tonic-gate if (data == 0) 2330Sstevel@tonic-gate return; 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate temp_size = data->d_size; 2360Sstevel@tonic-gate temp_string = data->d_buf; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate if (temp_size == 0) 2390Sstevel@tonic-gate return; 2400Sstevel@tonic-gate (void) fprintf(stdout, "%s:\n", cur_file); 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate while (temp_size--) { 2430Sstevel@tonic-gate char c = *temp_string++; 2440Sstevel@tonic-gate switch (c) { 2450Sstevel@tonic-gate case '\0': 2460Sstevel@tonic-gate (void) putchar('\n'); 2470Sstevel@tonic-gate break; 2480Sstevel@tonic-gate default: 2490Sstevel@tonic-gate (void) putchar(c); 2500Sstevel@tonic-gate break; 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate (void) putchar('\n'); 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * ACT_APPEND 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate static void 2600Sstevel@tonic-gate doappend(char *a_string, section_info_table *info) 2610Sstevel@tonic-gate { 2620Sstevel@tonic-gate Elf_Data *data; 2630Sstevel@tonic-gate char *p; 2640Sstevel@tonic-gate size_t len; 2650Sstevel@tonic-gate char *tp; 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* 268*1282Sab196087 * Get the length of the string to be added. We accept any 269*1282Sab196087 * string (even null), as this is arbitrary user defined text. 270*1282Sab196087 * 271*1282Sab196087 * The caller expects this routine to replace a NULL info->mdata 272*1282Sab196087 * field with a pointer to a freshly allocated copy. Any attempt 273*1282Sab196087 * to optimize away a null string append would have to deal with 274*1282Sab196087 * that, as failing to do so will cause a segfault when the NULL 275*1282Sab196087 * mdata field is dereferenced. Accepting null strings in 276*1282Sab196087 * this very unimportant case eliminates the need for that. 2770Sstevel@tonic-gate */ 2780Sstevel@tonic-gate len = strlen(a_string); 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* 2810Sstevel@tonic-gate * Every modification operation will be done 2820Sstevel@tonic-gate * to a new Elf_Data descriptor. 2830Sstevel@tonic-gate */ 2840Sstevel@tonic-gate if (info->mdata == 0) { 2850Sstevel@tonic-gate /* 2860Sstevel@tonic-gate * mdata is not allocated yet. 2870Sstevel@tonic-gate * Allocate the data and set it. 2880Sstevel@tonic-gate */ 2890Sstevel@tonic-gate info->mdata = data = calloc(1, sizeof (Elf_Data)); 2900Sstevel@tonic-gate if (data == NULL) { 2910Sstevel@tonic-gate error_message(MALLOC_ERROR, 2920Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 2930Sstevel@tonic-gate prog); 2940Sstevel@tonic-gate exit(1); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate *data = *info->data; 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * Check if the section is deleted or not. 3000Sstevel@tonic-gate * Or if the size is 0 or not. 3010Sstevel@tonic-gate */ 3020Sstevel@tonic-gate if ((GET_ACTION(info->flags) == ACT_DELETE) || 3030Sstevel@tonic-gate data->d_size == 0) { 3040Sstevel@tonic-gate /* 3050Sstevel@tonic-gate * The section was deleated. 3060Sstevel@tonic-gate * But now, the user wants to add data to this 3070Sstevel@tonic-gate * section. 3080Sstevel@tonic-gate */ 3090Sstevel@tonic-gate data->d_buf = calloc(1, len + 2); 3100Sstevel@tonic-gate if (data->d_buf == 0) { 3110Sstevel@tonic-gate error_message(MALLOC_ERROR, 3120Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 3130Sstevel@tonic-gate prog); 3140Sstevel@tonic-gate exit(1); 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate tp = (char *)data->d_buf; 3170Sstevel@tonic-gate (void) memcpy(& tp[1], a_string, len + 1); 3180Sstevel@tonic-gate data->d_size = len + 2; 3190Sstevel@tonic-gate } else { 3200Sstevel@tonic-gate /* 3210Sstevel@tonic-gate * The user wants to add data to the section. 3220Sstevel@tonic-gate * I am not going to change the original data. 3230Sstevel@tonic-gate * Do the modification on the new one. 3240Sstevel@tonic-gate */ 3250Sstevel@tonic-gate p = malloc(len + 1 + data->d_size); 3260Sstevel@tonic-gate if (p == NULL) { 3270Sstevel@tonic-gate error_message(MALLOC_ERROR, 3280Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 3290Sstevel@tonic-gate prog); 3300Sstevel@tonic-gate exit(1); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate (void) memcpy(p, data->d_buf, data->d_size); 3330Sstevel@tonic-gate (void) memcpy(&p[data->d_size], a_string, len + 1); 3340Sstevel@tonic-gate data->d_buf = p; 3350Sstevel@tonic-gate data->d_size = data->d_size + len + 1; 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate } else { 3380Sstevel@tonic-gate /* 3390Sstevel@tonic-gate * mdata is already allocated. 3400Sstevel@tonic-gate * Modify it. 3410Sstevel@tonic-gate */ 3420Sstevel@tonic-gate data = info->mdata; 3430Sstevel@tonic-gate if ((GET_ACTION(info->flags) == ACT_DELETE) || 3440Sstevel@tonic-gate data->d_size == 0) { 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * The section was deleated. 3470Sstevel@tonic-gate * But now, the user wants to add data to this 3480Sstevel@tonic-gate * section. 3490Sstevel@tonic-gate */ 3500Sstevel@tonic-gate if (data->d_buf) 3510Sstevel@tonic-gate free(data->d_buf); 3520Sstevel@tonic-gate data->d_buf = calloc(1, len + 2); 3530Sstevel@tonic-gate if (data->d_buf == 0) { 3540Sstevel@tonic-gate error_message(MALLOC_ERROR, 3550Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 3560Sstevel@tonic-gate prog); 3570Sstevel@tonic-gate exit(1); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate tp = (char *)data->d_buf; 3600Sstevel@tonic-gate (void) memcpy(&tp[1], a_string, len + 1); 3610Sstevel@tonic-gate data->d_size = len + 2; 3620Sstevel@tonic-gate } else { 3630Sstevel@tonic-gate /* 3640Sstevel@tonic-gate * The user wants to add data to the section. 3650Sstevel@tonic-gate * I am not going to change the original data. 3660Sstevel@tonic-gate * Do the modification on the new one. 3670Sstevel@tonic-gate */ 3680Sstevel@tonic-gate p = malloc(len + 1 + data->d_size); 3690Sstevel@tonic-gate if (p == NULL) { 3700Sstevel@tonic-gate error_message(MALLOC_ERROR, 3710Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 3720Sstevel@tonic-gate prog); 3730Sstevel@tonic-gate exit(1); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate (void) memcpy(p, data->d_buf, data->d_size); 3760Sstevel@tonic-gate (void) memcpy(&p[data->d_size], a_string, len + 1); 3770Sstevel@tonic-gate free(data->d_buf); 3780Sstevel@tonic-gate data->d_buf = p; 3790Sstevel@tonic-gate data->d_size = data->d_size + len + 1; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate /* 3850Sstevel@tonic-gate * ACT_COMPRESS 3860Sstevel@tonic-gate */ 3870Sstevel@tonic-gate #define HALFLONG 16 3880Sstevel@tonic-gate #define low(x) (x&((1L<<HALFLONG)-1)) 3890Sstevel@tonic-gate #define high(x) (x>>HALFLONG) 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate static void 3920Sstevel@tonic-gate docompress(section_info_table *info) 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate Elf_Data *data; 3950Sstevel@tonic-gate size_t size; 3960Sstevel@tonic-gate char *buf; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate if (info->mdata == 0) { 3990Sstevel@tonic-gate /* 4000Sstevel@tonic-gate * mdata is not allocated yet. 4010Sstevel@tonic-gate * Allocate the data and set it. 4020Sstevel@tonic-gate */ 4030Sstevel@tonic-gate char *p; 4040Sstevel@tonic-gate info->mdata = data = calloc(1, sizeof (Elf_Data)); 4050Sstevel@tonic-gate if (data == NULL) { 4060Sstevel@tonic-gate error_message(MALLOC_ERROR, 4070Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 4080Sstevel@tonic-gate prog); 4090Sstevel@tonic-gate exit(1); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate *data = *info->data; 4120Sstevel@tonic-gate p = malloc(data->d_size); 4130Sstevel@tonic-gate (void) memcpy(p, (char *)data->d_buf, data->d_size); 4140Sstevel@tonic-gate data->d_buf = p; 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate size = info->mdata->d_size; 4170Sstevel@tonic-gate buf = (char *)info->mdata->d_buf; 4180Sstevel@tonic-gate buf = compress(buf, &size); 4190Sstevel@tonic-gate info->mdata->d_buf = buf; 4200Sstevel@tonic-gate info->mdata->d_size = size; 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate static char * 4240Sstevel@tonic-gate compress(char *str, size_t *size) 4250Sstevel@tonic-gate { 4260Sstevel@tonic-gate int hash; 4270Sstevel@tonic-gate int i; 4280Sstevel@tonic-gate size_t temp_string_size = 0; 4290Sstevel@tonic-gate size_t o_size = *size; 4300Sstevel@tonic-gate char *temp_string = str; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate int *hash_key; 4330Sstevel@tonic-gate size_t hash_num; 4340Sstevel@tonic-gate size_t hash_end; 4350Sstevel@tonic-gate size_t *hash_str; 4360Sstevel@tonic-gate char *strings; 4370Sstevel@tonic-gate size_t next_str; 4380Sstevel@tonic-gate size_t str_size; 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate hash_key = malloc(sizeof (int) * 200); 4410Sstevel@tonic-gate hash_end = 200; 4420Sstevel@tonic-gate hash_str = malloc(sizeof (size_t) * 200); 4430Sstevel@tonic-gate str_size = o_size+1; 4440Sstevel@tonic-gate strings = malloc(str_size); 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if (hash_key == NULL || hash_str == NULL || strings == NULL) { 4470Sstevel@tonic-gate error_message(MALLOC_ERROR, 4480Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 4490Sstevel@tonic-gate prog); 4500Sstevel@tonic-gate mcs_exit(FAILURE); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate hash_num = 0; 4540Sstevel@tonic-gate next_str = 0; 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate while (temp_string_size < o_size) { 4570Sstevel@tonic-gate size_t pos; 4580Sstevel@tonic-gate char c; 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * Get a string 4610Sstevel@tonic-gate */ 4620Sstevel@tonic-gate pos = next_str; 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate while ((c = *(temp_string++)) != '\0' && 4650Sstevel@tonic-gate (temp_string_size + (next_str - pos)) <= o_size) { 4660Sstevel@tonic-gate if (next_str >= str_size) { 4670Sstevel@tonic-gate str_size *= 2; 4680Sstevel@tonic-gate if ((strings = (char *) 4690Sstevel@tonic-gate realloc(strings, str_size)) == NULL) { 4700Sstevel@tonic-gate error_message(MALLOC_ERROR, 4710Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 4720Sstevel@tonic-gate prog); 4730Sstevel@tonic-gate mcs_exit(FAILURE); 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate strings[next_str++] = c; 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate if (next_str >= str_size) { 4800Sstevel@tonic-gate str_size *= 2; 4810Sstevel@tonic-gate if ((strings = (char *) 4820Sstevel@tonic-gate realloc(strings, str_size)) == NULL) { 4830Sstevel@tonic-gate error_message(MALLOC_ERROR, 4840Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 4850Sstevel@tonic-gate prog); 4860Sstevel@tonic-gate mcs_exit(FAILURE); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate strings[next_str++] = NULL; 4900Sstevel@tonic-gate /* 4910Sstevel@tonic-gate * End get string 4920Sstevel@tonic-gate */ 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate temp_string_size += (next_str - pos); 4950Sstevel@tonic-gate hash = dohash(pos + strings); 4960Sstevel@tonic-gate for (i = 0; i < hash_num; i++) { 4970Sstevel@tonic-gate if (hash != hash_key[i]) 4980Sstevel@tonic-gate continue; 4990Sstevel@tonic-gate if (strcmp(pos + strings, hash_str[i] + strings) == 0) 5000Sstevel@tonic-gate break; 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate if (i != hash_num) { 5030Sstevel@tonic-gate next_str = pos; 5040Sstevel@tonic-gate continue; 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate if (hash_num == hash_end) { 5070Sstevel@tonic-gate hash_end *= 2; 5080Sstevel@tonic-gate hash_key = realloc((char *)hash_key, 5090Sstevel@tonic-gate hash_end * sizeof (int)); 5100Sstevel@tonic-gate hash_str = realloc((char *)hash_str, 5110Sstevel@tonic-gate hash_end * sizeof (size_t)); 5120Sstevel@tonic-gate if (hash_key == NULL || hash_str == NULL) { 5130Sstevel@tonic-gate error_message(MALLOC_ERROR, 5140Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 5150Sstevel@tonic-gate prog); 5160Sstevel@tonic-gate mcs_exit(FAILURE); 5170Sstevel@tonic-gate } 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate hash_key[hash_num] = hash; 5200Sstevel@tonic-gate hash_str[hash_num++] = pos; 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate /* 5240Sstevel@tonic-gate * Clean up 5250Sstevel@tonic-gate */ 5260Sstevel@tonic-gate free(hash_key); 5270Sstevel@tonic-gate free(hash_str); 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* 5300Sstevel@tonic-gate * Return 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate if (next_str != o_size) { 5330Sstevel@tonic-gate /* 5340Sstevel@tonic-gate * string compressed. 5350Sstevel@tonic-gate */ 5360Sstevel@tonic-gate *size = next_str; 5370Sstevel@tonic-gate free(str); 5380Sstevel@tonic-gate str = malloc(next_str); 5390Sstevel@tonic-gate (void) memcpy(str, strings, next_str); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate free(strings); 5420Sstevel@tonic-gate return (str); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate static int 5460Sstevel@tonic-gate dohash(char *str) 5470Sstevel@tonic-gate { 5480Sstevel@tonic-gate long sum; 5490Sstevel@tonic-gate unsigned shift; 5500Sstevel@tonic-gate int t; 5510Sstevel@tonic-gate sum = 1; 5520Sstevel@tonic-gate for (shift = 0; (t = *str++) != NULL; shift += 7) { 5530Sstevel@tonic-gate sum += (long)t << (shift %= HALFLONG); 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate sum = low(sum) + high(sum); 5560Sstevel@tonic-gate /* LINTED */ 5570Sstevel@tonic-gate return ((short)low(sum) + (short)high(sum)); 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate /* 5610Sstevel@tonic-gate * Append an item to the specified list, and return a pointer to the list 5620Sstevel@tonic-gate * node created. 5630Sstevel@tonic-gate */ 5640Sstevel@tonic-gate Listnode * 5650Sstevel@tonic-gate list_appendc(List *lst, const void *item) 5660Sstevel@tonic-gate { 5670Sstevel@tonic-gate Listnode *_lnp; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate if ((_lnp = malloc(sizeof (Listnode))) == (Listnode *)0) 5700Sstevel@tonic-gate return (0); 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate _lnp->data = (void *)item; 5730Sstevel@tonic-gate _lnp->next = NULL; 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate if (lst->head == NULL) 5760Sstevel@tonic-gate lst->tail = lst->head = _lnp; 5770Sstevel@tonic-gate else { 5780Sstevel@tonic-gate lst->tail->next = _lnp; 5790Sstevel@tonic-gate lst->tail = lst->tail->next; 5800Sstevel@tonic-gate } 5810Sstevel@tonic-gate return (_lnp); 5820Sstevel@tonic-gate } 583