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