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 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include <sys/param.h>
  30 #include <sys/wait.h>
  31 #include <unistd.h>
  32 #include <libintl.h>
  33 
  34 #include <vroot/report.h>
  35 #include <vroot/vroot.h>
  36 #include <mk/defs.h>      /* for tmpdir */
  37 
  38 static  FILE    *report_file;
  39 static  FILE    *command_output_fp;
  40 static  char    *target_being_reported_for;
  41 static  char    *search_dir;
  42 static  char    command_output_tmpfile[30];
  43 static  int     is_path = 0;
  44 static  char    sfile[MAXPATHLEN];
  45 extern "C" {
  46 static  void    (*warning_ptr) (char *, ...) = (void (*) (char *, ...)) NULL;
  47 }
  48 
  49 FILE *
  50 get_report_file(void)
  51 {
  52         return(report_file);
  53 }
  54 
  55 char *
  56 get_target_being_reported_for(void)
  57 {
  58         return(target_being_reported_for);
  59 }
  60 
  61 extern "C" {
  62 static void
  63 close_report_file(void)
  64 {
  65         (void)fputs("\n", report_file);
  66         (void)fclose(report_file);
  67 }
  68 } // extern "C"
  69 
  70 static void
  71 clean_up(FILE *nse_depinfo_fp, FILE *merge_fp, char *nse_depinfo_file, char *merge_file, int unlinkf)
  72 {
  73         fclose(nse_depinfo_fp);
  74         fclose(merge_fp);
  75         fclose(command_output_fp);
  76         unlink(command_output_tmpfile);
  77         if (unlinkf)
  78                 unlink(merge_file);
  79         else
  80                 rename(merge_file, nse_depinfo_file);
  81 }
  82 
  83 
  84 /*
  85  *  Update the file, if necessary.  We don't want to rewrite
  86  *  the file if we don't have to because we don't want the time of the file
  87  *  to change in that case.
  88  */
  89 
  90 extern "C" {
  91 static void
  92 close_file(void)
  93 {
  94         char            line[MAXPATHLEN+2];
  95         char            buf[MAXPATHLEN+2];
  96         FILE            *nse_depinfo_fp;
  97         FILE            *merge_fp;
  98         char            nse_depinfo_file[MAXPATHLEN];
  99         char            merge_file[MAXPATHLEN];
 100         char            lock_file[MAXPATHLEN];
 101         int             err;
 102         int             len;
 103         int             changed = 0;
 104         int             file_locked;
 105 
 106         fprintf(command_output_fp, "\n");
 107         fclose(command_output_fp);
 108         if ((command_output_fp = fopen(command_output_tmpfile, "r")) == NULL) {
 109                 return;
 110         }
 111         sprintf(nse_depinfo_file, "%s/%s", search_dir, NSE_DEPINFO);
 112         sprintf(merge_file, "%s/.tmp%s.%d", search_dir, NSE_DEPINFO, getpid());
 113         sprintf(lock_file, "%s/%s", search_dir, NSE_DEPINFO_LOCK);
 114         err = file_lock(nse_depinfo_file, lock_file, &file_locked, 0);
 115         if (err) {
 116                 if (warning_ptr != (void (*) (char *, ...)) NULL) {
 117                         (*warning_ptr)(gettext("Couldn't write to %s"), nse_depinfo_file);
 118                       }
 119                 unlink(command_output_tmpfile);
 120                 return;
 121         }
 122         /* If .nse_depinfo file doesn't exist */
 123         if ((nse_depinfo_fp = fopen(nse_depinfo_file, "r+")) == NULL) {
 124                 if (is_path) {
 125                         if ((nse_depinfo_fp = 
 126                              fopen(nse_depinfo_file, "w")) == NULL) {
 127                                 fprintf(stderr, gettext("Cannot open `%s' for writing\n"),
 128                                     nse_depinfo_file);
 129                                 unlink(command_output_tmpfile);
 130 
 131                                 unlink(lock_file);
 132                                 return;
 133                         }
 134                         while (fgets(line, MAXPATHLEN+2, command_output_fp) 
 135                                != NULL) {
 136                                 fprintf(nse_depinfo_fp, "%s", line);
 137                         }
 138                         fclose(command_output_fp);
 139                 }
 140                 fclose(nse_depinfo_fp);
 141                 if (file_locked) {
 142                         unlink(lock_file);
 143                 }
 144                 unlink(command_output_tmpfile);
 145                 return;
 146         }
 147         if ((merge_fp = fopen(merge_file, "w")) == NULL) {
 148                 fprintf(stderr, gettext("Cannot open %s for writing\n"), merge_file);
 149                 if (file_locked) {
 150                         unlink(lock_file);
 151                 }
 152                 unlink(command_output_tmpfile);
 153                 return;
 154         }
 155         len = strlen(sfile);
 156         while (fgets(line, MAXPATHLEN+2, nse_depinfo_fp) != NULL) {
 157                 if (strncmp(line, sfile, len) == 0 && line[len] == ':') {
 158                         while (fgets(buf, MAXPATHLEN+2, command_output_fp) 
 159                                != NULL) {
 160                                 if (is_path) {
 161                                         fprintf(merge_fp, "%s", buf);
 162                                         if (strcmp(line, buf)) {
 163                                                 /* changed */
 164                                                 changed = 1;
 165                                         }
 166                                 }
 167                                 if (buf[strlen(buf)-1] == '\n') {
 168                                         break;
 169                                 }
 170                         }
 171                         if (changed || !is_path) {
 172                                 while (fgets(line, MAXPATHLEN, nse_depinfo_fp)
 173                                        != NULL) {
 174                                         fputs(line, merge_fp);
 175                                 }
 176                                 clean_up(nse_depinfo_fp, merge_fp, 
 177                                          nse_depinfo_file, merge_file, 0);
 178                         } else {
 179                                 clean_up(nse_depinfo_fp, merge_fp, 
 180                                          nse_depinfo_file, merge_file, 1);
 181                         }
 182                         if (file_locked) {
 183                                 unlink(lock_file);
 184                         }
 185                         unlink(command_output_tmpfile);
 186                         return;
 187                 } /* entry found */
 188                 fputs(line, merge_fp);
 189         } 
 190         /* Entry never found.  Add it if there is a search path */
 191         if (is_path) {
 192                 while (fgets(line, MAXPATHLEN+2, command_output_fp) != NULL) {
 193                         fprintf(nse_depinfo_fp, "%s", line);
 194                 }
 195         }
 196         clean_up(nse_depinfo_fp, merge_fp, nse_depinfo_file, merge_file, 1);
 197         if (file_locked) {
 198                 unlink(lock_file);
 199         }
 200 }
 201 
 202 } // extern "C"
 203 
 204 static void
 205 report_dep(char *iflag, char *filename)
 206 {
 207 
 208         if (command_output_fp == NULL) {
 209                 sprintf(command_output_tmpfile, 
 210                         "%s/%s.%d.XXXXXX", tmpdir, NSE_DEPINFO, getpid());
 211                 int fd = mkstemp(command_output_tmpfile);
 212                 if ((fd < 0) || (command_output_fp = fdopen(fd, "w")) == NULL) {
 213                         return;
 214                 }
 215                 if ((search_dir = getenv("NSE_DEP")) == NULL) {
 216                         return;
 217                 }
 218                 atexit(close_file);
 219                 strcpy(sfile, filename);
 220                 if (iflag == NULL || *iflag == '\0') {
 221                         return;
 222                 }
 223                 fprintf(command_output_fp, "%s:", sfile);
 224         }
 225         fprintf(command_output_fp, " ");
 226         fprintf(command_output_fp, iflag);
 227         if (iflag != NULL) {
 228                 is_path = 1;
 229         }
 230 }
 231 
 232 void
 233 report_libdep(char *lib, char *flag)
 234 {
 235         char            *ptr;
 236         char            filename[MAXPATHLEN];
 237         char            *p;
 238 
 239         if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
 240                 return;
 241         }
 242         ptr = strchr(p, ' ');
 243         if(ptr) {
 244                 sprintf(filename, "%s-%s", ptr+1, flag);
 245                 is_path = 1;
 246                 report_dep(lib, filename);
 247         }
 248 }
 249 
 250 void
 251 report_search_path(char *iflag)
 252 {
 253         char            curdir[MAXPATHLEN];
 254         char            *sdir;
 255         char            *newiflag;
 256         char            filename[MAXPATHLEN];
 257         char            *p, *ptr;
 258 
 259         if ((sdir = getenv("NSE_DEP")) == NULL) {
 260                 return;
 261         }
 262         if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
 263                 return;
 264         }
 265         ptr = strchr(p, ' ');
 266         if( ! ptr ) {
 267                 return;
 268         }
 269         sprintf(filename, "%s-CPP", ptr+1);
 270         getcwd(curdir, sizeof(curdir));
 271         if (strcmp(curdir, sdir) != 0 && strlen(iflag) > 2 && 
 272             iflag[2] != '/') {
 273                 /* Makefile must have had an "cd xx; cc ..." */
 274                 /* Modify the -I path to be relative to the cd */
 275                 newiflag = (char *)malloc(strlen(iflag) + strlen(curdir) + 2);
 276                 sprintf(newiflag, "-%c%s/%s", iflag[1], curdir, &iflag[2]);
 277                 report_dep(newiflag, filename);
 278         } else {
 279                 report_dep(iflag, filename);
 280         }
 281 }
 282 
 283 void
 284 report_dependency(const char *name)
 285 {
 286         register char   *filename;
 287         char            buffer[MAXPATHLEN+1];
 288         register char   *p;
 289         register char   *p2;
 290         char            nse_depinfo_file[MAXPATHLEN];
 291 
 292         if (report_file == NULL) {
 293                 if ((filename= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
 294                         report_file = (FILE *)-1;
 295                         return;
 296                 }
 297                 if (strlen(filename) == 0) {
 298                         report_file = (FILE *)-1;
 299                         return;
 300                 }
 301                 (void)strcpy(buffer, name);
 302                 name = buffer;
 303                 p = strchr(filename, ' ');
 304                 if(p) {
 305                         *p= 0;
 306                 } else {
 307                         report_file = (FILE *)-1;
 308                         return;
 309                 }
 310                 if ((report_file= fopen(filename, "a")) == NULL) {
 311                         if ((report_file= fopen(filename, "w")) == NULL) {
 312                                 report_file= (FILE *)-1;
 313                                 return;
 314                         }
 315                 }
 316                 atexit(close_report_file);
 317                 if ((p2= strchr(p+1, ' ')) != NULL)
 318                         *p2= 0;
 319                 target_being_reported_for= (char *)malloc((unsigned)(strlen(p+1)+1));
 320                 (void)strcpy(target_being_reported_for, p+1);
 321                 (void)fputs(p+1, report_file);
 322                 (void)fputs(":", report_file);
 323                 *p= ' ';
 324                 if (p2 != NULL)
 325                         *p2= ' ';
 326         }
 327         if (report_file == (FILE *)-1)
 328                 return;
 329         (void)fputs(name, report_file);
 330         (void)fputs(" ", report_file);
 331 }
 332 
 333