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