1 /*- 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)spec.c 5.13 (Berkeley) 07/21/90"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <pwd.h> 14 #include <grp.h> 15 #include <stdio.h> 16 #include <errno.h> 17 #include <ctype.h> 18 #include "mtree.h" 19 20 extern NODE *root; /* root of the tree */ 21 22 static int lineno; /* current spec line number */ 23 24 spec() 25 { 26 register NODE *centry, *last; 27 register char *p; 28 NODE ginfo, *emalloc(); 29 char buf[2048]; 30 31 bzero((void *)&ginfo, sizeof(ginfo)); 32 for (lineno = 1; fgets(buf, sizeof(buf), stdin); ++lineno) { 33 if (!(p = index(buf, '\n'))) { 34 (void)fprintf(stderr, 35 "mtree: line %d too long.\n", lineno); 36 exit(1); 37 } 38 *p = '\0'; 39 for (p = buf; *p && isspace(*p); ++p); 40 if (!*p || *p == '#') 41 continue; 42 43 /* grab file name, "$", "set", or "unset" */ 44 if (!(p = strtok(p, "\n\t "))) 45 specerr(); 46 47 if (p[0] == '/') 48 switch(p[1]) { 49 case 's': 50 if (strcmp(p + 1, "set")) 51 break; 52 set(&ginfo); 53 continue; 54 case 'u': 55 if (strncmp(p + 1, "unset")) 56 break; 57 unset(&ginfo); 58 continue; 59 } 60 61 if (index(p, '/')) { 62 (void)fprintf(stderr, 63 "mtree: file names may not contain slashes.\n"); 64 specerr(); 65 } 66 67 if (!strcmp(p, "..")) { 68 /* don't go up, if haven't gone down */ 69 if (!root) 70 noparent(); 71 if (last->type != F_DIR || last->flags & F_DONE) { 72 if (last == root) 73 noparent(); 74 last = last->parent; 75 } 76 last->flags |= F_DONE; 77 continue; 78 } 79 80 centry = emalloc(sizeof(NODE) + strlen(p)); 81 *centry = ginfo; 82 (void)strcpy(centry->name, p); 83 #define MAGIC "?*[" 84 if (strpbrk(p, MAGIC)) 85 centry->flags |= F_MAGIC; 86 set(centry); 87 88 if (!root) { 89 last = root = centry; 90 root->parent = root; 91 } else if (last->type == F_DIR && !(last->flags & F_DONE)) { 92 centry->parent = last; 93 last = last->child = centry; 94 } else { 95 centry->parent = last->parent; 96 centry->prev = last; 97 last = last->next = centry; 98 } 99 } 100 } 101 102 set(ip) 103 register NODE *ip; 104 { 105 register int type; 106 register char *kw, *val; 107 gid_t getgroup(); 108 uid_t getowner(); 109 long atol(), strtol(); 110 111 while (kw = strtok((char *)NULL, "= \t\n")) { 112 ip->flags |= type = key(kw); 113 val = strtok((char *)NULL, " \t\n"); 114 if (!val) 115 specerr(); 116 switch(type) { 117 case F_CKSUM: 118 ip->cksum = atol(val); 119 break; 120 case F_GROUP: 121 ip->st_gid = getgroup(val); 122 break; 123 case F_IGN: 124 /* just set flag bit */ 125 break; 126 case F_MODE: { 127 mode_t *m, *setmode(); 128 129 if (!(m = setmode(val))) { 130 (void)fprintf(stderr, 131 "mtree: invalid file mode %s.\n", val); 132 specerr(); 133 } 134 ip->st_mode = getmode(m, 0); 135 break; 136 } 137 case F_NLINK: 138 ip->st_nlink = atoi(val); 139 break; 140 case F_OWNER: 141 ip->st_uid = getowner(val); 142 break; 143 case F_SIZE: 144 ip->st_size = atol(val); 145 break; 146 case F_SLINK: 147 if (!(ip->slink = strdup(val))) 148 nomem(); 149 break; 150 case F_TIME: 151 ip->st_mtime = atol(val); 152 break; 153 case F_TYPE: 154 switch(*val) { 155 case 'b': 156 if (!strcmp(val, "block")) 157 ip->type = F_BLOCK; 158 break; 159 case 'c': 160 if (!strcmp(val, "char")) 161 ip->type = F_CHAR; 162 break; 163 case 'd': 164 if (!strcmp(val, "dir")) 165 ip->type = F_DIR; 166 break; 167 case 'f': 168 if (!strcmp(val, "file")) 169 ip->type = F_FILE; 170 if (!strcmp(val, "fifo")) 171 ip->type = F_FIFO; 172 break; 173 case 'l': 174 if (!strcmp(val, "link")) 175 ip->type = F_LINK; 176 break; 177 case 's': 178 if (!strcmp(val, "socket")) 179 ip->type = F_SOCK; 180 break; 181 default: 182 (void)fprintf(stderr, 183 "mtree: unknown file type %s.\n", val); 184 specerr(); 185 } 186 break; 187 } 188 } 189 } 190 191 unset(ip) 192 register NODE *ip; 193 { 194 register char *p; 195 196 while (p = strtok((char *)NULL, "\n\t ")) 197 ip->flags &= ~key(p); 198 } 199 200 key(p) 201 char *p; 202 { 203 switch(*p) { 204 case 'c': 205 if (!strcmp(p, "cksum")) 206 return(F_CKSUM); 207 break; 208 case 'g': 209 if (!strcmp(p, "group")) 210 return(F_GROUP); 211 break; 212 case 'i': 213 if (!strcmp(p, "ignore")) 214 return(F_IGN); 215 break; 216 case 'l': 217 if (!strcmp(p, "link")) 218 return(F_SLINK); 219 break; 220 case 'm': 221 if (!strcmp(p, "mode")) 222 return(F_MODE); 223 break; 224 case 'n': 225 if (!strcmp(p, "nlink")) 226 return(F_NLINK); 227 break; 228 case 'o': 229 if (!strcmp(p, "owner")) 230 return(F_OWNER); 231 break; 232 case 's': 233 if (!strcmp(p, "size")) 234 return(F_SIZE); 235 break; 236 case 't': 237 if (!strcmp(p, "type")) 238 return(F_TYPE); 239 if (!strcmp(p, "time")) 240 return(F_TIME); 241 break; 242 } 243 (void)fprintf(stderr, "mtree: unknown keyword %s.\n", p); 244 specerr(); 245 /* NOTREACHED */ 246 } 247 248 249 uid_t 250 getowner(p) 251 register char *p; 252 { 253 struct passwd *pw; 254 int val; 255 256 if (isdigit(*p)) { 257 if ((val = atoi(p)) >= 0) 258 return((uid_t)val); 259 (void)fprintf(stderr, "mtree: illegal uid value %s.\n", p); 260 } else if (pw = getpwnam(p)) 261 return(pw->pw_uid); 262 else 263 (void)fprintf(stderr, "mtree: unknown user %s.\n", p); 264 specerr(); 265 /* NOTREACHED */ 266 } 267 268 gid_t 269 getgroup(p) 270 register char *p; 271 { 272 struct group *gr; 273 int val; 274 275 if (isdigit(*p)) { 276 if ((val = atoi(p)) >= 0) 277 return((gid_t)val); 278 (void)fprintf(stderr, "mtree: illegal gid value %s.\n", p); 279 } else if (gr = getgrnam(p)) 280 return(gr->gr_gid); 281 else 282 (void)fprintf(stderr, "mtree: unknown group %s.\n", p); 283 specerr(); 284 /* NOTREACHED */ 285 } 286 287 noparent() 288 { 289 (void)fprintf(stderr, "mtree: no parent node.\n"); 290 specerr(); 291 } 292 293 specerr() 294 { 295 (void)fprintf(stderr, 296 "mtree: line %d of the specification is incorrect.\n", lineno); 297 exit(1); 298 } 299 300 NODE * 301 emalloc(size) 302 int size; 303 { 304 void *p; 305 306 /* NOSTRICT */ 307 if (!(p = malloc((u_int)size))) 308 nomem(); 309 bzero(p, size); 310 return((NODE *)p); 311 } 312 313 nomem() 314 { 315 (void)fprintf(stderr, "mtree: %s.\n", strerror(ENOMEM)); 316 exit(1); 317 } 318