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 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #include <stdio.h>
  29 #include <fcntl.h>
  30 #include <strings.h>
  31 #include <ctype.h>
  32 #include <stdlib.h>
  33 
  34 #include "list.h"
  35 #include "proto_list.h"
  36 
  37 #define FS      " \t\n"
  38 
  39 static void
  40 error(const char *msg, int lc)
  41 {
  42         (void) fprintf(stderr, "warning: line %d - %s\n", lc, msg);
  43 }
  44 
  45 /*
  46  * int is_num()
  47  *
  48  * returns 1 if the string is entirely numeric - if not it returns 0
  49  *
  50  */
  51 static int
  52 is_num(const char *str)
  53 {
  54         int i;
  55         int len = strlen(str);
  56 
  57         if (len < 1)
  58                 return (0);
  59 
  60         for (i = 0; i < len; i++)
  61                 if (!isdigit(str[i]))
  62                         return (0);
  63         return (1);
  64 }
  65 
  66 /*
  67  * void check_line()
  68  *
  69  * try and do some sanity/syntax checking against the line just
  70  * read in - print warning messages as errors are encountered.
  71  *
  72  * these are simple checks, but then they catch the simple errors-:)
  73  *
  74  */
  75 static void
  76 check_line(char *v[], int lc)
  77 {
  78         if ((!v[NAME]) || ((int)strlen(v[NAME]) < 1))
  79                 error("bad name", lc);
  80 
  81         if ((!v[SRC]) || ((int)strlen(v[SRC])) < 1)
  82                 error("bad source/symbolic line", lc);
  83 
  84         if ((!v[PERM]) || ((int)strlen(v[PERM]) < 3) || (!is_num(v[PERM])))
  85                 error("bad permissions", lc);
  86 
  87         if ((!v[OWNR]) || ((int)strlen(v[OWNR]) < 2))
  88                 error("bad owner", lc);
  89 
  90         if ((!v[GRP]) || ((int)strlen(v[GRP]) < 2))
  91                 error("bad group", lc);
  92 
  93         if ((!v[INO]) || (!is_num(v[INO])))
  94                 error("bad i-node", lc);
  95 
  96         if ((!v[LCNT]) || (!is_num(v[LCNT])))
  97                 error("bad link-count", lc);
  98 
  99         if ((!v[CODE]) || ((*v[CODE] != 'f') && (*v[CODE] != 'c') &&
 100             (*v[CODE] != 'd') && (*v[CODE] != 'b') &&
 101             (*v[CODE] != 'v') && (*v[CODE] != 'e') &&
 102             (*v[CODE] != 's')) || ((int)strlen(v[CODE]) > 1))
 103                 error("bad type", lc);
 104 
 105         if ((!v[MAJOR]) || ((!is_num(v[MAJOR])) && (*v[MAJOR] != '-')))
 106                 error("bad major number", lc);
 107 
 108         if ((!v[MINOR]) || ((!is_num(v[MINOR])) && (*v[MINOR] != '-')))
 109                 error("bad minor number", lc);
 110 }
 111 
 112 static char **
 113 get_line(FILE *fp, char *v[])
 114 {
 115         char    *rc;
 116         char    *p;
 117         int     len;
 118         int     cont = 1;
 119         static char     buf[BUFSIZ];
 120         static int      line_count = 0;
 121 
 122         p = buf;
 123         p[0] = '\0';
 124 
 125         do {
 126                 rc = fgets(p, BUFSIZ, fp);
 127                 line_count ++;
 128                 /*
 129                  * check for continuation marks at the end of the
 130                  * line - if it exists then append the next line at the
 131                  * end of this one.
 132                  */
 133                 if (buf[0] == '#') {
 134                         /*
 135                          * skip comments.
 136                          */
 137                         continue;
 138                 } else if ((rc != NULL) && ((len = strlen(p)) > 1) &&
 139                     (p[len - 2] == '\\')) {
 140                         /*
 141                          * check for continuation marks at the end of the
 142                          * line - if it exists then append the next line at the
 143                          * end of this one.
 144                          */
 145                         p += len - 2;
 146                 } else
 147                         cont = 0;
 148         } while (cont);
 149 
 150         if (rc == NULL)
 151                 return (NULL);
 152 
 153         /*
 154          * breakup the line into the various fields.
 155          */
 156         v[PROTOS] = index(buf, ';');
 157         if (v[PROTOS])
 158                 *v[PROTOS]++ = '\0';
 159         v[0]  = strtok(buf, FS);
 160         for (cont = 1; cont < FIELDS - 1; cont++)
 161                 v[cont] = strtok(NULL, FS);
 162 
 163         check_line(v, line_count);
 164 
 165         return (v);
 166 }
 167 
 168 static void
 169 parse_line(char **v, elem *e)
 170 {
 171         e->flag = 0;
 172         e->pkgs = NULL;
 173         e->arch = P_ISA;
 174         (void) strcpy(e->name, v[NAME]);
 175         e->perm = strtol(v[PERM], NULL, 8);
 176         (void) strcpy(e->owner, v[OWNR]);
 177         (void) strcpy(e->group, v[GRP]);
 178         e->inode = atoi(v[INO]);
 179         e->ref_cnt = atoi(v[LCNT]);
 180         e->file_type = *v[CODE];
 181         if ((v[MAJOR][0] == '-') && (v[MAJOR][1] == '\0'))
 182                 e->major = -1;
 183         else
 184                 e->major = atoi(v[MAJOR]);
 185 
 186         if ((v[MINOR][0] == '-') && (v[MINOR][1] == '\0'))
 187                 e->minor = -1;
 188         else
 189                 e->minor = atoi(v[MINOR]);
 190 
 191         if ((v[SYM][0] == '-') && (v[SYM][1] == '\0'))
 192                 e->symsrc = NULL;
 193         else {
 194                 e->symsrc = malloc(strlen(v[SYM]) + 1);
 195                 (void) strcpy(e->symsrc, v[SYM]);
 196                         if (e->file_type != SYM_LINK_T)
 197 #if defined(__sparc)
 198                         if (strncmp(e->symsrc, "sun4/", 5) == 0)
 199                                 e->arch = P_SUN4;
 200                         else if (strncmp(e->symsrc, "sun4c/", 6) == 0)
 201                                 e->arch = P_SUN4c;
 202                         else if (strncmp(e->symsrc, "sun4u/", 6) == 0)
 203                                 e->arch = P_SUN4u;
 204                         else if (strncmp(e->symsrc, "sun4d/", 6) == 0)
 205                                 e->arch = P_SUN4d;
 206                         else if (strncmp(e->symsrc, "sun4e/", 6) == 0)
 207                                 e->arch = P_SUN4e;
 208                         else if (strncmp(e->symsrc, "sun4m/", 6) == 0)
 209                                 e->arch = P_SUN4m;
 210                         else if (strncmp(e->symsrc, "sun4v/", 6) == 0)
 211                                 e->arch = P_SUN4v;
 212 #elif defined(__i386)
 213                         if (strncmp(e->symsrc, "i86pc/", 6) == 0)
 214                                 e->arch = P_I86PC;
 215 #elif defined(__ppc)
 216                         if (strncmp(e->symsrc, "prep/", 5) == 0)
 217                                 e->arch = P_PREP;
 218 #else
 219 #error "Unknown instruction set"
 220 #endif
 221                         else {
 222                                 (void) fprintf(stderr,
 223                                     "warning: Unknown relocation architecture "
 224                                     "for %s\n", e->symsrc);
 225                         }
 226 
 227         }
 228 }
 229 
 230 int
 231 read_in_protolist(const char *pname, elem_list *list, int verbose)
 232 {
 233         FILE    *proto_fp;
 234         char    *line_vec[FIELDS];
 235         int     count = 0;
 236         static elem     *e = NULL;
 237 
 238         list->type = PROTOLIST_LIST;
 239 
 240         if ((proto_fp = fopen(pname, "r")) == NULL) {
 241                 perror(pname);
 242                 exit(1);
 243         }
 244 
 245         if (verbose)
 246                 (void) printf("reading in proto_list(%s)...\n", pname);
 247 
 248         count = 0;
 249         while (get_line(proto_fp, line_vec)) {
 250                 if (!e)
 251                         e = (elem *)calloc(1, sizeof (elem));
 252 
 253                 parse_line(line_vec, e);
 254                 if (!find_elem(list, e, FOLLOW_LINK)) {
 255                         add_elem(list, e);
 256                         e = NULL;
 257                         count++;
 258                 }
 259         }
 260 
 261         if (verbose)
 262                 (void) printf("read in %d lines\n", count);
 263 
 264         (void) fclose(proto_fp);
 265 
 266         return (count);
 267 }