1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1998-2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include "initialize.h"
28 
29 #ifndef TEXT_DOMAIN
30 /*
31  * TEXT_DOMAIN should have been set by build environment.
32  */
33 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
34 #endif /* TEXT_DOMAIN */
35 
36 /*
37  * /dev/zero, output file, stdin, stdout, and stderr
38  */
39 #define	N_FILES_ALREADY_OPEN	5
40 
41 static const char *filename_stdin = "STDIN";
42 const char *filename_stdout = "STDOUT";
43 
44 static sigjmp_buf signal_jmp_buf;
45 static volatile sig_atomic_t signal_delivered;
46 
47 static void
set_signal_jmp(void)48 set_signal_jmp(void)
49 {
50 	if (sigsetjmp(signal_jmp_buf, 1))
51 		exit(127 + signal_delivered);
52 }
53 
54 static void
sig_handler(int signo)55 sig_handler(int signo)
56 {
57 	signal_delivered = signo;
58 	siglongjmp(signal_jmp_buf, 1);
59 }
60 
61 void
initialize_pre(sort_t * S)62 initialize_pre(sort_t *S)
63 {
64 	/*
65 	 * Initialize sort structure.
66 	 */
67 	(void) memset(S, 0, sizeof (sort_t));
68 
69 	S->m_stats = safe_realloc(NULL, sizeof (sort_statistics_t));
70 	__S(stats_init(S->m_stats));
71 
72 	S->m_default_species = ALPHA;
73 
74 	/*
75 	 * Simple localization issues.
76 	 */
77 	(void) setlocale(LC_ALL, "");
78 	(void) textdomain(TEXT_DOMAIN);
79 
80 #ifndef DEBUG_FORCE_WIDE
81 	S->m_c_locale = xstreql("C", setlocale(LC_COLLATE, NULL));
82 	S->m_single_byte_locale = SGN(MB_CUR_MAX == 1);
83 #else /* DEBUG_FORCE_WIDE */
84 	S->m_c_locale = 0;
85 	S->m_single_byte_locale = 0;
86 #endif /* DEBUG_FORCE_WIDE */
87 
88 	/*
89 	 * We use a constant seed so that our sorts on a given file are
90 	 * reproducible.
91 	 */
92 	srand(3459871433U);
93 
94 	if (atexit(atexit_handler) < 0)
95 		warn(gettext("atexit() handler installation failed"));
96 
97 	/*
98 	 * Establish signal handlers and sufficient state for clean up.
99 	 */
100 	if (signal(SIGTERM, sig_handler) == SIG_ERR)
101 		die(EMSG_SIGNAL, "SIGTERM");
102 	if (signal(SIGHUP, sig_handler) == SIG_ERR)
103 		die(EMSG_SIGNAL, "SIGHUP");
104 	if (signal(SIGPIPE, sig_handler) == SIG_ERR)
105 		die(EMSG_SIGNAL, "SIGPIPE");
106 
107 	set_signal_jmp();
108 }
109 
110 static int
strcoll_cmp(void * s1,void * s2,flag_t f __unused)111 strcoll_cmp(void *s1, void *s2, flag_t f __unused)
112 {
113 	return (strcoll(s1, s2));
114 }
115 
116 static int
wcscoll_cmp(void * s1,void * s2,flag_t f __unused)117 wcscoll_cmp(void *s1, void *s2, flag_t f __unused)
118 {
119 	return (wcscoll(s1, s2));
120 }
121 
122 void
initialize_post(sort_t * S)123 initialize_post(sort_t *S)
124 {
125 	field_t	*F;
126 
127 	S->m_memory_available = available_memory(S->m_memory_limit);
128 
129 	set_file_template(&S->m_tmpdir_template);
130 
131 	/*
132 	 * Initialize locale-specific ops vectors.
133 	 */
134 	field_initialize(S);
135 
136 	if (S->m_single_byte_locale) {
137 		S->m_compare_fn = strcoll_cmp;
138 		S->m_coll_convert = field_convert;
139 		F = S->m_fields_head;
140 
141 		while (F != NULL) {
142 			switch (F->f_species) {
143 			case ALPHA:
144 				if (F->f_options &
145 				    (FIELD_IGNORE_NONPRINTABLES |
146 				    FIELD_DICTIONARY_ORDER |
147 				    FIELD_FOLD_UPPERCASE))
148 					F->f_convert = field_convert_alpha;
149 				else
150 					F->f_convert =
151 					    field_convert_alpha_simple;
152 				break;
153 			case NUMERIC:
154 				F->f_convert = field_convert_numeric;
155 				break;
156 			case MONTH:
157 				F->f_convert = field_convert_month;
158 				break;
159 			default:
160 				die(EMSG_UNKN_FIELD, F->f_species);
161 				break;
162 			}
163 			F = F->f_next;
164 		}
165 	} else {
166 		S->m_compare_fn = wcscoll_cmp;
167 		S->m_coll_convert = field_convert_wide;
168 
169 		F = S->m_fields_head;
170 		while (F != NULL) {
171 			switch (F->f_species) {
172 			case ALPHA:
173 				F->f_convert = field_convert_alpha_wide;
174 				break;
175 			case NUMERIC:
176 				F->f_convert =
177 				    field_convert_numeric_wide;
178 				break;
179 			case MONTH:
180 				F->f_convert = field_convert_month_wide;
181 				break;
182 			default:
183 				die(EMSG_UNKN_FIELD, F->f_species);
184 				break;
185 			}
186 			F = F->f_next;
187 		}
188 	}
189 
190 	/*
191 	 * Validate and obtain sizes, inodes for input streams.
192 	 */
193 	stream_stat_chain(S->m_input_streams);
194 	__S(stats_set_input_files(stream_count_chain(S->m_input_streams)));
195 
196 	/*
197 	 * Output guard.
198 	 */
199 	establish_output_guard(S);
200 
201 	/*
202 	 * Ready stdin for usage as stream.
203 	 */
204 	if (S->m_input_from_stdin) {
205 		stream_t *str;
206 
207 		if (S->m_single_byte_locale) {
208 			str = stream_new(STREAM_SINGLE | STREAM_NOTFILE);
209 			str->s_element_size = sizeof (char);
210 		} else {
211 			str = stream_new(STREAM_WIDE | STREAM_NOTFILE);
212 			str->s_element_size = sizeof (wchar_t);
213 		}
214 		str->s_filename = (char *)filename_stdin;
215 		stream_push_to_chain(&S->m_input_streams, str);
216 		__S(stats_incr_input_files());
217 	}
218 }
219