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*9131SRod.Evans@Sun.COM * Copyright 2009 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
apply_action(section_info_table * info,char * cur_file,Cmd_Info * cmd_info)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,
74*9131SRod.Evans@Sun.COM NULL, 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,
102*9131SRod.Evans@Sun.COM PLAIN_ERROR, NULL,
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,
118*9131SRod.Evans@Sun.COM PLAIN_ERROR, NULL,
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++;
141*9131SRod.Evans@Sun.COM error_message(ACT_APPEND1_ERROR, PLAIN_ERROR,
142*9131SRod.Evans@Sun.COM NULL, prog, cur_file, SECT_NAME);
1430Sstevel@tonic-gate break;
1440Sstevel@tonic-gate } else if (GET_LOC(info->flags) == IN) {
1450Sstevel@tonic-gate ret++;
146*9131SRod.Evans@Sun.COM error_message(ACT_APPEND2_ERROR, PLAIN_ERROR,
147*9131SRod.Evans@Sun.COM NULL, prog, cur_file, SECT_NAME);
1480Sstevel@tonic-gate break;
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate doappend(Action[act_index].a_string, info);
1510Sstevel@tonic-gate (cmd_info->no_of_append)++;
1520Sstevel@tonic-gate info->secno = info->osecno;
1530Sstevel@tonic-gate SET_ACTION(info->flags, ACT_APPEND);
1540Sstevel@tonic-gate SET_MODIFIED(info->flags);
1550Sstevel@tonic-gate if (GET_LOC(info->flags) == PRIOR)
1560Sstevel@tonic-gate info->secno = (GElf_Word)EXPANDED;
1570Sstevel@tonic-gate break;
1580Sstevel@tonic-gate case ACT_COMPRESS:
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * If this section is already deleted,
1610Sstevel@tonic-gate * don't do anything.
1620Sstevel@tonic-gate */
1630Sstevel@tonic-gate if (GET_ACTION(info->flags) == ACT_DELETE)
1640Sstevel@tonic-gate break;
1650Sstevel@tonic-gate if (shdr.sh_type == SHT_NOBITS) {
1660Sstevel@tonic-gate ret++;
167*9131SRod.Evans@Sun.COM error_message(ACT_COMPRESS1_ERROR, PLAIN_ERROR,
168*9131SRod.Evans@Sun.COM NULL, prog, cur_file, SECT_NAME);
1690Sstevel@tonic-gate break;
1700Sstevel@tonic-gate } else if (GET_LOC(info->flags) == IN) {
1710Sstevel@tonic-gate ret++;
172*9131SRod.Evans@Sun.COM error_message(ACT_COMPRESS2_ERROR, PLAIN_ERROR,
173*9131SRod.Evans@Sun.COM NULL, prog, cur_file, SECT_NAME);
1740Sstevel@tonic-gate break;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate docompress(info);
1780Sstevel@tonic-gate (cmd_info->no_of_compressed)++;
1790Sstevel@tonic-gate SET_ACTION(info->flags, ACT_COMPRESS);
1800Sstevel@tonic-gate SET_MODIFIED(info->flags);
1810Sstevel@tonic-gate if (GET_LOC(info->flags) == PRIOR)
1820Sstevel@tonic-gate info->secno = (GElf_Word)SHRUNK;
1830Sstevel@tonic-gate break;
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate return (ret);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate /*
1900Sstevel@tonic-gate * ACT_ZAP
1910Sstevel@tonic-gate */
1920Sstevel@tonic-gate static void
dozap(section_info_table * info)1930Sstevel@tonic-gate dozap(section_info_table *info)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate Elf_Data *data;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate info->mdata = data = malloc(sizeof (Elf_Data));
1980Sstevel@tonic-gate if (data == NULL) {
199*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
2008223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate *data = *info->data;
2030Sstevel@tonic-gate data->d_buf = calloc(1, data->d_size);
2040Sstevel@tonic-gate if (data->d_buf == NULL) {
205*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
2068223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate * ACT_PRINT
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate static void
doprint(char * cur_file,section_info_table * info)2140Sstevel@tonic-gate doprint(char *cur_file, section_info_table *info)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate Elf_Data *data;
2170Sstevel@tonic-gate size_t temp_size;
2180Sstevel@tonic-gate char *temp_string;
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate if (GET_MODIFIED(info->flags) == 0)
2210Sstevel@tonic-gate data = info->data;
2220Sstevel@tonic-gate else
2230Sstevel@tonic-gate data = info->mdata;
2240Sstevel@tonic-gate if (data == 0)
2250Sstevel@tonic-gate return;
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate temp_size = data->d_size;
2280Sstevel@tonic-gate temp_string = data->d_buf;
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate if (temp_size == 0)
2310Sstevel@tonic-gate return;
2320Sstevel@tonic-gate (void) fprintf(stdout, "%s:\n", cur_file);
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate while (temp_size--) {
2350Sstevel@tonic-gate char c = *temp_string++;
2360Sstevel@tonic-gate switch (c) {
2370Sstevel@tonic-gate case '\0':
2380Sstevel@tonic-gate (void) putchar('\n');
2390Sstevel@tonic-gate break;
2400Sstevel@tonic-gate default:
2410Sstevel@tonic-gate (void) putchar(c);
2420Sstevel@tonic-gate break;
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate (void) putchar('\n');
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate * ACT_APPEND
2500Sstevel@tonic-gate */
2510Sstevel@tonic-gate static void
doappend(char * a_string,section_info_table * info)2520Sstevel@tonic-gate doappend(char *a_string, section_info_table *info)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate Elf_Data *data;
2550Sstevel@tonic-gate char *p;
2560Sstevel@tonic-gate size_t len;
2570Sstevel@tonic-gate char *tp;
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate /*
2601282Sab196087 * Get the length of the string to be added. We accept any
2611282Sab196087 * string (even null), as this is arbitrary user defined text.
2621282Sab196087 *
2631282Sab196087 * The caller expects this routine to replace a NULL info->mdata
2641282Sab196087 * field with a pointer to a freshly allocated copy. Any attempt
2651282Sab196087 * to optimize away a null string append would have to deal with
2661282Sab196087 * that, as failing to do so will cause a segfault when the NULL
2671282Sab196087 * mdata field is dereferenced. Accepting null strings in
2681282Sab196087 * this very unimportant case eliminates the need for that.
2690Sstevel@tonic-gate */
2700Sstevel@tonic-gate len = strlen(a_string);
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate * Every modification operation will be done
2740Sstevel@tonic-gate * to a new Elf_Data descriptor.
2750Sstevel@tonic-gate */
2760Sstevel@tonic-gate if (info->mdata == 0) {
2770Sstevel@tonic-gate /*
2780Sstevel@tonic-gate * mdata is not allocated yet.
2790Sstevel@tonic-gate * Allocate the data and set it.
2800Sstevel@tonic-gate */
2810Sstevel@tonic-gate info->mdata = data = calloc(1, sizeof (Elf_Data));
2820Sstevel@tonic-gate if (data == NULL) {
283*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
2848223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate *data = *info->data;
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate /*
2890Sstevel@tonic-gate * Check if the section is deleted or not.
2900Sstevel@tonic-gate * Or if the size is 0 or not.
2910Sstevel@tonic-gate */
2920Sstevel@tonic-gate if ((GET_ACTION(info->flags) == ACT_DELETE) ||
2930Sstevel@tonic-gate data->d_size == 0) {
2940Sstevel@tonic-gate /*
2950Sstevel@tonic-gate * The section was deleated.
2960Sstevel@tonic-gate * But now, the user wants to add data to this
2970Sstevel@tonic-gate * section.
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate data->d_buf = calloc(1, len + 2);
300*9131SRod.Evans@Sun.COM if (data->d_buf == NULL) {
301*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
302*9131SRod.Evans@Sun.COM prog);
3038223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate tp = (char *)data->d_buf;
3060Sstevel@tonic-gate (void) memcpy(& tp[1], a_string, len + 1);
3070Sstevel@tonic-gate data->d_size = len + 2;
3080Sstevel@tonic-gate } else {
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate * The user wants to add data to the section.
3110Sstevel@tonic-gate * I am not going to change the original data.
3120Sstevel@tonic-gate * Do the modification on the new one.
3130Sstevel@tonic-gate */
3140Sstevel@tonic-gate p = malloc(len + 1 + data->d_size);
3150Sstevel@tonic-gate if (p == NULL) {
316*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
317*9131SRod.Evans@Sun.COM prog);
3188223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate (void) memcpy(p, data->d_buf, data->d_size);
3210Sstevel@tonic-gate (void) memcpy(&p[data->d_size], a_string, len + 1);
3220Sstevel@tonic-gate data->d_buf = p;
3230Sstevel@tonic-gate data->d_size = data->d_size + len + 1;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate } else {
3260Sstevel@tonic-gate /*
3270Sstevel@tonic-gate * mdata is already allocated.
3280Sstevel@tonic-gate * Modify it.
3290Sstevel@tonic-gate */
3300Sstevel@tonic-gate data = info->mdata;
3310Sstevel@tonic-gate if ((GET_ACTION(info->flags) == ACT_DELETE) ||
3320Sstevel@tonic-gate data->d_size == 0) {
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate * The section was deleated.
3350Sstevel@tonic-gate * But now, the user wants to add data to this
3360Sstevel@tonic-gate * section.
3370Sstevel@tonic-gate */
3380Sstevel@tonic-gate if (data->d_buf)
3390Sstevel@tonic-gate free(data->d_buf);
3400Sstevel@tonic-gate data->d_buf = calloc(1, len + 2);
341*9131SRod.Evans@Sun.COM if (data->d_buf == NULL) {
342*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
343*9131SRod.Evans@Sun.COM prog);
3448223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate tp = (char *)data->d_buf;
3470Sstevel@tonic-gate (void) memcpy(&tp[1], a_string, len + 1);
3480Sstevel@tonic-gate data->d_size = len + 2;
3490Sstevel@tonic-gate } else {
3500Sstevel@tonic-gate /*
3510Sstevel@tonic-gate * The user wants to add data to the section.
3520Sstevel@tonic-gate * I am not going to change the original data.
3530Sstevel@tonic-gate * Do the modification on the new one.
3540Sstevel@tonic-gate */
3550Sstevel@tonic-gate p = malloc(len + 1 + data->d_size);
3560Sstevel@tonic-gate if (p == NULL) {
357*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
358*9131SRod.Evans@Sun.COM prog);
3598223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate (void) memcpy(p, data->d_buf, data->d_size);
3620Sstevel@tonic-gate (void) memcpy(&p[data->d_size], a_string, len + 1);
3630Sstevel@tonic-gate free(data->d_buf);
3640Sstevel@tonic-gate data->d_buf = p;
3650Sstevel@tonic-gate data->d_size = data->d_size + len + 1;
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate * ACT_COMPRESS
3720Sstevel@tonic-gate */
3730Sstevel@tonic-gate #define HALFLONG 16
3740Sstevel@tonic-gate #define low(x) (x&((1L<<HALFLONG)-1))
3750Sstevel@tonic-gate #define high(x) (x>>HALFLONG)
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate static void
docompress(section_info_table * info)3780Sstevel@tonic-gate docompress(section_info_table *info)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate Elf_Data *data;
3810Sstevel@tonic-gate size_t size;
3820Sstevel@tonic-gate char *buf;
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate if (info->mdata == 0) {
3850Sstevel@tonic-gate /*
3860Sstevel@tonic-gate * mdata is not allocated yet.
3870Sstevel@tonic-gate * Allocate the data and set it.
3880Sstevel@tonic-gate */
3890Sstevel@tonic-gate char *p;
3900Sstevel@tonic-gate info->mdata = data = calloc(1, sizeof (Elf_Data));
3910Sstevel@tonic-gate if (data == NULL) {
392*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
3938223SAli.Bahrami@Sun.COM mcs_exit(FAILURE);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate *data = *info->data;
3960Sstevel@tonic-gate p = malloc(data->d_size);
3970Sstevel@tonic-gate (void) memcpy(p, (char *)data->d_buf, data->d_size);
3980Sstevel@tonic-gate data->d_buf = p;
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate size = info->mdata->d_size;
4010Sstevel@tonic-gate buf = (char *)info->mdata->d_buf;
4020Sstevel@tonic-gate buf = compress(buf, &size);
4030Sstevel@tonic-gate info->mdata->d_buf = buf;
4040Sstevel@tonic-gate info->mdata->d_size = size;
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate static char *
compress(char * str,size_t * size)4080Sstevel@tonic-gate compress(char *str, size_t *size)
4090Sstevel@tonic-gate {
4100Sstevel@tonic-gate int hash;
4110Sstevel@tonic-gate int i;
4120Sstevel@tonic-gate size_t temp_string_size = 0;
4130Sstevel@tonic-gate size_t o_size = *size;
4140Sstevel@tonic-gate char *temp_string = str;
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate int *hash_key;
4170Sstevel@tonic-gate size_t hash_num;
4180Sstevel@tonic-gate size_t hash_end;
4190Sstevel@tonic-gate size_t *hash_str;
4200Sstevel@tonic-gate char *strings;
4210Sstevel@tonic-gate size_t next_str;
4220Sstevel@tonic-gate size_t str_size;
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate hash_key = malloc(sizeof (int) * 200);
4250Sstevel@tonic-gate hash_end = 200;
4260Sstevel@tonic-gate hash_str = malloc(sizeof (size_t) * 200);
4270Sstevel@tonic-gate str_size = o_size+1;
4280Sstevel@tonic-gate strings = malloc(str_size);
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate if (hash_key == NULL || hash_str == NULL || strings == NULL) {
431*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
4320Sstevel@tonic-gate mcs_exit(FAILURE);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate hash_num = 0;
4360Sstevel@tonic-gate next_str = 0;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate while (temp_string_size < o_size) {
4390Sstevel@tonic-gate size_t pos;
4400Sstevel@tonic-gate char c;
4410Sstevel@tonic-gate /*
4420Sstevel@tonic-gate * Get a string
4430Sstevel@tonic-gate */
4440Sstevel@tonic-gate pos = next_str;
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate while ((c = *(temp_string++)) != '\0' &&
4470Sstevel@tonic-gate (temp_string_size + (next_str - pos)) <= o_size) {
4480Sstevel@tonic-gate if (next_str >= str_size) {
4490Sstevel@tonic-gate str_size *= 2;
4500Sstevel@tonic-gate if ((strings = (char *)
4510Sstevel@tonic-gate realloc(strings, str_size)) == NULL) {
452*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR,
453*9131SRod.Evans@Sun.COM NULL, prog);
4540Sstevel@tonic-gate mcs_exit(FAILURE);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate strings[next_str++] = c;
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate if (next_str >= str_size) {
4610Sstevel@tonic-gate str_size *= 2;
4620Sstevel@tonic-gate if ((strings = (char *)
4630Sstevel@tonic-gate realloc(strings, str_size)) == NULL) {
464*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
465*9131SRod.Evans@Sun.COM prog);
4660Sstevel@tonic-gate mcs_exit(FAILURE);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate strings[next_str++] = NULL;
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * End get string
4720Sstevel@tonic-gate */
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate temp_string_size += (next_str - pos);
4750Sstevel@tonic-gate hash = dohash(pos + strings);
4760Sstevel@tonic-gate for (i = 0; i < hash_num; i++) {
4770Sstevel@tonic-gate if (hash != hash_key[i])
4780Sstevel@tonic-gate continue;
4790Sstevel@tonic-gate if (strcmp(pos + strings, hash_str[i] + strings) == 0)
4800Sstevel@tonic-gate break;
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate if (i != hash_num) {
4830Sstevel@tonic-gate next_str = pos;
4840Sstevel@tonic-gate continue;
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate if (hash_num == hash_end) {
4870Sstevel@tonic-gate hash_end *= 2;
4880Sstevel@tonic-gate hash_key = realloc((char *)hash_key,
4895154Sab196087 hash_end * sizeof (int));
4900Sstevel@tonic-gate hash_str = realloc((char *)hash_str,
4915154Sab196087 hash_end * sizeof (size_t));
4920Sstevel@tonic-gate if (hash_key == NULL || hash_str == NULL) {
493*9131SRod.Evans@Sun.COM error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
494*9131SRod.Evans@Sun.COM prog);
4950Sstevel@tonic-gate mcs_exit(FAILURE);
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate hash_key[hash_num] = hash;
4990Sstevel@tonic-gate hash_str[hash_num++] = pos;
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate /*
5030Sstevel@tonic-gate * Clean up
5040Sstevel@tonic-gate */
5050Sstevel@tonic-gate free(hash_key);
5060Sstevel@tonic-gate free(hash_str);
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate /*
5090Sstevel@tonic-gate * Return
5100Sstevel@tonic-gate */
5110Sstevel@tonic-gate if (next_str != o_size) {
5120Sstevel@tonic-gate /*
5130Sstevel@tonic-gate * string compressed.
5140Sstevel@tonic-gate */
5150Sstevel@tonic-gate *size = next_str;
5160Sstevel@tonic-gate free(str);
5170Sstevel@tonic-gate str = malloc(next_str);
5180Sstevel@tonic-gate (void) memcpy(str, strings, next_str);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate free(strings);
5210Sstevel@tonic-gate return (str);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate static int
dohash(char * str)5250Sstevel@tonic-gate dohash(char *str)
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate long sum;
5280Sstevel@tonic-gate unsigned shift;
5290Sstevel@tonic-gate int t;
5300Sstevel@tonic-gate sum = 1;
5310Sstevel@tonic-gate for (shift = 0; (t = *str++) != NULL; shift += 7) {
5320Sstevel@tonic-gate sum += (long)t << (shift %= HALFLONG);
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate sum = low(sum) + high(sum);
5350Sstevel@tonic-gate /* LINTED */
5360Sstevel@tonic-gate return ((short)low(sum) + (short)high(sum));
5370Sstevel@tonic-gate }
538