4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 #include <arpa/inet.h>
32 #include <mksh/misc.h>
34 #include <netinet/in.h>
35 #include <sys/socket.h>
37 #include <sys/types.h>
38 #include <sys/utsname.h>
39 #include <rpc/rpc.h> /* host2netname(), netname2host() */
55 * File table of contents
57 static int get_max(wchar_t **ms_address
, wchar_t *hostname
);
58 static Boolean
pskip_comment(wchar_t **cp_address
);
59 static void pskip_till_next_word(wchar_t **cp
);
60 static Boolean
pskip_white_space(wchar_t **cp_address
);
64 * read_make_machines(Name make_machines_name)
66 * For backwards compatibility w/ PMake 1.x, when DMake 2.x is
67 * being run in parallel mode, DMake should parse the PMake startup
68 * file $(HOME)/.make.machines to get the PMake max jobs.
71 * int of PMake max jobs
74 * make_machines_name Name of .make.machines file
78 read_make_machines(Name make_machines_name
)
81 Boolean default_make_machines
;
83 wchar_t local_host
[MAX_HOSTNAMELEN
+ 1];
84 char local_host_mb
[MAX_HOSTNAMELEN
+ 1] = "";
86 wchar_t full_host
[MAXNETNAMELEN
+ 1];
87 int full_host_wslen
= 0;
90 struct stat make_machines_buf
;
91 FILE *make_machines_file
;
92 wchar_t *make_machines_list
= NULL
;
93 char *make_machines_list_mb
= NULL
;
94 wchar_t make_machines_path
[MAXPATHLEN
];
95 char mb_make_machines_path
[MAXPATHLEN
];
98 int pmake_max_jobs
= 0;
99 struct utsname uts_info
;
102 MBSTOWCS(wcs_buffer
, "MAKE_MACHINES");
103 MAKE_MACHINES
= GETNAME(wcs_buffer
, FIND_LENGTH
);
104 /* Did the user specify a .make.machines file on the command line? */
105 default_make_machines
= false;
106 if (make_machines_name
== NULL
) {
107 /* Try reading the default .make.machines file, in $(HOME). */
108 homedir
= getenv("HOME");
109 if ((homedir
!= NULL
) && (strlen(homedir
) < (sizeof(mb_make_machines_path
) - 16))) {
110 sprintf(mb_make_machines_path
,
111 "%s/.make.machines", homedir
);
112 MBSTOWCS(make_machines_path
, mb_make_machines_path
);
113 make_machines_name
= GETNAME(make_machines_path
, FIND_LENGTH
);
114 default_make_machines
= true;
116 if (make_machines_name
== NULL
) {
118 * No $(HOME)/.make.machines file.
119 * Return 0 for PMake max jobs.
125 make_machines_list_mb = getenv(MAKE_MACHINES->string_mb);
127 /* Open the .make.machines file. */
128 if ((make_machines_file
= fopen(make_machines_name
->string_mb
, "r")) == NULL
) {
129 if (!default_make_machines
) {
130 /* Error opening .make.machines file. */
131 fatal(gettext("Open of %s failed: %s"),
132 make_machines_name
->string_mb
,
136 * No $(HOME)/.make.machines file.
137 * Return 0 for PMake max jobs.
141 /* Stat the .make.machines file to get the size of the file. */
142 } else if (fstat(fileno(make_machines_file
), &make_machines_buf
) < 0) {
143 /* Error stat'ing .make.machines file. */
144 fatal(gettext("Stat of %s failed: %s"),
145 make_machines_name
->string_mb
,
148 /* Allocate memory for "MAKE_MACHINES=<contents of .m.m>" */
149 make_machines_list_mb
=
150 (char *) getmem((int) (strlen(MAKE_MACHINES
->string_mb
) +
152 make_machines_buf
.st_size
));
153 sprintf(make_machines_list_mb
,
155 MAKE_MACHINES
->string_mb
);
156 /* Read in the .make.machines file. */
157 if (fread(make_machines_list_mb
+ strlen(MAKE_MACHINES
->string_mb
) + 1,
159 (int) make_machines_buf
.st_size
,
160 make_machines_file
) != make_machines_buf
.st_size
) {
162 * Error reading .make.machines file.
163 * Return 0 for PMake max jobs.
165 warning(gettext("Unable to read %s"),
166 make_machines_name
->string_mb
);
167 (void) fclose(make_machines_file
);
168 retmem_mb((caddr_t
) make_machines_list_mb
);
171 (void) fclose(make_machines_file
);
172 /* putenv "MAKE_MACHINES=<contents of .m.m>" */
173 *(make_machines_list_mb
+
174 strlen(MAKE_MACHINES
->string_mb
) +
176 make_machines_buf
.st_size
) = (int) nul_char
;
177 if (putenv(make_machines_list_mb
) != 0) {
178 warning(gettext("Couldn't put contents of %s in environment"),
179 make_machines_name
->string_mb
);
181 make_machines_list_mb
+= strlen(MAKE_MACHINES
->string_mb
) + 1;
182 make_machines_list
= ALLOC_WC(strlen(make_machines_list_mb
) + 1);
183 (void) mbstowcs(make_machines_list
,
184 make_machines_list_mb
,
185 (strlen(make_machines_list_mb
) + 1));
191 strcpy(local_host_mb
, &uts_info
.nodename
[0]);
192 MBSTOWCS(local_host
, local_host_mb
);
193 local_host_wslen
= wcslen(local_host
);
195 // There is no getdomainname() function on Solaris.
196 // And netname2host() function does not work on Linux.
197 // So we have to use different APIs.
198 if (host2netname(mbs_buffer
, NULL
, NULL
) &&
199 netname2host(mbs_buffer
, mbs_buffer2
, MAXNETNAMELEN
+1)) {
200 MBSTOWCS(full_host
, mbs_buffer2
);
201 full_host_wslen
= wcslen(full_host
);
204 for (ms
= make_machines_list
;
208 * Skip white space and comments till you reach
211 pskip_till_next_word(&ms
);
214 * If we haven't reached the end of file, process the
219 * If invalid machine name decrement counter
225 *ms
++ = '\0'; /* Append null to machine name. */
227 * If this was the beginning of a comment
228 * (we overwrote a # sign) and it's not
229 * end of line yet, shift the # sign.
231 if ((c
== '#') && (*ms
!= '\n') && (*ms
)) {
234 WCSTOMBS(mbs_buffer
, mp
);
236 * Print "Ignoring unknown host" if:
237 * 1) hostname is longer than MAX_HOSTNAMELEN, or
238 * 2) hostname is unknown
240 if ((wcslen(mp
) > MAX_HOSTNAMELEN
) ||
241 ((hp
= gethostbyname(mbs_buffer
)) == NULL
)) {
242 warning(gettext("Ignoring unknown host %s"),
245 /* Increment ptr if not end of file. */
250 /* Compare current hostname with local_host. */
251 if (wcslen(mp
) == local_host_wslen
&&
252 IS_WEQUALN(mp
, local_host
, local_host_wslen
)) {
254 * Bingo, local_host is in .make.machines.
257 pmake_max_jobs
= PMAKE_DEF_MAX_JOBS
;
258 /* Compare current hostname with full_host. */
259 } else if (wcslen(mp
) == full_host_wslen
&&
260 IS_WEQUALN(mp
, full_host
, full_host_wslen
)) {
262 * Bingo, full_host is in .make.machines.
265 pmake_max_jobs
= PMAKE_DEF_MAX_JOBS
;
275 /* If we get here, local_host is in .make.machines. */
277 /* Now look for keyword 'max'. */
278 MBSTOWCS(wcs_buffer
, "max");
280 while ((*ms
!= '\n') && (*ms
)) {
283 } else if (IS_WEQUALN(ms
, wcs_buffer
, 3)) {
286 pmake_max_jobs
= get_max(&ms
, mp
);
289 warning(gettext("unknown option for host %s"), mbs_buffer
);
295 break; /* out of outermost for() loop. */
299 retmem(make_machines_list
);
300 return(pmake_max_jobs
);
304 * pskip_till_next_word(cp)
307 * cp the address of the string pointer.
310 * cp points to beginning of machine name.
314 pskip_till_next_word(wchar_t **cp
)
317 * Keep recursing until all combinations of white spaces
318 * and comments have been skipped.
320 if (pskip_white_space(cp
) || pskip_comment(cp
)) {
321 pskip_till_next_word(cp
);
326 * pskip_white_space(cp_address)
328 * Advances the string pointer so that it points to the first
329 * non white character (space/tab/linefeed).
332 * cp_address the address of the string pointer.
335 * True if the pointer was changed.
339 pskip_white_space(wchar_t **cp_address
)
341 wchar_t *cp
= *cp_address
;
343 while (*cp
&& iswspace(*cp
)) {
346 /* Have we skipped any characters? */
347 if (cp
!= *cp_address
) {
356 * pskip_comment(cp_address)
358 * If cp_address is pointing to '#' (the beginning of a comment),
359 * increment the pointer till you reach end of line.
362 * cp_address the address of the string pointer.
365 * True if the pointer was changed.
369 pskip_comment(wchar_t **cp_address
)
371 wchar_t *cp
= *cp_address
;
373 /* Is this the beginning of a comment? Skip till end of line. */
377 /* Have we skipped a comment line? */
378 if (cp
!= *cp_address
) {
387 get_max(wchar_t **ms_address
, wchar_t *hostname
)
389 wchar_t *ms
= *ms_address
;
390 int limit
= PMAKE_DEF_MAX_JOBS
; /* Default setting. */
392 WCSTOMBS(mbs_buffer
, hostname
);
395 if ((!*ms
) || (*ms
== '\n') || (*ms
!= '=')) {
397 warning(gettext("expected `=' after max, ignoring rest of line for host %s"),
404 if ((*ms
!= '\n') && (*ms
!= '\0')) {
405 /* We've found, hopefully, a valid "max" value. */
406 limit
= (int) wcstol(ms
, &ms
, 10);
408 limit
= PMAKE_DEF_MAX_JOBS
;
409 warning(gettext("max value cannot be less than or equal to zero for host %s"), mbs_buffer
);
412 /* No "max" value after "max=". */
413 warning(gettext("no max value specified for host %s"), mbs_buffer
);