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 55154Sab196087 * Common Development and Distribution License (the "License"). 65154Sab196087 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 220Sstevel@tonic-gate * Copyright(c) 1988 AT&T 230Sstevel@tonic-gate * All Rights Reserved 240Sstevel@tonic-gate * 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* 28*8223SAli.Bahrami@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 290Sstevel@tonic-gate * Use is subject to license terms. 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include "mcs.h" 330Sstevel@tonic-gate #include "extern.h" 340Sstevel@tonic-gate #include "gelf.h" 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * Function prototypes. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate static void docompress(section_info_table *); 400Sstevel@tonic-gate static char *compress(char *, size_t *); 410Sstevel@tonic-gate static void doappend(char *, section_info_table *); 420Sstevel@tonic-gate static void doprint(char *, section_info_table *); 430Sstevel@tonic-gate static void dozap(section_info_table *); 440Sstevel@tonic-gate static int dohash(char *); 450Sstevel@tonic-gate 460Sstevel@tonic-gate 470Sstevel@tonic-gate 480Sstevel@tonic-gate /* 490Sstevel@tonic-gate * Apply the actions specified by the user. 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate int 520Sstevel@tonic-gate apply_action(section_info_table *info, char *cur_file, Cmd_Info *cmd_info) 530Sstevel@tonic-gate { 540Sstevel@tonic-gate int act_index; 550Sstevel@tonic-gate int ret = 0; 560Sstevel@tonic-gate GElf_Shdr shdr; 570Sstevel@tonic-gate 580Sstevel@tonic-gate (void) gelf_getshdr(info->scn, &shdr); 590Sstevel@tonic-gate for (act_index = 0; act_index < actmax; act_index++) { 600Sstevel@tonic-gate Action[act_index].a_cnt++; 610Sstevel@tonic-gate switch (Action[act_index].a_action) { 620Sstevel@tonic-gate case ACT_ZAP: 630Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 640Sstevel@tonic-gate break; 650Sstevel@tonic-gate dozap(info); 660Sstevel@tonic-gate SET_ACTION(info->flags, ACT_ZAP); 670Sstevel@tonic-gate SET_MODIFIED(info->flags); 680Sstevel@tonic-gate break; 690Sstevel@tonic-gate case ACT_PRINT: 700Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 710Sstevel@tonic-gate break; 720Sstevel@tonic-gate if (shdr.sh_type == SHT_NOBITS) { 735154Sab196087 error_message(ACT_PRINT_ERROR, PLAIN_ERROR, 745154Sab196087 (char *)0, prog, cur_file, SECT_NAME); 750Sstevel@tonic-gate break; 760Sstevel@tonic-gate } 770Sstevel@tonic-gate doprint(cur_file, info); 780Sstevel@tonic-gate break; 790Sstevel@tonic-gate case ACT_DELETE: 800Sstevel@tonic-gate /* 810Sstevel@tonic-gate * If I am strip command, this is the 820Sstevel@tonic-gate * only action I can take. 830Sstevel@tonic-gate */ 840Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE) 850Sstevel@tonic-gate break; 860Sstevel@tonic-gate if (GET_LOC(info->flags) == IN) { 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * If I am 'strip', I have to 890Sstevel@tonic-gate * unset the candidate flag and 900Sstevel@tonic-gate * unset the error return code. 910Sstevel@tonic-gate */ 920Sstevel@tonic-gate if (CHK_OPT(info, I_AM_STRIP)) { 930Sstevel@tonic-gate ret = 0; 940Sstevel@tonic-gate UNSET_CANDIDATE(info->flags); 950Sstevel@tonic-gate } else { 965154Sab196087 char *name = info->name; 975154Sab196087 980Sstevel@tonic-gate ret++; 995154Sab196087 if (name == NULL) 1005154Sab196087 name = gettext("<unknown>"); 1010Sstevel@tonic-gate error_message(ACT_DELETE1_ERROR, 1025154Sab196087 PLAIN_ERROR, (char *)0, 1035154Sab196087 prog, cur_file, 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, 1185154Sab196087 PLAIN_ERROR, (char *)0, 1195154Sab196087 prog, cur_file, SECT_NAME, 1205154Sab196087 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, 1425154Sab196087 PLAIN_ERROR, (char *)0, 1435154Sab196087 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, 1485154Sab196087 PLAIN_ERROR, (char *)0, 1495154Sab196087 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, 1705154Sab196087 PLAIN_ERROR, (char *)0, 1715154Sab196087 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, 1765154Sab196087 PLAIN_ERROR, (char *)0, 1775154Sab196087 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) { 2035154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 204*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate *data = *info->data; 2070Sstevel@tonic-gate data->d_buf = calloc(1, data->d_size); 2080Sstevel@tonic-gate if (data->d_buf == NULL) { 2095154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 210*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* 2150Sstevel@tonic-gate * ACT_PRINT 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate static void 2180Sstevel@tonic-gate doprint(char *cur_file, section_info_table *info) 2190Sstevel@tonic-gate { 2200Sstevel@tonic-gate Elf_Data *data; 2210Sstevel@tonic-gate size_t temp_size; 2220Sstevel@tonic-gate char *temp_string; 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate if (GET_MODIFIED(info->flags) == 0) 2250Sstevel@tonic-gate data = info->data; 2260Sstevel@tonic-gate else 2270Sstevel@tonic-gate data = info->mdata; 2280Sstevel@tonic-gate if (data == 0) 2290Sstevel@tonic-gate return; 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate temp_size = data->d_size; 2320Sstevel@tonic-gate temp_string = data->d_buf; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate if (temp_size == 0) 2350Sstevel@tonic-gate return; 2360Sstevel@tonic-gate (void) fprintf(stdout, "%s:\n", cur_file); 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate while (temp_size--) { 2390Sstevel@tonic-gate char c = *temp_string++; 2400Sstevel@tonic-gate switch (c) { 2410Sstevel@tonic-gate case '\0': 2420Sstevel@tonic-gate (void) putchar('\n'); 2430Sstevel@tonic-gate break; 2440Sstevel@tonic-gate default: 2450Sstevel@tonic-gate (void) putchar(c); 2460Sstevel@tonic-gate break; 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate (void) putchar('\n'); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * ACT_APPEND 2540Sstevel@tonic-gate */ 2550Sstevel@tonic-gate static void 2560Sstevel@tonic-gate doappend(char *a_string, section_info_table *info) 2570Sstevel@tonic-gate { 2580Sstevel@tonic-gate Elf_Data *data; 2590Sstevel@tonic-gate char *p; 2600Sstevel@tonic-gate size_t len; 2610Sstevel@tonic-gate char *tp; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* 2641282Sab196087 * Get the length of the string to be added. We accept any 2651282Sab196087 * string (even null), as this is arbitrary user defined text. 2661282Sab196087 * 2671282Sab196087 * The caller expects this routine to replace a NULL info->mdata 2681282Sab196087 * field with a pointer to a freshly allocated copy. Any attempt 2691282Sab196087 * to optimize away a null string append would have to deal with 2701282Sab196087 * that, as failing to do so will cause a segfault when the NULL 2711282Sab196087 * mdata field is dereferenced. Accepting null strings in 2721282Sab196087 * this very unimportant case eliminates the need for that. 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate len = strlen(a_string); 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate /* 2770Sstevel@tonic-gate * Every modification operation will be done 2780Sstevel@tonic-gate * to a new Elf_Data descriptor. 2790Sstevel@tonic-gate */ 2800Sstevel@tonic-gate if (info->mdata == 0) { 2810Sstevel@tonic-gate /* 2820Sstevel@tonic-gate * mdata is not allocated yet. 2830Sstevel@tonic-gate * Allocate the data and set it. 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate info->mdata = data = calloc(1, sizeof (Elf_Data)); 2860Sstevel@tonic-gate if (data == NULL) { 2875154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 2885154Sab196087 (char *)0, prog); 289*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate *data = *info->data; 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * Check if the section is deleted or not. 2950Sstevel@tonic-gate * Or if the size is 0 or not. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate if ((GET_ACTION(info->flags) == ACT_DELETE) || 2980Sstevel@tonic-gate data->d_size == 0) { 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * The section was deleated. 3010Sstevel@tonic-gate * But now, the user wants to add data to this 3020Sstevel@tonic-gate * section. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate data->d_buf = calloc(1, len + 2); 3050Sstevel@tonic-gate if (data->d_buf == 0) { 3065154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 3075154Sab196087 (char *)0, prog); 308*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 3090Sstevel@tonic-gate } 3100Sstevel@tonic-gate tp = (char *)data->d_buf; 3110Sstevel@tonic-gate (void) memcpy(& tp[1], a_string, len + 1); 3120Sstevel@tonic-gate data->d_size = len + 2; 3130Sstevel@tonic-gate } else { 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * The user wants to add data to the section. 3160Sstevel@tonic-gate * I am not going to change the original data. 3170Sstevel@tonic-gate * Do the modification on the new one. 3180Sstevel@tonic-gate */ 3190Sstevel@tonic-gate p = malloc(len + 1 + data->d_size); 3200Sstevel@tonic-gate if (p == NULL) { 3215154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 3225154Sab196087 (char *)0, prog); 323*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate (void) memcpy(p, data->d_buf, data->d_size); 3260Sstevel@tonic-gate (void) memcpy(&p[data->d_size], a_string, len + 1); 3270Sstevel@tonic-gate data->d_buf = p; 3280Sstevel@tonic-gate data->d_size = data->d_size + len + 1; 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate } else { 3310Sstevel@tonic-gate /* 3320Sstevel@tonic-gate * mdata is already allocated. 3330Sstevel@tonic-gate * Modify it. 3340Sstevel@tonic-gate */ 3350Sstevel@tonic-gate data = info->mdata; 3360Sstevel@tonic-gate if ((GET_ACTION(info->flags) == ACT_DELETE) || 3370Sstevel@tonic-gate data->d_size == 0) { 3380Sstevel@tonic-gate /* 3390Sstevel@tonic-gate * The section was deleated. 3400Sstevel@tonic-gate * But now, the user wants to add data to this 3410Sstevel@tonic-gate * section. 3420Sstevel@tonic-gate */ 3430Sstevel@tonic-gate if (data->d_buf) 3440Sstevel@tonic-gate free(data->d_buf); 3450Sstevel@tonic-gate data->d_buf = calloc(1, len + 2); 3460Sstevel@tonic-gate if (data->d_buf == 0) { 3475154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 3485154Sab196087 (char *)0, prog); 349*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate tp = (char *)data->d_buf; 3520Sstevel@tonic-gate (void) memcpy(&tp[1], a_string, len + 1); 3530Sstevel@tonic-gate data->d_size = len + 2; 3540Sstevel@tonic-gate } else { 3550Sstevel@tonic-gate /* 3560Sstevel@tonic-gate * The user wants to add data to the section. 3570Sstevel@tonic-gate * I am not going to change the original data. 3580Sstevel@tonic-gate * Do the modification on the new one. 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate p = malloc(len + 1 + data->d_size); 3610Sstevel@tonic-gate if (p == NULL) { 3625154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 3635154Sab196087 (char *)0, prog); 364*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate (void) memcpy(p, data->d_buf, data->d_size); 3670Sstevel@tonic-gate (void) memcpy(&p[data->d_size], a_string, len + 1); 3680Sstevel@tonic-gate free(data->d_buf); 3690Sstevel@tonic-gate data->d_buf = p; 3700Sstevel@tonic-gate data->d_size = data->d_size + len + 1; 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* 3760Sstevel@tonic-gate * ACT_COMPRESS 3770Sstevel@tonic-gate */ 3780Sstevel@tonic-gate #define HALFLONG 16 3790Sstevel@tonic-gate #define low(x) (x&((1L<<HALFLONG)-1)) 3800Sstevel@tonic-gate #define high(x) (x>>HALFLONG) 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate static void 3830Sstevel@tonic-gate docompress(section_info_table *info) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate Elf_Data *data; 3860Sstevel@tonic-gate size_t size; 3870Sstevel@tonic-gate char *buf; 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate if (info->mdata == 0) { 3900Sstevel@tonic-gate /* 3910Sstevel@tonic-gate * mdata is not allocated yet. 3920Sstevel@tonic-gate * Allocate the data and set it. 3930Sstevel@tonic-gate */ 3940Sstevel@tonic-gate char *p; 3950Sstevel@tonic-gate info->mdata = data = calloc(1, sizeof (Elf_Data)); 3960Sstevel@tonic-gate if (data == NULL) { 3975154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 3985154Sab196087 (char *)0, prog); 399*8223SAli.Bahrami@Sun.COM mcs_exit(FAILURE); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate *data = *info->data; 4020Sstevel@tonic-gate p = malloc(data->d_size); 4030Sstevel@tonic-gate (void) memcpy(p, (char *)data->d_buf, data->d_size); 4040Sstevel@tonic-gate data->d_buf = p; 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate size = info->mdata->d_size; 4070Sstevel@tonic-gate buf = (char *)info->mdata->d_buf; 4080Sstevel@tonic-gate buf = compress(buf, &size); 4090Sstevel@tonic-gate info->mdata->d_buf = buf; 4100Sstevel@tonic-gate info->mdata->d_size = size; 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate static char * 4140Sstevel@tonic-gate compress(char *str, size_t *size) 4150Sstevel@tonic-gate { 4160Sstevel@tonic-gate int hash; 4170Sstevel@tonic-gate int i; 4180Sstevel@tonic-gate size_t temp_string_size = 0; 4190Sstevel@tonic-gate size_t o_size = *size; 4200Sstevel@tonic-gate char *temp_string = str; 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate int *hash_key; 4230Sstevel@tonic-gate size_t hash_num; 4240Sstevel@tonic-gate size_t hash_end; 4250Sstevel@tonic-gate size_t *hash_str; 4260Sstevel@tonic-gate char *strings; 4270Sstevel@tonic-gate size_t next_str; 4280Sstevel@tonic-gate size_t str_size; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate hash_key = malloc(sizeof (int) * 200); 4310Sstevel@tonic-gate hash_end = 200; 4320Sstevel@tonic-gate hash_str = malloc(sizeof (size_t) * 200); 4330Sstevel@tonic-gate str_size = o_size+1; 4340Sstevel@tonic-gate strings = malloc(str_size); 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate if (hash_key == NULL || hash_str == NULL || strings == NULL) { 4375154Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 4380Sstevel@tonic-gate mcs_exit(FAILURE); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate hash_num = 0; 4420Sstevel@tonic-gate next_str = 0; 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate while (temp_string_size < o_size) { 4450Sstevel@tonic-gate size_t pos; 4460Sstevel@tonic-gate char c; 4470Sstevel@tonic-gate /* 4480Sstevel@tonic-gate * Get a string 4490Sstevel@tonic-gate */ 4500Sstevel@tonic-gate pos = next_str; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate while ((c = *(temp_string++)) != '\0' && 4530Sstevel@tonic-gate (temp_string_size + (next_str - pos)) <= o_size) { 4540Sstevel@tonic-gate if (next_str >= str_size) { 4550Sstevel@tonic-gate str_size *= 2; 4560Sstevel@tonic-gate if ((strings = (char *) 4570Sstevel@tonic-gate realloc(strings, str_size)) == NULL) { 4580Sstevel@tonic-gate error_message(MALLOC_ERROR, 4595154Sab196087 PLAIN_ERROR, (char *)0, prog); 4600Sstevel@tonic-gate mcs_exit(FAILURE); 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate strings[next_str++] = c; 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate 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, 4715154Sab196087 PLAIN_ERROR, (char *)0, prog); 4720Sstevel@tonic-gate mcs_exit(FAILURE); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate strings[next_str++] = NULL; 4760Sstevel@tonic-gate /* 4770Sstevel@tonic-gate * End get string 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate temp_string_size += (next_str - pos); 4810Sstevel@tonic-gate hash = dohash(pos + strings); 4820Sstevel@tonic-gate for (i = 0; i < hash_num; i++) { 4830Sstevel@tonic-gate if (hash != hash_key[i]) 4840Sstevel@tonic-gate continue; 4850Sstevel@tonic-gate if (strcmp(pos + strings, hash_str[i] + strings) == 0) 4860Sstevel@tonic-gate break; 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate if (i != hash_num) { 4890Sstevel@tonic-gate next_str = pos; 4900Sstevel@tonic-gate continue; 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate if (hash_num == hash_end) { 4930Sstevel@tonic-gate hash_end *= 2; 4940Sstevel@tonic-gate hash_key = realloc((char *)hash_key, 4955154Sab196087 hash_end * sizeof (int)); 4960Sstevel@tonic-gate hash_str = realloc((char *)hash_str, 4975154Sab196087 hash_end * sizeof (size_t)); 4980Sstevel@tonic-gate if (hash_key == NULL || hash_str == NULL) { 4990Sstevel@tonic-gate error_message(MALLOC_ERROR, 5005154Sab196087 PLAIN_ERROR, (char *)0, prog); 5010Sstevel@tonic-gate mcs_exit(FAILURE); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate hash_key[hash_num] = hash; 5050Sstevel@tonic-gate hash_str[hash_num++] = pos; 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* 5090Sstevel@tonic-gate * Clean up 5100Sstevel@tonic-gate */ 5110Sstevel@tonic-gate free(hash_key); 5120Sstevel@tonic-gate free(hash_str); 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate /* 5150Sstevel@tonic-gate * Return 5160Sstevel@tonic-gate */ 5170Sstevel@tonic-gate if (next_str != o_size) { 5180Sstevel@tonic-gate /* 5190Sstevel@tonic-gate * string compressed. 5200Sstevel@tonic-gate */ 5210Sstevel@tonic-gate *size = next_str; 5220Sstevel@tonic-gate free(str); 5230Sstevel@tonic-gate str = malloc(next_str); 5240Sstevel@tonic-gate (void) memcpy(str, strings, next_str); 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate free(strings); 5270Sstevel@tonic-gate return (str); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate static int 5310Sstevel@tonic-gate dohash(char *str) 5320Sstevel@tonic-gate { 5330Sstevel@tonic-gate long sum; 5340Sstevel@tonic-gate unsigned shift; 5350Sstevel@tonic-gate int t; 5360Sstevel@tonic-gate sum = 1; 5370Sstevel@tonic-gate for (shift = 0; (t = *str++) != NULL; shift += 7) { 5380Sstevel@tonic-gate sum += (long)t << (shift %= HALFLONG); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate sum = low(sum) + high(sum); 5410Sstevel@tonic-gate /* LINTED */ 5420Sstevel@tonic-gate return ((short)low(sum) + (short)high(sum)); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate /* 5460Sstevel@tonic-gate * Append an item to the specified list, and return a pointer to the list 5470Sstevel@tonic-gate * node created. 5480Sstevel@tonic-gate */ 5490Sstevel@tonic-gate Listnode * 5500Sstevel@tonic-gate list_appendc(List *lst, const void *item) 5510Sstevel@tonic-gate { 5520Sstevel@tonic-gate Listnode *_lnp; 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate if ((_lnp = malloc(sizeof (Listnode))) == (Listnode *)0) 5550Sstevel@tonic-gate return (0); 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate _lnp->data = (void *)item; 5580Sstevel@tonic-gate _lnp->next = NULL; 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate if (lst->head == NULL) 5610Sstevel@tonic-gate lst->tail = lst->head = _lnp; 5620Sstevel@tonic-gate else { 5630Sstevel@tonic-gate lst->tail->next = _lnp; 5640Sstevel@tonic-gate lst->tail = lst->tail->next; 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate return (_lnp); 5670Sstevel@tonic-gate } 568