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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * @(#)report.cc 1.17 06/12/12
27 */
28
29 #pragma ident "@(#)report.cc 1.17 06/12/12"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/param.h>
35 #include <sys/wait.h>
36 #include <unistd.h>
37
38 #include <vroot/report.h>
39 #include <vroot/vroot.h>
40 #include <mksdmsi18n/mksdmsi18n.h>
41 #include <avo/intl.h> /* for NOCATGETS */
42 #include <mk/defs.h> /* for tmpdir */
43
44 static FILE *report_file;
45 static FILE *command_output_fp;
46 static char *target_being_reported_for;
47 static char *search_dir;
48 static char command_output_tmpfile[30];
49 static int is_path = 0;
50 static char sfile[MAXPATHLEN];
51 extern "C" {
52 static void (*warning_ptr) (char *, ...) = (void (*) (char *, ...)) NULL;
53 }
54
55 FILE *
56 get_report_file(void)
57 {
58 return(report_file);
59 }
60
61 char *
62 get_target_being_reported_for(void)
63 {
64 return(target_being_reported_for);
65 }
66
67 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
68 extern "C" {
69 static void
70 close_report_file(void)
71 {
72 (void)fputs("\n", report_file);
73 (void)fclose(report_file);
74 }
75 } // extern "C"
76 #else
77 static void
78 close_report_file(int, ...)
79 {
80 (void)fputs("\n", report_file);
81 (void)fclose(report_file);
82 }
83 #endif
84
85 static void
86 clean_up(FILE *nse_depinfo_fp, FILE *merge_fp, char *nse_depinfo_file, char *merge_file, int unlinkf)
87 {
88 fclose(nse_depinfo_fp);
89 fclose(merge_fp);
90 fclose(command_output_fp);
91 unlink(command_output_tmpfile);
92 if (unlinkf)
93 unlink(merge_file);
94 else
95 rename(merge_file, nse_depinfo_file);
96 }
97
98
99 /*
100 * Update the file, if necessary. We don't want to rewrite
101 * the file if we don't have to because we don't want the time of the file
102 * to change in that case.
103 */
104
105 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
106 extern "C" {
107 static void
108 close_file(void)
109 #else
110 static void
111 close_file(int, ...)
112 #endif
113 {
114 char line[MAXPATHLEN+2];
115 char buf[MAXPATHLEN+2];
116 FILE *nse_depinfo_fp;
117 FILE *merge_fp;
118 char nse_depinfo_file[MAXPATHLEN];
119 char merge_file[MAXPATHLEN];
120 char lock_file[MAXPATHLEN];
121 int err;
122 int len;
123 int changed = 0;
124 int file_locked;
125
126 fprintf(command_output_fp, "\n");
127 fclose(command_output_fp);
128 if ((command_output_fp = fopen(command_output_tmpfile, "r")) == NULL) {
129 return;
130 }
131 sprintf(nse_depinfo_file, "%s/%s", search_dir, NSE_DEPINFO);
132 sprintf(merge_file, NOCATGETS("%s/.tmp%s.%d"), search_dir, NSE_DEPINFO, getpid());
133 sprintf(lock_file, "%s/%s", search_dir, NSE_DEPINFO_LOCK);
134 err = file_lock(nse_depinfo_file, lock_file, &file_locked, 0);
135 if (err) {
136 if (warning_ptr != (void (*) (char *, ...)) NULL) {
137 (*warning_ptr)(catgets(libmksdmsi18n_catd, 1, 147, "Couldn't write to %s"), nse_depinfo_file);
138 }
139 unlink(command_output_tmpfile);
140 return;
141 }
142 /* If .nse_depinfo file doesn't exist */
143 if ((nse_depinfo_fp = fopen(nse_depinfo_file, "r+")) == NULL) {
144 if (is_path) {
145 if ((nse_depinfo_fp =
146 fopen(nse_depinfo_file, "w")) == NULL) {
147 fprintf(stderr, catgets(libmksdmsi18n_catd, 1, 148, "Cannot open `%s' for writing\n"),
148 nse_depinfo_file);
149 unlink(command_output_tmpfile);
150
151 unlink(lock_file);
152 return;
153 }
154 while (fgets(line, MAXPATHLEN+2, command_output_fp)
155 != NULL) {
156 fprintf(nse_depinfo_fp, "%s", line);
157 }
158 fclose(command_output_fp);
159 }
160 fclose(nse_depinfo_fp);
161 if (file_locked) {
162 unlink(lock_file);
163 }
164 unlink(command_output_tmpfile);
165 return;
166 }
167 if ((merge_fp = fopen(merge_file, "w")) == NULL) {
168 fprintf(stderr, catgets(libmksdmsi18n_catd, 1, 149, "Cannot open %s for writing\n"), merge_file);
169 if (file_locked) {
170 unlink(lock_file);
171 }
172 unlink(command_output_tmpfile);
173 return;
174 }
175 len = strlen(sfile);
176 while (fgets(line, MAXPATHLEN+2, nse_depinfo_fp) != NULL) {
177 if (strncmp(line, sfile, len) == 0 && line[len] == ':') {
178 while (fgets(buf, MAXPATHLEN+2, command_output_fp)
179 != NULL) {
180 if (is_path) {
181 fprintf(merge_fp, "%s", buf);
182 if (strcmp(line, buf)) {
183 /* changed */
184 changed = 1;
185 }
186 }
187 if (buf[strlen(buf)-1] == '\n') {
188 break;
189 }
190 }
191 if (changed || !is_path) {
192 while (fgets(line, MAXPATHLEN, nse_depinfo_fp)
193 != NULL) {
194 fputs(line, merge_fp);
195 }
196 clean_up(nse_depinfo_fp, merge_fp,
197 nse_depinfo_file, merge_file, 0);
198 } else {
199 clean_up(nse_depinfo_fp, merge_fp,
200 nse_depinfo_file, merge_file, 1);
201 }
202 if (file_locked) {
203 unlink(lock_file);
204 }
205 unlink(command_output_tmpfile);
206 return;
207 } /* entry found */
208 fputs(line, merge_fp);
209 }
210 /* Entry never found. Add it if there is a search path */
211 if (is_path) {
212 while (fgets(line, MAXPATHLEN+2, command_output_fp) != NULL) {
213 fprintf(nse_depinfo_fp, "%s", line);
214 }
215 }
216 clean_up(nse_depinfo_fp, merge_fp, nse_depinfo_file, merge_file, 1);
217 if (file_locked) {
218 unlink(lock_file);
219 }
220 }
221
222 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
223 } // extern "C"
224 #endif
225
226 static void
227 report_dep(char *iflag, char *filename)
228 {
229
230 if (command_output_fp == NULL) {
231 sprintf(command_output_tmpfile,
232 NOCATGETS("%s/%s.%d.XXXXXX"), tmpdir, NSE_DEPINFO, getpid());
233 int fd = mkstemp(command_output_tmpfile);
234 if ((fd < 0) || (command_output_fp = fdopen(fd, "w")) == NULL) {
235 return;
236 }
237 if ((search_dir = getenv(NOCATGETS("NSE_DEP"))) == NULL) {
238 return;
239 }
240 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
241 atexit(close_file);
242 #else
243 on_exit(close_file, 0);
244 #endif
245 strcpy(sfile, filename);
246 if (iflag == NULL || *iflag == '\0') {
247 return;
248 }
249 fprintf(command_output_fp, "%s:", sfile);
250 }
251 fprintf(command_output_fp, " ");
252 fprintf(command_output_fp, iflag);
253 if (iflag != NULL) {
254 is_path = 1;
255 }
256 }
257
258 void
259 report_libdep(char *lib, char *flag)
260 {
261 char *ptr;
262 char filename[MAXPATHLEN];
263 char *p;
264
265 if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
266 return;
267 }
268 ptr = strchr(p, ' ');
269 if(ptr) {
270 sprintf(filename, "%s-%s", ptr+1, flag);
271 is_path = 1;
272 report_dep(lib, filename);
273 }
274 }
275
276 void
277 report_search_path(char *iflag)
278 {
279 char curdir[MAXPATHLEN];
280 char *sdir;
281 char *newiflag;
282 char filename[MAXPATHLEN];
283 char *p, *ptr;
284
285 if ((sdir = getenv(NOCATGETS("NSE_DEP"))) == NULL) {
286 return;
287 }
288 if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
289 return;
290 }
291 ptr = strchr(p, ' ');
292 if( ! ptr ) {
293 return;
294 }
295 sprintf(filename, NOCATGETS("%s-CPP"), ptr+1);
296 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
297 getcwd(curdir, sizeof(curdir));
298 #else
299 getwd(curdir);
300 #endif
301 if (strcmp(curdir, sdir) != 0 && strlen(iflag) > 2 &&
302 iflag[2] != '/') {
303 /* Makefile must have had an "cd xx; cc ..." */
304 /* Modify the -I path to be relative to the cd */
305 newiflag = (char *)malloc(strlen(iflag) + strlen(curdir) + 2);
306 sprintf(newiflag, "-%c%s/%s", iflag[1], curdir, &iflag[2]);
307 report_dep(newiflag, filename);
308 } else {
309 report_dep(iflag, filename);
310 }
311 }
312
313 void
314 report_dependency(register char *name)
315 {
316 register char *filename;
317 char buffer[MAXPATHLEN+1];
318 register char *p;
319 register char *p2;
320 char nse_depinfo_file[MAXPATHLEN];
321
322 if (report_file == NULL) {
323 if ((filename= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
324 report_file = (FILE *)-1;
325 return;
326 }
327 if (strlen(filename) == 0) {
328 report_file = (FILE *)-1;
329 return;
330 }
331 (void)strcpy(buffer, name);
332 name = buffer;
333 p = strchr(filename, ' ');
334 if(p) {
335 *p= 0;
336 } else {
337 report_file = (FILE *)-1;
338 return;
339 }
340 if ((report_file= fopen(filename, "a")) == NULL) {
341 if ((report_file= fopen(filename, "w")) == NULL) {
342 report_file= (FILE *)-1;
343 return;
344 }
345 }
346 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
347 atexit(close_report_file);
348 #else
349 (void)on_exit(close_report_file, (char *)report_file);
350 #endif
351 if ((p2= strchr(p+1, ' ')) != NULL)
352 *p2= 0;
353 target_being_reported_for= (char *)malloc((unsigned)(strlen(p+1)+1));
354 (void)strcpy(target_being_reported_for, p+1);
355 (void)fputs(p+1, report_file);
356 (void)fputs(":", report_file);
357 *p= ' ';
358 if (p2 != NULL)
359 *p2= ' ';
360 }
361 if (report_file == (FILE *)-1)
362 return;
363 (void)fputs(name, report_file);
364 (void)fputs(" ", report_file);
365 }
366
367 #ifdef MAKE_IT
368 void
369 make_it(filename)
370 register char *filename;
371 {
372 register char *command;
373 register char *argv[6];
374 register int pid;
375 union wait foo;
376
377 if (getenv(SUNPRO_DEPENDENCIES) == NULL) return;
378 command= alloca(strlen(filename)+32);
379 (void)sprintf(command, NOCATGETS("make %s\n"), filename);
380 switch (pid= fork()) {
381 case 0: /* child */
382 argv[0]= NOCATGETS("csh");
383 argv[1]= NOCATGETS("-c");
384 argv[2]= command;
385 argv[3]= 0;
386 (void)dup2(2, 1);
387 execve(NOCATGETS("/bin/sh"), argv, environ);
388 perror(NOCATGETS("execve error"));
389 exit(1);
390 case -1: /* error */
391 perror(NOCATGETS("fork error"));
392 default: /* parent */
393 while (wait(&foo) != pid);};
394 }
395 #endif
396