Print this page
    
4732 /usr/bin/file should provide -b option for compatiblity with GNU/BSD file
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/file/file.c
          +++ new/usr/src/cmd/file/file.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  22   22  /*        All Rights Reserved   */
  23   23  
  24   24  
  25   25  /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  26   26  /*        All Rights Reserved   */
  27   27  
  28   28  /*
  29   29   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  30   30   * Use is subject to license terms.
  31   31   */
  32   32  
  33   33  #define _LARGEFILE64_SOURCE
  34   34  
  35   35  /* Get definitions for the relocation types supported. */
  36   36  #define ELF_TARGET_ALL
  37   37  
  38   38  #include <ctype.h>
  39   39  #include <unistd.h>
  40   40  #include <fcntl.h>
  41   41  #include <signal.h>
  42   42  #include <stdio.h>
  43   43  #include <libelf.h>
  44   44  #include <stdlib.h>
  45   45  #include <limits.h>
  46   46  #include <locale.h>
  47   47  #include <wctype.h>
  48   48  #include <string.h>
  49   49  #include <errno.h>
  50   50  #include <door.h>
  51   51  #include <sys/param.h>
  52   52  #include <sys/types.h>
  53   53  #include <sys/mkdev.h>
  54   54  #include <sys/stat.h>
  55   55  #include <sys/elf.h>
  56   56  #include <procfs.h>
  57   57  #include <sys/core.h>
  58   58  #include <sys/dumphdr.h>
  59   59  #include <netinet/in.h>
  60   60  #include <gelf.h>
  61   61  #include <elfcap.h>
  62   62  #include <sgsrtcid.h>
  63   63  #include "file.h"
  64   64  #include "elf_read.h"
  65   65  
  66   66  /*
  67   67   *      Misc
  68   68   */
  69   69  
  70   70  #define FBSZ            512
  71   71  #define MLIST_SZ        12
  72   72  
  73   73  /*
  74   74   * The 0x8FCA0102 magic string was used in crash dumps generated by releases
  75   75   * prior to Solaris 7.
  76   76   */
  77   77  #define OLD_DUMP_MAGIC  0x8FCA0102
  78   78  
  79   79  #if defined(__sparc)
  80   80  #define NATIVE_ISA      "SPARC"
  81   81  #define OTHER_ISA       "Intel"
  82   82  #else
  83   83  #define NATIVE_ISA      "Intel"
  84   84  #define OTHER_ISA       "SPARC"
  85   85  #endif
  86   86  
  87   87  /* Assembly language comment char */
  88   88  #ifdef pdp11
  89   89  #define ASCOMCHAR '/'
  90   90  #else
  91   91  #define ASCOMCHAR '!'
  92   92  #endif
  93   93  
  94   94  #pragma align   16(fbuf)
  95   95  static char     fbuf[FBSZ];
  96   96  
  97   97  /*
  98   98   * Magic file variables
  99   99   */
 100  100  static intmax_t maxmagicoffset;
 101  101  static intmax_t tmpmax;
 102  102  static char     *magicbuf;
 103  103  
 104  104  static char     *dfile;
 105  105  static char     *troff[] = {    /* new troff intermediate lang */
 106  106                  "x", "T", "res", "init", "font", "202", "V0", "p1", 0};
 107  107  
 108  108  static char     *fort[] = {                     /* FORTRAN */
 109  109                  "function", "subroutine", "common", "dimension", "block",
 110  110                  "integer", "real", "data", "double",
 111  111                  "FUNCTION", "SUBROUTINE", "COMMON", "DIMENSION", "BLOCK",
 112  112                  "INTEGER", "REAL", "DATA", "DOUBLE", 0};
 113  113  
 114  114  static char     *asc[] = {              /* Assembler Commands */
 115  115                  "sys", "mov", "tst", "clr", "jmp", "cmp", "set", "inc",
 116  116                  "dec", 0};
 117  117  
 118  118  static char     *c[] = {                        /* C Language */
 119  119                  "int", "char", "float", "double", "short", "long", "unsigned",
 120  120                  "register", "static", "struct", "extern", 0};
 121  121  
 122  122  static char     *as[] = {       /* Assembler Pseudo Ops, prepended with '.' */
 123  123                  "globl", "global", "ident", "file", "byte", "even",
 124  124                  "text", "data", "bss", "comm", 0};
 125  125  
 126  126  /*
 127  127   * The line and debug section names are used by the strip command.
 128  128   * Any changes in the strip implementation need to be reflected here.
 129  129   */
 130  130  static char     *debug_sections[] = { /* Debug sections in a ELF file */
 131  131                  ".debug", ".stab", ".dwarf", ".line", NULL};
 132  132  
 133  133  /* start for MB env */
 134  134  static wchar_t  wchar;
 135  135  static int      length;
 136  136  static int      IS_ascii;
 137  137  static int      Max;
 138  138  /* end for MB env */
 139  139  static int      i;      /* global index into first 'fbsz' bytes of file */
 140  140  static int      fbsz;
 141  141  static int      ifd = -1;
 142  142  static int      elffd = -1;
 143  143  static int      tret;
 144  144  static int      hflg;
 145  145  static int      dflg;
 146  146  static int      mflg;
 147  147  static int      M_flg;
 148  148  static int      iflg;
 149  149  static struct stat64    mbuf;
 150  150  
 151  151  static char     **mlist1;       /* 1st ordered list of magic files */
 152  152  static char     **mlist2;       /* 2nd ordered list of magic files */
 153  153  static size_t   mlist1_sz;      /* number of ptrs allocated for mlist1 */
 154  154  static size_t   mlist2_sz;      /* number of ptrs allocated for mlist2 */
 155  155  static char     **mlist1p;      /* next entry in mlist1 */
 156  156  static char     **mlist2p;      /* next entry in mlist2 */
 157  157  
 158  158  static ssize_t  mread;
 159  159  
 160  160  static void ar_coff_or_aout(int ifd);
 161  161  static int type(char *file);
 162  162  static int def_position_tests(char *file);
 163  163  static void def_context_tests(void);
 164  164  static int troffint(char *bp, int n);
 165  165  static int lookup(char **tab);
 166  166  static int ccom(void);
 167  167  static int ascom(void);
 168  168  static int sccs(void);
 169  169  static int english(char *bp, int n);
 170  170  static int shellscript(char buf[], struct stat64 *sb);
 171  171  static int elf_check(char *file);
 172  172  static int get_door_target(char *, char *, size_t);
 173  173  static int zipfile(char *, int);
 174  174  static int is_crash_dump(const char *, int);
 175  175  static void print_dumphdr(const int, const dumphdr_t *, uint32_t (*)(uint32_t),
 176  176      const char *);
 177  177  static uint32_t swap_uint32(uint32_t);
 178  178  static uint32_t return_uint32(uint32_t);
 179  179  static void usage(void);
 180  180  static void default_magic(void);
 181  181  static void add_to_mlist(char *, int);
 182  182  static void fd_cleanup(void);
 183  183  static int is_rtld_config(void);
 184  184  
 185  185  /* from elf_read.c */
 186  186  int elf_read32(int elffd, Elf_Info *EInfo);
 187  187  int elf_read64(int elffd, Elf_Info *EInfo);
 188  188  
 189  189  #ifdef XPG4
 190  190          /* SUSv3 requires a single <space> after the colon */
 191  191  #define prf(x)  (void) printf("%s: ", x);
 192  192  #else   /* !XPG4 */
 193  193  #define prf(x)  (void) printf("%s:%s", x, (int)strlen(x) > 6 ? "\t" : "\t\t");
 194  194  #endif  /* XPG4 */
 195  195  
 196  196  /*
 197  197   * Static program identifier - used to prevent localization of the name "file"
  
    | 
      ↓ open down ↓ | 
    197 lines elided | 
    
      ↑ open up ↑ | 
  
 198  198   * within individual error messages.
 199  199   */
 200  200  const char *File = "file";
 201  201  
 202  202  int
 203  203  main(int argc, char **argv)
 204  204  {
 205  205          char    *p;
 206  206          int     ch;
 207  207          FILE    *fl;
      208 +        int     bflg = 0;
 208  209          int     cflg = 0;
 209  210          int     eflg = 0;
 210  211          int     fflg = 0;
 211  212          char    *ap = NULL;
 212  213          int     pathlen;
 213  214          char    **filep;
 214  215  
 215  216          (void) setlocale(LC_ALL, "");
 216  217  #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 217  218  #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 218  219  #endif
 219  220          (void) textdomain(TEXT_DOMAIN);
 220  221  
 221      -        while ((ch = getopt(argc, argv, "M:cdf:him:")) != EOF) {
      222 +        while ((ch = getopt(argc, argv, "M:bcdf:him:")) != EOF) {
 222  223                  switch (ch) {
 223  224  
 224  225                  case 'M':
 225  226                          add_to_mlist(optarg, !dflg);
 226  227                          M_flg++;
 227  228                          break;
 228  229  
      230 +                case 'b':
      231 +                        bflg++;
      232 +                        break;
      233 +
 229  234                  case 'c':
 230  235                          cflg++;
 231  236                          break;
 232  237  
 233  238                  case 'd':
 234  239                          if (!dflg) {
 235  240                                  default_magic();
 236  241                                  add_to_mlist(dfile, 0);
 237  242                                  dflg++;
 238  243                          }
 239  244                          break;
 240  245  
 241  246                  case 'f':
 242  247                          fflg++;
 243  248                          errno = 0;
 244  249                          if ((fl = fopen(optarg, "r")) == NULL) {
 245  250                                  int err = errno;
 246  251                                  (void) fprintf(stderr, gettext("%s: cannot "
 247  252                                      "open file %s: %s\n"), File, optarg,
 248  253                                      err ? strerror(err) : "");
 249  254                                  usage();
 250  255                          }
 251  256                          pathlen = pathconf("/", _PC_PATH_MAX);
 252  257                          if (pathlen == -1) {
 253  258                                  int err = errno;
 254  259                                  (void) fprintf(stderr, gettext("%s: cannot "
 255  260                                      "determine maximum path length: %s\n"),
 256  261                                      File, strerror(err));
 257  262                                  exit(1);
 258  263                          }
 259  264                          pathlen += 2; /* for null and newline in fgets */
 260  265                          if ((ap = malloc(pathlen * sizeof (char))) == NULL) {
 261  266                                  int err = errno;
 262  267                                  (void) fprintf(stderr, gettext("%s: malloc "
 263  268                                      "failed: %s\n"), File, strerror(err));
 264  269                                  exit(2);
 265  270                          }
 266  271                          break;
 267  272  
 268  273                  case 'h':
 269  274                          hflg++;
 270  275                          break;
 271  276  
 272  277                  case 'i':
 273  278                          iflg++;
 274  279                          break;
 275  280  
 276  281                  case 'm':
 277  282                          add_to_mlist(optarg, !dflg);
 278  283                          mflg++;
 279  284                          break;
 280  285  
  
    | 
      ↓ open down ↓ | 
    42 lines elided | 
    
      ↑ open up ↑ | 
  
 281  286                  case '?':
 282  287                          eflg++;
 283  288                          break;
 284  289                  }
 285  290          }
 286  291          if (!cflg && !fflg && (eflg || optind == argc))
 287  292                  usage();
 288  293          if (iflg && (dflg || mflg || M_flg)) {
 289  294                  usage();
 290  295          }
 291      -        if (iflg && cflg) {
      296 +        if ((iflg && cflg) || (cflg && bflg)) {
 292  297                  usage();
 293  298          }
 294  299  
 295  300          if (!dflg && !mflg && !M_flg && !iflg) {
 296  301          /* no -d, -m, nor -M option; also -i option doesn't need magic  */
 297  302                  default_magic();
 298  303                  if (f_mkmtab(dfile, cflg, 0) == -1) {
 299  304                          exit(2);
 300  305                  }
 301  306          }
 302  307  
 303  308          else if (mflg && !M_flg && !dflg) {
 304  309          /* -m specified without -d nor -M */
 305  310  
 306  311  #ifdef XPG4     /* For SUSv3 only */
 307  312  
 308  313                  /*
 309  314                   * The default position-dependent magic file tests
 310  315                   * in /etc/magic will follow all the -m magic tests.
 311  316                   */
 312  317  
 313  318                  for (filep = mlist1; filep < mlist1p; filep++) {
 314  319                          if (f_mkmtab(*filep, cflg, 1) == -1) {
 315  320                                  exit(2);
 316  321                          }
 317  322                  }
 318  323                  default_magic();
 319  324                  if (f_mkmtab(dfile, cflg, 0) == -1) {
 320  325                          exit(2);
 321  326                  }
 322  327  #else   /* !XPG4 */
 323  328                  /*
 324  329                   * Retain Solaris file behavior for -m before SUSv3,
 325  330                   * when the new -d and -M options are not specified.
 326  331                   * Use the -m file specified in place of the default
 327  332                   * /etc/magic file.  Solaris file will
 328  333                   * now allow more than one magic file to be specified
 329  334                   * with multiple -m options, for consistency with
 330  335                   * other behavior.
 331  336                   *
 332  337                   * Put the magic table(s) specified by -m into
 333  338                   * the second magic table instead of the first
 334  339                   * (as indicated by the last argument to f_mkmtab()),
 335  340                   * since they replace the /etc/magic tests and
 336  341                   * must be executed alongside the default
 337  342                   * position-sensitive tests.
 338  343                   */
 339  344  
 340  345                  for (filep = mlist1; filep < mlist1p; filep++) {
 341  346                          if (f_mkmtab(*filep, cflg, 0) == -1) {
 342  347                                  exit(2);
 343  348                          }
 344  349                  }
 345  350  #endif /* XPG4 */
 346  351          } else {
 347  352                  /*
 348  353                   * For any other combination of -d, -m, and -M,
 349  354                   * use the magic files in command-line order.
 350  355                   * Store the entries from the two separate lists of magic
 351  356                   * files, if any, into two separate magic file tables.
 352  357                   * mlist1: magic tests executed before default magic tests
 353  358                   * mlist2: default magic tests and after
 354  359                   */
 355  360                  for (filep = mlist1; filep && (filep < mlist1p); filep++) {
 356  361                          if (f_mkmtab(*filep, cflg, 1) == -1) {
 357  362                                  exit(2);
 358  363                          }
 359  364                  }
 360  365                  for (filep = mlist2; filep && (filep < mlist2p); filep++) {
 361  366                          if (f_mkmtab(*filep, cflg, 0) == -1) {
 362  367                                  exit(2);
 363  368                          }
 364  369                  }
 365  370          }
 366  371  
 367  372          /* Initialize the magic file variables; check both magic tables */
 368  373          tmpmax = f_getmaxoffset(1);
 369  374          maxmagicoffset = f_getmaxoffset(0);
 370  375          if (maxmagicoffset < tmpmax) {
 371  376                  maxmagicoffset = tmpmax;
 372  377          }
 373  378          if (maxmagicoffset < (intmax_t)FBSZ)
 374  379                  maxmagicoffset = (intmax_t)FBSZ;
 375  380          if ((magicbuf = malloc(maxmagicoffset)) == NULL) {
 376  381                  int err = errno;
 377  382                  (void) fprintf(stderr, gettext("%s: malloc failed: %s\n"),
 378  383                      File, strerror(err));
 379  384                  exit(2);
 380  385          }
 381  386  
 382  387          if (cflg) {
 383  388                  f_prtmtab();
 384  389                  if (ferror(stdout) != 0) {
 385  390                          (void) fprintf(stderr, gettext("%s: error writing to "
 386  391                              "stdout\n"), File);
 387  392                          exit(1);
 388  393                  }
 389  394                  if (fclose(stdout) != 0) {
 390  395                          int err = errno;
 391  396                          (void) fprintf(stderr, gettext("%s: fclose "
 392  397                              "failed: %s\n"), File, strerror(err));
 393  398                          exit(1);
 394  399                  }
 395  400                  exit(0);
 396  401          }
 397  402  
 398  403          for (; fflg || optind < argc; optind += !fflg) {
 399  404                  register int    l;
 400  405  
 401  406                  if (fflg) {
  
    | 
      ↓ open down ↓ | 
    100 lines elided | 
    
      ↑ open up ↑ | 
  
 402  407                          if ((p = fgets(ap, pathlen, fl)) == NULL) {
 403  408                                  fflg = 0;
 404  409                                  optind--;
 405  410                                  continue;
 406  411                          }
 407  412                          l = strlen(p);
 408  413                          if (l > 0)
 409  414                                  p[l - 1] = '\0';
 410  415                  } else
 411  416                          p = argv[optind];
 412      -                prf(p);                         /* print "file_name:<tab>" */
      417 +
      418 +                if (!bflg)
      419 +                        prf(p);         /* print "file_name:<tab>" */
 413  420  
 414  421                  if (type(p))
 415  422                          tret = 1;
 416  423          }
 417  424          if (ap != NULL)
 418  425                  free(ap);
 419  426          if (tret != 0)
 420  427                  exit(tret);
 421  428  
 422  429          if (ferror(stdout) != 0) {
 423  430                  (void) fprintf(stderr, gettext("%s: error writing to "
 424  431                      "stdout\n"), File);
 425  432                  exit(1);
 426  433          }
 427  434          if (fclose(stdout) != 0) {
 428  435                  int err = errno;
 429  436                  (void) fprintf(stderr, gettext("%s: fclose failed: %s\n"),
 430  437                      File, strerror(err));
 431  438                  exit(1);
 432  439          }
 433  440          return (0);
 434  441  }
 435  442  
 436  443  static int
 437  444  type(char *file)
 438  445  {
 439  446          int     cc;
 440  447          char    buf[BUFSIZ];
 441  448          int     (*statf)() = hflg ? lstat64 : stat64;
 442  449  
 443  450          i = 0;          /* reset index to beginning of file */
 444  451          ifd = -1;
 445  452          if ((*statf)(file, &mbuf) < 0) {
 446  453                  if (statf == lstat64 || lstat64(file, &mbuf) < 0) {
 447  454                          int err = errno;
 448  455                          (void) printf(gettext("cannot open: %s\n"),
 449  456                              strerror(err));
 450  457                          return (0);             /* POSIX.2 */
 451  458                  }
 452  459          }
 453  460          switch (mbuf.st_mode & S_IFMT) {
 454  461          case S_IFREG:
 455  462                  if (iflg) {
 456  463                          (void) printf(gettext("regular file\n"));
 457  464                          return (0);
 458  465                  }
 459  466                  break;
 460  467          case S_IFCHR:
 461  468                  (void) printf(gettext("character"));
 462  469                  goto spcl;
 463  470  
 464  471          case S_IFDIR:
 465  472                  (void) printf(gettext("directory\n"));
 466  473                  return (0);
 467  474  
 468  475          case S_IFIFO:
 469  476                  (void) printf(gettext("fifo\n"));
 470  477                  return (0);
 471  478  
 472  479          case S_IFLNK:
 473  480                  if ((cc = readlink(file, buf, BUFSIZ)) < 0) {
 474  481                          int err = errno;
 475  482                          (void) printf(gettext("readlink error: %s\n"),
 476  483                              strerror(err));
 477  484                          return (1);
 478  485                  }
 479  486                  buf[cc] = '\0';
 480  487                  (void) printf(gettext("symbolic link to %s\n"), buf);
 481  488                  return (0);
 482  489  
 483  490          case S_IFBLK:
 484  491                  (void) printf(gettext("block"));
 485  492                                          /* major and minor, see sys/mkdev.h */
 486  493  spcl:
 487  494                  (void) printf(gettext(" special (%d/%d)\n"),
 488  495                      major(mbuf.st_rdev), minor(mbuf.st_rdev));
 489  496                  return (0);
 490  497  
 491  498          case S_IFSOCK:
 492  499                  (void) printf("socket\n");
 493  500                  /* FIXME, should open and try to getsockname. */
 494  501                  return (0);
 495  502  
 496  503          case S_IFDOOR:
 497  504                  if (get_door_target(file, buf, sizeof (buf)) == 0)
 498  505                          (void) printf(gettext("door to %s\n"), buf);
 499  506                  else
 500  507                          (void) printf(gettext("door\n"));
 501  508                  return (0);
 502  509  
 503  510          }
 504  511  
 505  512          if (elf_version(EV_CURRENT) == EV_NONE) {
 506  513                  (void) printf(gettext("libelf is out of date\n"));
 507  514                  return (1);
 508  515          }
 509  516  
 510  517          ifd = open64(file, O_RDONLY);
 511  518          if (ifd < 0) {
 512  519                  int err = errno;
 513  520                  (void) printf(gettext("cannot open: %s\n"), strerror(err));
 514  521                  return (0);                     /* POSIX.2 */
 515  522          }
 516  523  
 517  524          /* need another fd for elf, since we might want to read the file too */
 518  525          elffd = open64(file, O_RDONLY);
 519  526          if (elffd < 0) {
 520  527                  int err = errno;
 521  528                  (void) printf(gettext("cannot open: %s\n"), strerror(err));
 522  529                  (void) close(ifd);
 523  530                  ifd = -1;
 524  531                  return (0);                     /* POSIX.2 */
 525  532          }
 526  533          if ((fbsz = read(ifd, fbuf, FBSZ)) == -1) {
 527  534                  int err = errno;
 528  535                  (void) printf(gettext("cannot read: %s\n"), strerror(err));
 529  536                  (void) close(ifd);
 530  537                  ifd = -1;
 531  538                  return (0);                     /* POSIX.2 */
 532  539          }
 533  540          if (fbsz == 0) {
 534  541                  (void) printf(gettext("empty file\n"));
 535  542                  fd_cleanup();
 536  543                  return (0);
 537  544          }
 538  545  
 539  546          /*
 540  547           * First try user-specified position-dependent magic tests, if any,
 541  548           * which need to execute before the default tests.
 542  549           */
 543  550          if ((mread = pread(ifd, (void*)magicbuf, (size_t)maxmagicoffset,
 544  551              (off_t)0)) == -1) {
 545  552                  int err = errno;
 546  553                  (void) printf(gettext("cannot read: %s\n"), strerror(err));
 547  554                  fd_cleanup();
 548  555                  return (0);
 549  556          }
 550  557  
 551  558          /*
 552  559           * ChecK against Magic Table entries.
 553  560           * Check first magic table for magic tests to be applied
 554  561           * before default tests.
 555  562           * If no default tests are to be applied, all magic tests
 556  563           * should occur in this magic table.
 557  564           */
 558  565          switch (f_ckmtab(magicbuf, mread, 1)) {
 559  566                  case -1:        /* Error */
 560  567                          exit(2);
 561  568                          break;
 562  569                  case 0:         /* Not magic */
 563  570                          break;
 564  571                  default:        /* Switch is magic index */
 565  572                          (void) putchar('\n');
 566  573                          fd_cleanup();
 567  574                          return (0);
 568  575                          /* NOTREACHED */
 569  576                          break;
 570  577          }
 571  578  
 572  579          if (dflg || !M_flg) {
 573  580                  /*
 574  581                   * default position-dependent tests,
 575  582                   * plus non-default magic tests, if any
 576  583                   */
 577  584                  switch (def_position_tests(file)) {
 578  585                          case -1:        /* error */
 579  586                                  fd_cleanup();
 580  587                                  return (1);
 581  588                          case 1: /* matching type found */
 582  589                                  fd_cleanup();
 583  590                                  return (0);
 584  591                                  /* NOTREACHED */
 585  592                                  break;
 586  593                          case 0:         /* no matching type found */
 587  594                                  break;
 588  595                  }
 589  596                  /* default context-sensitive tests */
 590  597                  def_context_tests();
 591  598          } else {
 592  599                  /* no more tests to apply; no match was found */
 593  600                  (void) printf(gettext("data\n"));
 594  601          }
 595  602          fd_cleanup();
 596  603          return (0);
 597  604  }
 598  605  
 599  606  /*
 600  607   * def_position_tests() - applies default position-sensitive tests,
 601  608   *      looking for values in specific positions in the file.
 602  609   *      These are followed by default (followed by possibly some
 603  610   *      non-default) magic file tests.
 604  611   *
 605  612   *      All position-sensitive tests, default or otherwise, must
 606  613   *      be applied before context-sensitive tests, to avoid
 607  614   *      false context-sensitive matches.
 608  615   *
 609  616   *      Returns -1 on error which should result in error (non-zero)
 610  617   *      exit status for the file utility.
 611  618   *      Returns 0 if no matching file type found.
 612  619   *      Returns 1 if matching file type found.
 613  620   */
 614  621  
 615  622  static int
 616  623  def_position_tests(char *file)
 617  624  {
 618  625          if (sccs()) {   /* look for "1hddddd" where d is a digit */
 619  626                  (void) printf("sccs \n");
 620  627                  return (1);
 621  628          }
 622  629          if (fbuf[0] == '#' && fbuf[1] == '!' && shellscript(fbuf+2, &mbuf))
 623  630                  return (1);
 624  631  
 625  632          if (elf_check(file) == 0) {
 626  633                  (void) putchar('\n');
 627  634                  return (1);
 628  635          /* LINTED: pointer cast may result in improper alignment */
 629  636          } else if (*(int *)fbuf == CORE_MAGIC) {
 630  637                  /* LINTED: pointer cast may result in improper alignment */
 631  638                  struct core *corep = (struct core *)fbuf;
 632  639  
 633  640                  (void) printf("a.out core file");
 634  641  
 635  642                  if (*(corep->c_cmdname) != '\0')
 636  643                          (void) printf(" from '%s'", corep->c_cmdname);
 637  644                  (void) putchar('\n');
 638  645                  return (1);
 639  646          }
 640  647  
 641  648          /*
 642  649           * Runtime linker (ld.so.1) configuration file.
 643  650           */
 644  651          if (is_rtld_config())
 645  652                  return (1);
 646  653  
 647  654          /*
 648  655           * ZIP files, JAR files, and Java executables
 649  656           */
 650  657          if (zipfile(fbuf, ifd))
 651  658                  return (1);
 652  659  
 653  660          if (is_crash_dump(fbuf, ifd))
 654  661                  return (1);
 655  662  
 656  663          /*
 657  664           * ChecK against Magic Table entries.
 658  665           * The magic entries checked here always start with default
 659  666           * magic tests and may be followed by other, non-default magic
 660  667           * tests.  If no default tests are to be executed, all the
 661  668           * magic tests should have been in the first magic table.
 662  669           */
 663  670          switch (f_ckmtab(magicbuf, mread, 0)) {
 664  671                  case -1:        /* Error */
 665  672                          exit(2);
 666  673                          break;
 667  674                  case 0:         /* Not magic */
 668  675                          return (0);
 669  676                          /* NOTREACHED */
 670  677                          break;
 671  678                  default:        /* Switch is magic index */
 672  679  
 673  680                          /*
 674  681                           * f_ckmtab recognizes file type,
 675  682                           * check if it is PostScript.
 676  683                           * if not, check if elf or a.out
 677  684                           */
 678  685                          if (magicbuf[0] == '%' && magicbuf[1] == '!') {
 679  686                                  (void) putchar('\n');
 680  687                          } else {
 681  688  
 682  689                                  /*
 683  690                                   * Check that the file is executable (dynamic
 684  691                                   * objects must be executable to be exec'ed,
 685  692                                   * shared objects need not be, but by convention
 686  693                                   * should be executable).
 687  694                                   *
 688  695                                   * Note that we should already have processed
 689  696                                   * the file if it was an ELF file.
 690  697                                   */
 691  698                                  ar_coff_or_aout(elffd);
 692  699                                  (void) putchar('\n');
 693  700                          }
 694  701                          return (1);
 695  702                          /* NOTREACHED */
 696  703                          break;
 697  704          }
 698  705  
 699  706          return (0);     /* file was not identified */
 700  707  }
 701  708  
 702  709  /*
 703  710   * def_context_tests() - default context-sensitive tests.
 704  711   *      These are the last tests to be applied.
 705  712   *      If no match is found, prints out "data".
 706  713   */
 707  714  
 708  715  static void
 709  716  def_context_tests(void)
 710  717  {
 711  718          int     j;
 712  719          int     nl;
 713  720          char    ch;
 714  721          int     len;
 715  722  
 716  723          if (ccom() == 0)
 717  724                  goto notc;
 718  725          while (fbuf[i] == '#') {
 719  726                  j = i;
 720  727                  while (fbuf[i++] != '\n') {
 721  728                          if (i - j > 255) {
 722  729                                  (void) printf(gettext("data\n"));
 723  730                                  return;
 724  731                          }
 725  732                          if (i >= fbsz)
 726  733                                  goto notc;
 727  734                  }
 728  735                  if (ccom() == 0)
 729  736                          goto notc;
 730  737          }
 731  738  check:
 732  739          if (lookup(c) == 1) {
 733  740                  while ((ch = fbuf[i]) != ';' && ch != '{') {
 734  741                          if ((len = mblen(&fbuf[i], MB_CUR_MAX)) <= 0)
 735  742                                  len = 1;
 736  743                          i += len;
 737  744                          if (i >= fbsz)
 738  745                                  goto notc;
 739  746                  }
 740  747                  (void) printf(gettext("c program text"));
 741  748                  goto outa;
 742  749          }
 743  750          nl = 0;
 744  751          while (fbuf[i] != '(') {
 745  752                  if (fbuf[i] <= 0)
 746  753                          goto notas;
 747  754                  if (fbuf[i] == ';') {
 748  755                          i++;
 749  756                          goto check;
 750  757                  }
 751  758                  if (fbuf[i++] == '\n')
 752  759                          if (nl++ > 6)
 753  760                                  goto notc;
 754  761                  if (i >= fbsz)
 755  762                          goto notc;
 756  763          }
 757  764          while (fbuf[i] != ')') {
 758  765                  if (fbuf[i++] == '\n')
 759  766                          if (nl++ > 6)
 760  767                                  goto notc;
 761  768                  if (i >= fbsz)
 762  769                          goto notc;
 763  770          }
 764  771          while (fbuf[i] != '{') {
 765  772                  if ((len = mblen(&fbuf[i], MB_CUR_MAX)) <= 0)
 766  773                          len = 1;
 767  774                  if (fbuf[i] == '\n')
 768  775                          if (nl++ > 6)
 769  776                                  goto notc;
 770  777                  i += len;
 771  778                  if (i >= fbsz)
 772  779                          goto notc;
 773  780          }
 774  781          (void) printf(gettext("c program text"));
 775  782          goto outa;
 776  783  notc:
 777  784          i = 0;                  /* reset to begining of file again */
 778  785          while (fbuf[i] == 'c' || fbuf[i] == 'C'|| fbuf[i] == '!' ||
 779  786              fbuf[i] == '*' || fbuf[i] == '\n') {
 780  787                  while (fbuf[i++] != '\n')
 781  788                          if (i >= fbsz)
 782  789                                  goto notfort;
 783  790          }
 784  791          if (lookup(fort) == 1) {
 785  792                  (void) printf(gettext("fortran program text"));
 786  793                  goto outa;
 787  794          }
 788  795  notfort:                        /* looking for assembler program */
 789  796          i = 0;                  /* reset to beginning of file again */
 790  797          if (ccom() == 0)        /* assembler programs may contain */
 791  798                                  /* c-style comments */
 792  799                  goto notas;
 793  800          if (ascom() == 0)
 794  801                  goto notas;
 795  802          j = i - 1;
 796  803          if (fbuf[i] == '.') {
 797  804                  i++;
 798  805                  if (lookup(as) == 1) {
 799  806                          (void) printf(gettext("assembler program text"));
 800  807                          goto outa;
 801  808                  } else if (j != -1 && fbuf[j] == '\n' && isalpha(fbuf[j + 2])) {
 802  809                          (void) printf(
 803  810                              gettext("[nt]roff, tbl, or eqn input text"));
 804  811                          goto outa;
 805  812                  }
 806  813          }
 807  814          while (lookup(asc) == 0) {
 808  815                  if (ccom() == 0)
 809  816                          goto notas;
 810  817                  if (ascom() == 0)
 811  818                          goto notas;
 812  819                  while (fbuf[i] != '\n' && fbuf[i++] != ':') {
 813  820                          if (i >= fbsz)
 814  821                                  goto notas;
 815  822                  }
 816  823                  while (fbuf[i] == '\n' || fbuf[i] == ' ' || fbuf[i] == '\t')
 817  824                          if (i++ >= fbsz)
 818  825                                  goto notas;
 819  826                  j = i - 1;
 820  827                  if (fbuf[i] == '.') {
 821  828                          i++;
 822  829                          if (lookup(as) == 1) {
 823  830                                  (void) printf(
 824  831                                      gettext("assembler program text"));
 825  832                                  goto outa;
 826  833                          } else if (fbuf[j] == '\n' && isalpha(fbuf[j+2])) {
 827  834                                  (void) printf(
 828  835                                      gettext("[nt]roff, tbl, or eqn input "
 829  836                                      "text"));
 830  837                                  goto outa;
 831  838                          }
 832  839                  }
 833  840          }
 834  841          (void) printf(gettext("assembler program text"));
 835  842          goto outa;
 836  843  notas:
 837  844          /* start modification for multibyte env */
 838  845          IS_ascii = 1;
 839  846          if (fbsz < FBSZ)
 840  847                  Max = fbsz;
 841  848          else
 842  849                  Max = FBSZ - MB_LEN_MAX; /* prevent cut of wchar read */
 843  850          /* end modification for multibyte env */
 844  851  
 845  852          for (i = 0; i < Max; /* null */)
 846  853                  if (fbuf[i] & 0200) {
 847  854                          IS_ascii = 0;
 848  855                          if (fbuf[0] == '\100' && fbuf[1] == '\357') {
 849  856                                  (void) printf(gettext("troff output\n"));
 850  857                                  return;
 851  858                          }
 852  859                  /* start modification for multibyte env */
 853  860                          if ((length = mbtowc(&wchar, &fbuf[i], MB_CUR_MAX))
 854  861                              <= 0 || !iswprint(wchar)) {
 855  862                                  (void) printf(gettext("data\n"));
 856  863                                  return;
 857  864                          }
 858  865                          i += length;
 859  866                  }
 860  867                  else
 861  868                          i++;
 862  869          i = fbsz;
 863  870                  /* end modification for multibyte env */
 864  871          if (mbuf.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))
 865  872                  (void) printf(gettext("commands text"));
 866  873          else if (troffint(fbuf, fbsz))
 867  874                  (void) printf(gettext("troff intermediate output text"));
 868  875          else if (english(fbuf, fbsz))
 869  876                  (void) printf(gettext("English text"));
 870  877          else if (IS_ascii)
 871  878                  (void) printf(gettext("ascii text"));
 872  879          else
 873  880                  (void) printf(gettext("text")); /* for multibyte env */
 874  881  outa:
 875  882          /*
 876  883           * This code is to make sure that no MB char is cut in half
 877  884           * while still being used.
 878  885           */
 879  886          fbsz = (fbsz < FBSZ ? fbsz : fbsz - MB_CUR_MAX + 1);
 880  887          while (i < fbsz) {
 881  888                  if (isascii(fbuf[i])) {
 882  889                          i++;
 883  890                          continue;
 884  891                  } else {
 885  892                          if ((length = mbtowc(&wchar, &fbuf[i], MB_CUR_MAX))
 886  893                              <= 0 || !iswprint(wchar)) {
 887  894                                  (void) printf(gettext(" with garbage\n"));
 888  895                                  return;
 889  896                          }
 890  897                          i = i + length;
 891  898                  }
 892  899          }
 893  900          (void) printf("\n");
 894  901  }
 895  902  
 896  903  static int
 897  904  troffint(char *bp, int n)
 898  905  {
 899  906          int k;
 900  907  
 901  908          i = 0;
 902  909          for (k = 0; k < 6; k++) {
 903  910                  if (lookup(troff) == 0)
 904  911                          return (0);
 905  912                  if (lookup(troff) == 0)
 906  913                          return (0);
 907  914                  while (i < n && bp[i] != '\n')
 908  915                          i++;
 909  916                  if (i++ >= n)
 910  917                          return (0);
 911  918          }
 912  919          return (1);
 913  920  }
 914  921  
 915  922  static void
 916  923  ar_coff_or_aout(int elffd)
 917  924  {
 918  925          Elf *elf;
 919  926  
 920  927          /*
 921  928           * Get the files elf descriptor and process it as an elf or
 922  929           * a.out (4.x) file.
 923  930           */
 924  931  
 925  932          elf = elf_begin(elffd, ELF_C_READ, (Elf *)0);
 926  933          switch (elf_kind(elf)) {
 927  934                  case ELF_K_AR :
 928  935                          (void) printf(gettext(", not a dynamic executable "
 929  936                              "or shared object"));
 930  937                          break;
 931  938                  case ELF_K_COFF:
 932  939                          (void) printf(gettext(", unsupported or unknown "
 933  940                              "file type"));
 934  941                          break;
 935  942                  default:
 936  943                          /*
 937  944                           * This is either an unknown file or an aout format
 938  945                           * At this time, we don't print dynamic/stripped
 939  946                           * info. on a.out or non-Elf binaries.
 940  947                           */
 941  948                          break;
 942  949          }
 943  950          (void) elf_end(elf);
 944  951  }
 945  952  
 946  953  
 947  954  static void
 948  955  print_elf_type(Elf_Info EI)
 949  956  {
 950  957          switch (EI.type) {
 951  958          case ET_NONE:
 952  959                  (void) printf(" %s", gettext("unknown type"));
 953  960                  break;
 954  961          case ET_REL:
 955  962                  (void) printf(" %s", gettext("relocatable"));
 956  963                  break;
 957  964          case ET_EXEC:
 958  965                  (void) printf(" %s", gettext("executable"));
 959  966                  break;
 960  967          case ET_DYN:
 961  968                  (void) printf(" %s", gettext("dynamic lib"));
 962  969                  break;
 963  970          default:
 964  971                  break;
 965  972          }
 966  973  }
 967  974  
 968  975  static void
 969  976  print_elf_machine(int machine)
 970  977  {
 971  978          /*
 972  979           * This table must be kept in sync with the EM_ constants
 973  980           * in /usr/include/sys/elf.h.
 974  981           */
 975  982          static const char *mach_str[EM_NUM] = {
 976  983                  "unknown machine",              /* 0 - EM_NONE */
 977  984                  "WE32100",                      /* 1 - EM_M32 */
 978  985                  "SPARC",                        /* 2 - EM_SPARC */
 979  986                  "80386",                        /* 3 - EM_386 */
 980  987                  "M68000",                       /* 4 - EM_68K */
 981  988                  "M88000",                       /* 5 - EM_88K */
 982  989                  "80486",                        /* 6 - EM_486 */
 983  990                  "i860",                         /* 7 - EM_860 */
 984  991                  "MIPS RS3000 Big-Endian",       /* 8 - EM_MIPS */
 985  992                  "S/370",                        /* 9 - EM_S370 */
 986  993                  "MIPS RS3000 Little-Endian",    /* 10 - EM_MIPS_RS3_LE */
 987  994                  "MIPS RS6000",                  /* 11 - EM_RS6000 */
 988  995                  NULL,                           /* 12 - EM_UNKNOWN12 */
 989  996                  NULL,                           /* 13 - EM_UNKNOWN13 */
 990  997                  NULL,                           /* 14 - EM_UNKNOWN14 */
 991  998                  "PA-RISC",                      /* 15 - EM_PA_RISC */
 992  999                  "nCUBE",                        /* 16 - EM_nCUBE */
 993 1000                  "VPP500",                       /* 17 - EM_VPP500 */
 994 1001                  "SPARC32PLUS",                  /* 18 - EM_SPARC32PLUS */
 995 1002                  "i960",                         /* 19 - EM_960 */
 996 1003                  "PowerPC",                      /* 20 - EM_PPC */
 997 1004                  "PowerPC64",                    /* 21 - EM_PPC64 */
 998 1005                  "S/390",                        /* 22 - EM_S390 */
 999 1006                  NULL,                           /* 23 - EM_UNKNOWN23 */
1000 1007                  NULL,                           /* 24 - EM_UNKNOWN24 */
1001 1008                  NULL,                           /* 25 - EM_UNKNOWN25 */
1002 1009                  NULL,                           /* 26 - EM_UNKNOWN26 */
1003 1010                  NULL,                           /* 27 - EM_UNKNOWN27 */
1004 1011                  NULL,                           /* 28 - EM_UNKNOWN28 */
1005 1012                  NULL,                           /* 29 - EM_UNKNOWN29 */
1006 1013                  NULL,                           /* 30 - EM_UNKNOWN30 */
1007 1014                  NULL,                           /* 31 - EM_UNKNOWN31 */
1008 1015                  NULL,                           /* 32 - EM_UNKNOWN32 */
1009 1016                  NULL,                           /* 33 - EM_UNKNOWN33 */
1010 1017                  NULL,                           /* 34 - EM_UNKNOWN34 */
1011 1018                  NULL,                           /* 35 - EM_UNKNOWN35 */
1012 1019                  "V800",                         /* 36 - EM_V800 */
1013 1020                  "FR20",                         /* 37 - EM_FR20 */
1014 1021                  "RH32",                         /* 38 - EM_RH32 */
1015 1022                  "RCE",                          /* 39 - EM_RCE */
1016 1023                  "ARM",                          /* 40 - EM_ARM */
1017 1024                  "Alpha",                        /* 41 - EM_ALPHA */
1018 1025                  "S/390",                        /* 42 - EM_SH */
1019 1026                  "SPARCV9",                      /* 43 - EM_SPARCV9 */
1020 1027                  "Tricore",                      /* 44 - EM_TRICORE */
1021 1028                  "ARC",                          /* 45 - EM_ARC */
1022 1029                  "H8/300",                       /* 46 - EM_H8_300 */
1023 1030                  "H8/300H",                      /* 47 - EM_H8_300H */
1024 1031                  "H8S",                          /* 48 - EM_H8S */
1025 1032                  "H8/500",                       /* 49 - EM_H8_500 */
1026 1033                  "IA64",                         /* 50 - EM_IA_64 */
1027 1034                  "MIPS-X",                       /* 51 - EM_MIPS_X */
1028 1035                  "Coldfire",                     /* 52 - EM_COLDFIRE */
1029 1036                  "M68HC12",                      /* 53 - EM_68HC12 */
1030 1037                  "MMA",                          /* 54 - EM_MMA */
1031 1038                  "PCP",                          /* 55 - EM_PCP */
1032 1039                  "nCPU",                         /* 56 - EM_NCPU */
1033 1040                  "NDR1",                         /* 57 - EM_NDR1 */
1034 1041                  "Starcore",                     /* 58 - EM_STARCORE */
1035 1042                  "ME16",                         /* 59 - EM_ME16 */
1036 1043                  "ST100",                        /* 60 - EM_ST100 */
1037 1044                  "TINYJ",                        /* 61 - EM_TINYJ */
1038 1045                  "AMD64",                        /* 62 - EM_AMD64 */
1039 1046                  "PDSP",                         /* 63 - EM_PDSP */
1040 1047                  NULL,                           /* 64 - EM_UNKNOWN64 */
1041 1048                  NULL,                           /* 65 - EM_UNKNOWN65 */
1042 1049                  "FX66",                         /* 66 - EM_FX66 */
1043 1050                  "ST9 PLUS",                     /* 67 - EM_ST9PLUS */
1044 1051                  "ST7",                          /* 68 - EM_ST7 */
1045 1052                  "68HC16",                       /* 69 - EM_68HC16 */
1046 1053                  "68HC11",                       /* 70 - EM_68HC11 */
1047 1054                  "68H08",                        /* 71 - EM_68HC08 */
1048 1055                  "68HC05",                       /* 72 - EM_68HC05 */
1049 1056                  "SVX",                          /* 73 - EM_SVX */
1050 1057                  "ST19",                         /* 74 - EM_ST19 */
1051 1058                  "VAX",                          /* 75 - EM_VAX */
1052 1059                  "CRIS",                         /* 76 - EM_CRIS */
1053 1060                  "Javelin",                      /* 77 - EM_JAVELIN */
1054 1061                  "Firepath",                     /* 78 - EM_FIREPATH */
1055 1062                  "ZSP",                          /* 79 - EM_ZSP */
1056 1063                  "MMIX",                         /* 80 - EM_MMIX */
1057 1064                  "HUANY",                        /* 81 - EM_HUANY */
1058 1065                  "Prism",                        /* 82 - EM_PRISM */
1059 1066                  "AVR",                          /* 83 - EM_AVR */
1060 1067                  "FR30",                         /* 84 - EM_FR30 */
1061 1068                  "D10V",                         /* 85 - EM_D10V */
1062 1069                  "D30V",                         /* 86 - EM_D30V */
1063 1070                  "V850",                         /* 87 - EM_V850 */
1064 1071                  "M32R",                         /* 88 - EM_M32R */
1065 1072                  "MN10300",                      /* 89 - EM_MN10300 */
1066 1073                  "MN10200",                      /* 90 - EM_MN10200 */
1067 1074                  "picoJava",                     /* 91 - EM_PJ */
1068 1075                  "OpenRISC",                     /* 92 - EM_OPENRISC */
1069 1076                  "Tangent-A5",                   /* 93 - EM_ARC_A5 */
1070 1077                  "Xtensa"                        /* 94 - EM_XTENSA */
1071 1078          };
1072 1079          /* If new machine is added, refuse to compile until we're updated */
1073 1080  #if EM_NUM != 95
1074 1081  #error "Number of known ELF machine constants has changed"
1075 1082  #endif
1076 1083  
1077 1084          const char *str;
1078 1085  
1079 1086          if ((machine < EM_NONE) || (machine >= EM_NUM))
1080 1087                  machine = EM_NONE;
1081 1088  
1082 1089          str = mach_str[machine];
1083 1090          if (str)
1084 1091                  (void) printf(" %s", str);
1085 1092  }
1086 1093  
1087 1094  static void
1088 1095  print_elf_datatype(int datatype)
1089 1096  {
1090 1097          switch (datatype) {
1091 1098          case ELFDATA2LSB:
1092 1099                  (void) printf(" LSB");
1093 1100                  break;
1094 1101          case ELFDATA2MSB:
1095 1102                  (void) printf(" MSB");
1096 1103                  break;
1097 1104          default:
1098 1105                  break;
1099 1106          }
1100 1107  }
1101 1108  
1102 1109  static void
1103 1110  print_elf_class(int class)
1104 1111  {
1105 1112          switch (class) {
1106 1113          case ELFCLASS32:
1107 1114                  (void) printf(" %s", gettext("32-bit"));
1108 1115                  break;
1109 1116          case ELFCLASS64:
1110 1117                  (void) printf(" %s", gettext("64-bit"));
1111 1118                  break;
1112 1119          default:
1113 1120                  break;
1114 1121          }
1115 1122  }
1116 1123  
1117 1124  static void
1118 1125  print_elf_flags(Elf_Info EI)
1119 1126  {
1120 1127          unsigned int flags;
1121 1128  
1122 1129          flags = EI.flags;
1123 1130          switch (EI.machine) {
1124 1131          case EM_SPARCV9:
1125 1132                  if (flags & EF_SPARC_EXT_MASK) {
1126 1133                          if (flags & EF_SPARC_SUN_US3) {
1127 1134                                  (void) printf("%s", gettext(
1128 1135                                      ", UltraSPARC3 Extensions Required"));
1129 1136                          } else if (flags & EF_SPARC_SUN_US1) {
1130 1137                                  (void) printf("%s", gettext(
1131 1138                                      ", UltraSPARC1 Extensions Required"));
1132 1139                          }
1133 1140                          if (flags & EF_SPARC_HAL_R1)
1134 1141                                  (void) printf("%s", gettext(
1135 1142                                      ", HaL R1 Extensions Required"));
1136 1143                  }
1137 1144                  break;
1138 1145          case EM_SPARC32PLUS:
1139 1146                  if (flags & EF_SPARC_32PLUS)
1140 1147                          (void) printf("%s", gettext(", V8+ Required"));
1141 1148                  if (flags & EF_SPARC_SUN_US3) {
1142 1149                          (void) printf("%s",
1143 1150                              gettext(", UltraSPARC3 Extensions Required"));
1144 1151                  } else if (flags & EF_SPARC_SUN_US1) {
1145 1152                          (void) printf("%s",
1146 1153                              gettext(", UltraSPARC1 Extensions Required"));
1147 1154                  }
1148 1155                  if (flags & EF_SPARC_HAL_R1)
1149 1156                          (void) printf("%s",
1150 1157                              gettext(", HaL R1 Extensions Required"));
1151 1158                  break;
1152 1159          default:
1153 1160                  break;
1154 1161          }
1155 1162  }
1156 1163  
1157 1164  /*
1158 1165   * check_ident: checks the ident field of the presumeably
1159 1166   *              elf file. If check fails, this is not an
1160 1167   *              elf file.
1161 1168   */
1162 1169  static int
1163 1170  check_ident(unsigned char *ident, int fd)
1164 1171  {
1165 1172          int class;
1166 1173          if (pread64(fd, ident, EI_NIDENT, 0) != EI_NIDENT)
1167 1174                  return (ELF_READ_FAIL);
1168 1175          class = ident[EI_CLASS];
1169 1176          if (class != ELFCLASS32 && class != ELFCLASS64)
1170 1177                  return (ELF_READ_FAIL);
1171 1178          if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
1172 1179              ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3)
1173 1180                  return (ELF_READ_FAIL);
1174 1181  
1175 1182          return (ELF_READ_OKAY);
1176 1183  }
1177 1184  
1178 1185  static int
1179 1186  elf_check(char *file)
1180 1187  {
1181 1188          Elf_Info EInfo;
1182 1189          int class, version, format;
1183 1190          unsigned char ident[EI_NIDENT];
1184 1191  
1185 1192          (void) memset(&EInfo, 0, sizeof (Elf_Info));
1186 1193          EInfo.file = file;
1187 1194  
1188 1195          /*
1189 1196           * Verify information in file indentifier.
1190 1197           * Return quietly if not elf; Different type of file.
1191 1198           */
1192 1199          if (check_ident(ident, elffd) == ELF_READ_FAIL)
1193 1200                  return (1);
1194 1201  
1195 1202          /*
1196 1203           * Read the elf headers for processing and get the
1197 1204           * get the needed information in Elf_Info struct.
1198 1205           */
1199 1206          class = ident[EI_CLASS];
1200 1207          if (class == ELFCLASS32) {
1201 1208                  if (elf_read32(elffd, &EInfo) == ELF_READ_FAIL) {
1202 1209                          (void) fprintf(stderr, gettext("%s: %s: can't "
1203 1210                              "read ELF header\n"), File, file);
1204 1211                          return (1);
1205 1212                  }
1206 1213          } else if (class == ELFCLASS64) {
1207 1214                  if (elf_read64(elffd, &EInfo) == ELF_READ_FAIL) {
1208 1215                          (void) fprintf(stderr, gettext("%s: %s: can't "
1209 1216                              "read ELF header\n"), File, file);
1210 1217                          return (1);
1211 1218                  }
1212 1219          } else {
1213 1220                  /* something wrong */
1214 1221                  return (1);
1215 1222          }
1216 1223  
1217 1224          /* version not in ident then 1 */
1218 1225          version = ident[EI_VERSION] ? ident[EI_VERSION] : 1;
1219 1226  
1220 1227          format = ident[EI_DATA];
1221 1228          (void) printf("%s", gettext("ELF"));
1222 1229          print_elf_class(class);
1223 1230          print_elf_datatype(format);
1224 1231          print_elf_type(EInfo);
1225 1232  
1226 1233          if (EInfo.core_type != EC_NOTCORE) {
1227 1234                  /* Print what kind of core is this */
1228 1235                  if (EInfo.core_type == EC_OLDCORE)
1229 1236                          (void) printf(" %s", gettext("pre-2.6 core file"));
1230 1237                  else
1231 1238                          (void) printf(" %s", gettext("core file"));
1232 1239          }
1233 1240  
1234 1241          /* Print machine info */
1235 1242          print_elf_machine(EInfo.machine);
1236 1243  
1237 1244          /* Print Version */
1238 1245          if (version == 1)
1239 1246                  (void) printf(" %s %d", gettext("Version"), version);
1240 1247  
1241 1248          /* Print Flags */
1242 1249          print_elf_flags(EInfo);
1243 1250  
1244 1251          /* Last bit, if it is a core */
1245 1252          if (EInfo.core_type != EC_NOTCORE) {
1246 1253                  /* Print the program name that dumped this core */
1247 1254                  (void) printf(gettext(", from '%s'"), EInfo.fname);
1248 1255                  return (0);
1249 1256          }
1250 1257  
1251 1258          /* Print Capabilities */
1252 1259          if (EInfo.cap_str[0] != '\0')
1253 1260                  (void) printf(" [%s]", EInfo.cap_str);
1254 1261  
1255 1262          if ((EInfo.type != ET_EXEC) && (EInfo.type != ET_DYN))
1256 1263                  return (0);
1257 1264  
1258 1265          /* Print if it is dynamically linked */
1259 1266          if (EInfo.dynamic)
1260 1267                  (void) printf(gettext(", dynamically linked"));
1261 1268          else
1262 1269                  (void) printf(gettext(", statically linked"));
1263 1270  
1264 1271          /* Printf it it is stripped */
1265 1272          if (EInfo.stripped & E_SYMTAB) {
1266 1273                  (void) printf(gettext(", not stripped"));
1267 1274                  if (!(EInfo.stripped & E_DBGINF)) {
1268 1275                          (void) printf(gettext(
1269 1276                              ", no debugging information available"));
1270 1277                  }
1271 1278          } else {
1272 1279                  (void) printf(gettext(", stripped"));
1273 1280          }
1274 1281  
1275 1282          return (0);
1276 1283  }
1277 1284  
1278 1285  /*
1279 1286   * is_rtld_config - If file is a runtime linker config file, prints
1280 1287   * the description and returns True (1). Otherwise, silently returns
1281 1288   * False (0).
1282 1289   */
1283 1290  int
1284 1291  is_rtld_config(void)
1285 1292  {
1286 1293          Rtc_id *id;
1287 1294  
1288 1295          if ((fbsz >= sizeof (*id)) && RTC_ID_TEST(fbuf)) {
1289 1296                  (void) printf(gettext("Runtime Linking Configuration"));
1290 1297                  id = (Rtc_id *) fbuf;
1291 1298                  print_elf_class(id->id_class);
1292 1299                  print_elf_datatype(id->id_data);
1293 1300                  print_elf_machine(id->id_machine);
1294 1301                  (void) printf("\n");
1295 1302                  return (1);
1296 1303          }
1297 1304  
1298 1305          return (0);
1299 1306  }
1300 1307  
1301 1308  /*
1302 1309   * lookup -
1303 1310   * Attempts to match one of the strings from a list, 'tab',
1304 1311   * with what is in the file, starting at the current index position 'i'.
1305 1312   * Looks past any initial whitespace and expects whitespace or other
1306 1313   * delimiting characters to follow the matched string.
1307 1314   * A match identifies the file as being 'assembler', 'fortran', 'c', etc.
1308 1315   * Returns 1 for a successful match, 0 otherwise.
1309 1316   */
1310 1317  static int
1311 1318  lookup(char **tab)
1312 1319  {
1313 1320          register char   r;
1314 1321          register int    k, j, l;
1315 1322  
1316 1323          while (fbuf[i] == ' ' || fbuf[i] == '\t' || fbuf[i] == '\n')
1317 1324                  i++;
1318 1325          for (j = 0; tab[j] != 0; j++) {
1319 1326                  l = 0;
1320 1327                  for (k = i; ((r = tab[j][l++]) == fbuf[k] && r != '\0'); k++)
1321 1328                          ;
1322 1329                  if (r == '\0')
1323 1330                          if (fbuf[k] == ' ' || fbuf[k] == '\n' ||
1324 1331                              fbuf[k] == '\t' || fbuf[k] == '{' ||
1325 1332                              fbuf[k] == '/') {
1326 1333                                  i = k;
1327 1334                                  return (1);
1328 1335                          }
1329 1336          }
1330 1337          return (0);
1331 1338  }
1332 1339  
1333 1340  /*
1334 1341   * ccom -
1335 1342   * Increments the current index 'i' into the file buffer 'fbuf' past any
1336 1343   * whitespace lines and C-style comments found, starting at the current
1337 1344   * position of 'i'.  Returns 1 as long as we don't increment i past the
1338 1345   * size of fbuf (fbsz).  Otherwise, returns 0.
1339 1346   */
1340 1347  
1341 1348  static int
1342 1349  ccom(void)
1343 1350  {
1344 1351          register char   cc;
1345 1352          int             len;
1346 1353  
1347 1354          while ((cc = fbuf[i]) == ' ' || cc == '\t' || cc == '\n')
1348 1355                  if (i++ >= fbsz)
1349 1356                          return (0);
1350 1357          if (fbuf[i] == '/' && fbuf[i+1] == '*') {
1351 1358                  i += 2;
1352 1359                  while (fbuf[i] != '*' || fbuf[i+1] != '/') {
1353 1360                          if (fbuf[i] == '\\')
1354 1361                                  i++;
1355 1362                          if ((len = mblen(&fbuf[i], MB_CUR_MAX)) <= 0)
1356 1363                                  len = 1;
1357 1364                          i += len;
1358 1365                          if (i >= fbsz)
1359 1366                                  return (0);
1360 1367                  }
1361 1368                  if ((i += 2) >= fbsz)
1362 1369                          return (0);
1363 1370          }
1364 1371          if (fbuf[i] == '\n')
1365 1372                  if (ccom() == 0)
1366 1373                          return (0);
1367 1374          return (1);
1368 1375  }
1369 1376  
1370 1377  /*
1371 1378   * ascom -
1372 1379   * Increments the current index 'i' into the file buffer 'fbuf' past
1373 1380   * consecutive assembler program comment lines starting with ASCOMCHAR,
1374 1381   * starting at the current position of 'i'.
1375 1382   * Returns 1 as long as we don't increment i past the
1376 1383   * size of fbuf (fbsz).  Otherwise returns 0.
1377 1384   */
1378 1385  
1379 1386  static int
1380 1387  ascom(void)
1381 1388  {
1382 1389          while (fbuf[i] == ASCOMCHAR) {
1383 1390                  i++;
1384 1391                  while (fbuf[i++] != '\n')
1385 1392                          if (i >= fbsz)
1386 1393                                  return (0);
1387 1394                  while (fbuf[i] == '\n')
1388 1395                          if (i++ >= fbsz)
1389 1396                                  return (0);
1390 1397          }
1391 1398          return (1);
1392 1399  }
1393 1400  
1394 1401  static int
1395 1402  sccs(void)
1396 1403  {                               /* look for "1hddddd" where d is a digit */
1397 1404          register int j;
1398 1405  
1399 1406          if (fbuf[0] == 1 && fbuf[1] == 'h') {
1400 1407                  for (j = 2; j <= 6; j++) {
1401 1408                          if (isdigit(fbuf[j]))
1402 1409                                  continue;
1403 1410                          else
1404 1411                                  return (0);
1405 1412                  }
1406 1413          } else {
1407 1414                  return (0);
1408 1415          }
1409 1416          return (1);
1410 1417  }
1411 1418  
1412 1419  static int
1413 1420  english(char *bp, int n)
1414 1421  {
1415 1422  #define NASC 128                /* number of ascii char ?? */
1416 1423          register int    j, vow, freq, rare, len;
1417 1424          register int    badpun = 0, punct = 0;
1418 1425          int     ct[NASC];
1419 1426  
1420 1427          if (n < 50)
1421 1428                  return (0); /* no point in statistics on squibs */
1422 1429          for (j = 0; j < NASC; j++)
1423 1430                  ct[j] = 0;
1424 1431          for (j = 0; j < n; j += len) {
1425 1432                  if ((unsigned char)bp[j] < NASC)
1426 1433                          ct[bp[j]|040]++;
1427 1434                  switch (bp[j]) {
1428 1435                  case '.':
1429 1436                  case ',':
1430 1437                  case ')':
1431 1438                  case '%':
1432 1439                  case ';':
1433 1440                  case ':':
1434 1441                  case '?':
1435 1442                          punct++;
1436 1443                          if (j < n-1 && bp[j+1] != ' ' && bp[j+1] != '\n')
1437 1444                                  badpun++;
1438 1445                  }
1439 1446                  if ((len = mblen(&bp[j], MB_CUR_MAX)) <= 0)
1440 1447                          len = 1;
1441 1448          }
1442 1449          if (badpun*5 > punct)
1443 1450                  return (0);
1444 1451          vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u'];
1445 1452          freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n'];
1446 1453          rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z'];
1447 1454          if (2*ct[';'] > ct['e'])
1448 1455                  return (0);
1449 1456          if ((ct['>'] + ct['<'] + ct['/']) > ct['e'])
1450 1457                  return (0);     /* shell file test */
1451 1458          return (vow * 5 >= n - ct[' '] && freq >= 10 * rare);
1452 1459  }
1453 1460  
1454 1461  
1455 1462  static int
1456 1463  shellscript(char buf[], struct stat64 *sb)
1457 1464  {
1458 1465          char *tp, *cp, *xp, *up, *gp;
1459 1466  
1460 1467          cp = strchr(buf, '\n');
1461 1468          if (cp == NULL || cp - fbuf > fbsz)
1462 1469                  return (0);
1463 1470          for (tp = buf; tp != cp && isspace((unsigned char)*tp); tp++)
1464 1471                  if (!isascii(*tp))
1465 1472                          return (0);
1466 1473          for (xp = tp; tp != cp && !isspace((unsigned char)*tp); tp++)
1467 1474                  if (!isascii(*tp))
1468 1475                          return (0);
1469 1476          if (tp == xp)
1470 1477                  return (0);
1471 1478          if (sb->st_mode & S_ISUID)
1472 1479                  up = gettext("set-uid ");
1473 1480          else
1474 1481                  up = "";
1475 1482  
1476 1483          if (sb->st_mode & S_ISGID)
1477 1484                  gp = gettext("set-gid ");
1478 1485          else
1479 1486                  gp = "";
1480 1487  
1481 1488          if (strncmp(xp, "/bin/sh", tp - xp) == 0)
1482 1489                  xp = gettext("shell");
1483 1490          else if (strncmp(xp, "/bin/csh", tp - xp) == 0)
1484 1491                  xp = gettext("c-shell");
1485 1492          else if (strncmp(xp, "/usr/sbin/dtrace", tp - xp) == 0)
1486 1493                  xp = gettext("DTrace");
1487 1494          else
1488 1495                  *tp = '\0';
1489 1496          /*
1490 1497           * TRANSLATION_NOTE
1491 1498           * This message is printed by file command for shell scripts.
1492 1499           * The first %s is for the translation for "set-uid " (if the script
1493 1500           *   has the set-uid bit set), or is for an empty string (if the
1494 1501           *   script does not have the set-uid bit set).
1495 1502           * Similarly, the second %s is for the translation for "set-gid ",
1496 1503           *   or is for an empty string.
1497 1504           * The third %s is for the translation for either: "shell", "c-shell",
1498 1505           *   or "DTrace", or is for the pathname of the program the script
1499 1506           *   executes.
1500 1507           */
1501 1508          (void) printf(gettext("%s%sexecutable %s script\n"), up, gp, xp);
1502 1509          return (1);
1503 1510  }
1504 1511  
1505 1512  static int
1506 1513  get_door_target(char *file, char *buf, size_t bufsize)
1507 1514  {
1508 1515          int fd;
1509 1516          door_info_t di;
1510 1517          psinfo_t psinfo;
1511 1518  
1512 1519          if ((fd = open64(file, O_RDONLY)) < 0 ||
1513 1520              door_info(fd, &di) != 0) {
1514 1521                  if (fd >= 0)
1515 1522                          (void) close(fd);
1516 1523                  return (-1);
1517 1524          }
1518 1525          (void) close(fd);
1519 1526  
1520 1527          (void) sprintf(buf, "/proc/%ld/psinfo", di.di_target);
1521 1528          if ((fd = open64(buf, O_RDONLY)) < 0 ||
1522 1529              read(fd, &psinfo, sizeof (psinfo)) != sizeof (psinfo)) {
1523 1530                  if (fd >= 0)
1524 1531                          (void) close(fd);
1525 1532                  return (-1);
1526 1533          }
1527 1534          (void) close(fd);
1528 1535  
1529 1536          (void) snprintf(buf, bufsize, "%s[%ld]", psinfo.pr_fname, di.di_target);
1530 1537          return (0);
1531 1538  }
1532 1539  
1533 1540  /*
1534 1541   * ZIP file header information
1535 1542   */
1536 1543  #define SIGSIZ          4
1537 1544  #define LOCSIG          "PK\003\004"
1538 1545  #define LOCHDRSIZ       30
1539 1546  
1540 1547  #define CH(b, n)        (((unsigned char *)(b))[n])
1541 1548  #define SH(b, n)        (CH(b, n) | (CH(b, n+1) << 8))
1542 1549  #define LG(b, n)        (SH(b, n) | (SH(b, n+2) << 16))
1543 1550  
1544 1551  #define LOCNAM(b)       (SH(b, 26))     /* filename size */
1545 1552  #define LOCEXT(b)       (SH(b, 28))     /* extra field size */
1546 1553  
1547 1554  #define XFHSIZ          4               /* header id, data size */
1548 1555  #define XFHID(b)        (SH(b, 0))      /* extract field header id */
1549 1556  #define XFDATASIZ(b)    (SH(b, 2))      /* extract field data size */
1550 1557  #define XFJAVASIG       0xcafe          /* java executables */
1551 1558  
1552 1559  static int
1553 1560  zipfile(char *fbuf, int fd)
1554 1561  {
1555 1562          off_t xoff, xoff_end;
1556 1563  
1557 1564          if (strncmp(fbuf, LOCSIG, SIGSIZ) != 0)
1558 1565                  return (0);
1559 1566  
1560 1567          xoff = LOCHDRSIZ + LOCNAM(fbuf);
1561 1568          xoff_end = xoff + LOCEXT(fbuf);
1562 1569  
1563 1570          while (xoff < xoff_end) {
1564 1571                  char xfhdr[XFHSIZ];
1565 1572  
1566 1573                  if (pread(fd, xfhdr, XFHSIZ, xoff) != XFHSIZ)
1567 1574                          break;
1568 1575  
1569 1576                  if (XFHID(xfhdr) == XFJAVASIG) {
1570 1577                          (void) printf("%s\n", gettext("java archive file"));
1571 1578                          return (1);
1572 1579                  }
1573 1580                  xoff += sizeof (xfhdr) + XFDATASIZ(xfhdr);
1574 1581          }
1575 1582  
1576 1583          /*
1577 1584           * We could just print "ZIP archive" here.
1578 1585           *
1579 1586           * However, customers may be using their own entries in
1580 1587           * /etc/magic to distinguish one kind of ZIP file from another, so
1581 1588           * let's defer the printing of "ZIP archive" to there.
1582 1589           */
1583 1590          return (0);
1584 1591  }
1585 1592  
1586 1593  static int
1587 1594  is_crash_dump(const char *buf, int fd)
1588 1595  {
1589 1596          /* LINTED: pointer cast may result in improper alignment */
1590 1597          const dumphdr_t *dhp = (const dumphdr_t *)buf;
1591 1598  
1592 1599          /*
1593 1600           * The current DUMP_MAGIC string covers Solaris 7 and later releases.
1594 1601           * The utsname struct is only present in dumphdr_t's with dump_version
1595 1602           * greater than or equal to 9.
1596 1603           */
1597 1604          if (dhp->dump_magic == DUMP_MAGIC) {
1598 1605                  print_dumphdr(fd, dhp, return_uint32, NATIVE_ISA);
1599 1606  
1600 1607          } else if (dhp->dump_magic == swap_uint32(DUMP_MAGIC)) {
1601 1608                  print_dumphdr(fd, dhp, swap_uint32, OTHER_ISA);
1602 1609  
1603 1610          } else if (dhp->dump_magic == OLD_DUMP_MAGIC ||
1604 1611              dhp->dump_magic == swap_uint32(OLD_DUMP_MAGIC)) {
1605 1612                  char *isa = (dhp->dump_magic == OLD_DUMP_MAGIC ?
1606 1613                      NATIVE_ISA : OTHER_ISA);
1607 1614                  (void) printf(gettext("SunOS 32-bit %s crash dump\n"), isa);
1608 1615  
1609 1616          } else {
1610 1617                  return (0);
1611 1618          }
1612 1619  
1613 1620          return (1);
1614 1621  }
1615 1622  
1616 1623  static void
1617 1624  print_dumphdr(const int fd, const dumphdr_t *dhp, uint32_t (*swap)(uint32_t),
1618 1625      const char *isa)
1619 1626  {
1620 1627          dumphdr_t dh;
1621 1628  
1622 1629          /*
1623 1630           * A dumphdr_t is bigger than FBSZ, so we have to manually read the
1624 1631           * rest of it.
1625 1632           */
1626 1633          if (swap(dhp->dump_version) > 8 && pread(fd, &dh, sizeof (dumphdr_t),
1627 1634              (off_t)0) == sizeof (dumphdr_t)) {
1628 1635                  const char *c = swap(dh.dump_flags) & DF_COMPRESSED ?
1629 1636                      "compressed " : "";
1630 1637                  const char *l = swap(dh.dump_flags) & DF_LIVE ?
1631 1638                      "live" : "crash";
1632 1639  
1633 1640                  (void) printf(gettext(
1634 1641                      "%s %s %s %u-bit %s %s%s dump from '%s'\n"),
1635 1642                      dh.dump_utsname.sysname, dh.dump_utsname.release,
1636 1643                      dh.dump_utsname.version, swap(dh.dump_wordsize), isa,
1637 1644                      c, l, dh.dump_utsname.nodename);
  
    | 
      ↓ open down ↓ | 
    1215 lines elided | 
    
      ↑ open up ↑ | 
  
1638 1645          } else {
1639 1646                  (void) printf(gettext("SunOS %u-bit %s crash dump\n"),
1640 1647                      swap(dhp->dump_wordsize), isa);
1641 1648          }
1642 1649  }
1643 1650  
1644 1651  static void
1645 1652  usage(void)
1646 1653  {
1647 1654          (void) fprintf(stderr, gettext(
1648      -            "usage: file [-dh] [-M mfile] [-m mfile] [-f ffile] file ...\n"
1649      -            "       file [-dh] [-M mfile] [-m mfile] -f ffile\n"
1650      -            "       file -i [-h] [-f ffile] file ...\n"
1651      -            "       file -i [-h] -f ffile\n"
     1655 +            "usage: file [-bdh] [-M mfile] [-m mfile] [-f ffile] file ...\n"
     1656 +            "       file [-bdh] [-M mfile] [-m mfile] -f ffile\n"
     1657 +            "       file -i [-bh] [-f ffile] file ...\n"
     1658 +            "       file -i [-bh] -f ffile\n"
1652 1659              "       file -c [-d] [-M mfile] [-m mfile]\n"));
1653 1660          exit(2);
1654 1661  }
1655 1662  
1656 1663  static uint32_t
1657 1664  swap_uint32(uint32_t in)
1658 1665  {
1659 1666          uint32_t out;
1660 1667  
1661 1668          out = (in & 0x000000ff) << 24;
1662 1669          out |= (in & 0x0000ff00) << 8; /* >> 8 << 16 */
1663 1670          out |= (in & 0x00ff0000) >> 8; /* >> 16 << 8 */
1664 1671          out |= (in & 0xff000000) >> 24;
1665 1672  
1666 1673          return (out);
1667 1674  }
1668 1675  
1669 1676  static uint32_t
1670 1677  return_uint32(uint32_t in)
1671 1678  {
1672 1679          return (in);
1673 1680  }
1674 1681  
1675 1682  /*
1676 1683   * Check if str is in the string list str_list.
1677 1684   */
1678 1685  int
1679 1686  is_in_list(char *str)
1680 1687  {
1681 1688          int i;
1682 1689  
1683 1690          /*
1684 1691           * Only need to compare the strlen(str_list[i]) bytes.
1685 1692           * That way .stab will match on .stab* sections, and
1686 1693           * .debug will match on .debug* sections.
1687 1694           */
1688 1695          for (i = 0; debug_sections[i] != NULL; i++) {
1689 1696                  if (strncmp(debug_sections[i], str,
1690 1697                      strlen(debug_sections[i])) == 0) {
1691 1698                          return (1);
1692 1699                  }
1693 1700          }
1694 1701          return (0);
1695 1702  }
1696 1703  
1697 1704  /*
1698 1705   * default_magic -
1699 1706   *      allocate space for and create the default magic file
1700 1707   *      name string.
1701 1708   */
1702 1709  
1703 1710  static void
1704 1711  default_magic(void)
1705 1712  {
1706 1713          const char *msg_locale = setlocale(LC_MESSAGES, NULL);
1707 1714          struct stat     statbuf;
1708 1715  
1709 1716          if ((dfile = malloc(strlen(msg_locale) + 35)) == NULL) {
1710 1717                  int err = errno;
1711 1718                  (void) fprintf(stderr, gettext("%s: malloc failed: %s\n"),
1712 1719                      File, strerror(err));
1713 1720                  exit(2);
1714 1721          }
1715 1722          (void) snprintf(dfile, strlen(msg_locale) + 35,
1716 1723              "/usr/lib/locale/%s/LC_MESSAGES/magic", msg_locale);
1717 1724          if (stat(dfile, &statbuf) != 0) {
1718 1725                  (void) strcpy(dfile, "/etc/magic");
1719 1726          }
1720 1727  }
1721 1728  
1722 1729  /*
1723 1730   * add_to_mlist -
1724 1731   *      Add the given magic_file filename string to the list of magic
1725 1732   *      files (mlist).  This list of files will later be examined, and
1726 1733   *      each magic file's entries will be added in order to
1727 1734   *      the mtab table.
1728 1735   *
1729 1736   *      The first flag is set to 1 to add to the first list, mlist1.
1730 1737   *      The first flag is set to 0 to add to the second list, mlist2.
1731 1738   */
1732 1739  
1733 1740  static void
1734 1741  add_to_mlist(char *magic_file, int first)
1735 1742  {
1736 1743          char    **mlist;        /* ordered list of magic files */
1737 1744          size_t  mlist_sz;       /* number of pointers allocated  for mlist */
1738 1745          char    **mlistp;       /* next entry in mlist */
1739 1746          size_t mlistp_off;
1740 1747  
1741 1748          if (first) {
1742 1749                  mlist = mlist1;
1743 1750                  mlist_sz = mlist1_sz;
1744 1751                  mlistp = mlist1p;
1745 1752          } else {
1746 1753                  mlist = mlist2;
1747 1754                  mlist_sz = mlist2_sz;
1748 1755                  mlistp = mlist2p;
1749 1756          }
1750 1757  
1751 1758          if (mlist == NULL) {    /* initial mlist allocation */
1752 1759                  if ((mlist = calloc(MLIST_SZ, sizeof (char *))) == NULL) {
1753 1760                          int err = errno;
1754 1761                          (void) fprintf(stderr, gettext("%s: malloc "
1755 1762                              "failed: %s\n"), File, strerror(err));
1756 1763                          exit(2);
1757 1764                  }
1758 1765                  mlist_sz = MLIST_SZ;
1759 1766                  mlistp = mlist;
1760 1767          }
1761 1768          if ((mlistp - mlist) >= mlist_sz) {
1762 1769                  mlistp_off = mlistp - mlist;
1763 1770                  mlist_sz *= 2;
1764 1771                  if ((mlist = realloc(mlist,
1765 1772                      mlist_sz * sizeof (char *))) == NULL) {
1766 1773                          int err = errno;
1767 1774                          (void) fprintf(stderr, gettext("%s: malloc "
1768 1775                              "failed: %s\n"), File, strerror(err));
1769 1776                          exit(2);
1770 1777                  }
1771 1778                  mlistp = mlist + mlistp_off;
1772 1779          }
1773 1780          /*
1774 1781           * now allocate memory for and copy the
1775 1782           * magic file name string
1776 1783           */
1777 1784          if ((*mlistp = malloc(strlen(magic_file) + 1)) == NULL) {
1778 1785                  int err = errno;
1779 1786                  (void) fprintf(stderr, gettext("%s: malloc failed: %s\n"),
1780 1787                      File, strerror(err));
1781 1788                  exit(2);
1782 1789          }
1783 1790          (void) strlcpy(*mlistp, magic_file, strlen(magic_file) + 1);
1784 1791          mlistp++;
1785 1792  
1786 1793          if (first) {
1787 1794                  mlist1 = mlist;
1788 1795                  mlist1_sz = mlist_sz;
1789 1796                  mlist1p = mlistp;
1790 1797          } else {
1791 1798                  mlist2 = mlist;
1792 1799                  mlist2_sz = mlist_sz;
1793 1800                  mlist2p = mlistp;
1794 1801          }
1795 1802  }
1796 1803  
1797 1804  static void
1798 1805  fd_cleanup(void)
1799 1806  {
1800 1807          if (ifd != -1) {
1801 1808                  (void) close(ifd);
1802 1809                  ifd = -1;
1803 1810          }
1804 1811          if (elffd != -1) {
1805 1812                  (void) close(elffd);
1806 1813                  elffd = -1;
1807 1814          }
1808 1815  }
  
    | 
      ↓ open down ↓ | 
    147 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX