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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1996, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3.8.1 */ 32 /* 33 * 34 * UNIX shell 35 * 36 */ 37 38 39 #include "defs.h" 40 #include <errno.h> 41 #include "sym.h" 42 #include "hash.h" 43 #include <sys/types.h> 44 #include <sys/times.h> 45 46 builtin(type, argc, argv, t) 47 int type, argc; 48 unsigned char **argv; 49 struct trenod *t; 50 { 51 short index = initio(t->treio, (type != SYSEXEC)); 52 unsigned char *a1 = argv[1]; 53 54 switch (type) 55 { 56 57 case SYSSUSP: 58 syssusp(argc,argv); 59 break; 60 61 case SYSSTOP: 62 sysstop(argc,argv); 63 break; 64 65 case SYSKILL: 66 syskill(argc,argv); 67 break; 68 69 case SYSFGBG: 70 sysfgbg(argc,argv); 71 break; 72 73 case SYSJOBS: 74 sysjobs(argc,argv); 75 break; 76 77 case SYSDOT: 78 if (a1) 79 { 80 register int f; 81 82 if ((f = pathopen(getpath(a1), a1)) < 0) 83 failed(a1, notfound); 84 else 85 execexp(0, f); 86 } 87 break; 88 89 case SYSTIMES: 90 { 91 struct tms tms; 92 93 times(&tms); 94 prt(tms.tms_cutime); 95 prc_buff(SPACE); 96 prt(tms.tms_cstime); 97 prc_buff(NL); 98 } 99 break; 100 101 case SYSEXIT: 102 if ( tried_to_exit++ || endjobs(JOB_STOPPED) ){ 103 flags |= forcexit; /* force exit */ 104 exitsh(a1 ? stoi(a1) : retval); 105 } 106 break; 107 108 case SYSNULL: 109 t->treio = 0; 110 break; 111 112 case SYSCONT: 113 if (loopcnt) 114 { 115 execbrk = breakcnt = 1; 116 if (a1) 117 breakcnt = stoi(a1); 118 if (breakcnt > loopcnt) 119 breakcnt = loopcnt; 120 else 121 breakcnt = -breakcnt; 122 } 123 break; 124 125 case SYSBREAK: 126 if (loopcnt) 127 { 128 execbrk = breakcnt = 1; 129 if (a1) 130 breakcnt = stoi(a1); 131 if (breakcnt > loopcnt) 132 breakcnt = loopcnt; 133 } 134 break; 135 136 case SYSTRAP: 137 systrap(argc,argv); 138 break; 139 140 case SYSEXEC: 141 argv++; 142 ioset = 0; 143 if (a1 == 0) { 144 setmode(0); 145 break; 146 } 147 /* FALLTHROUGH */ 148 149 #ifdef RES /* Research includes login as part of the shell */ 150 151 case SYSLOGIN: 152 if (!endjobs(JOB_STOPPED|JOB_RUNNING)) 153 break; 154 oldsigs(); 155 execa(argv, -1); 156 done(0); 157 #else 158 159 case SYSNEWGRP: 160 if (flags & rshflg) 161 failed(argv[0], restricted); 162 else if (!endjobs(JOB_STOPPED|JOB_RUNNING)) 163 break; 164 else 165 { 166 flags |= forcexit; /* bad exec will terminate shell */ 167 oldsigs(); 168 rmtemp(0); 169 rmfunctmp(); 170 #ifdef ACCT 171 doacct(); 172 #endif 173 execa(argv, -1); 174 done(0); 175 } 176 177 #endif 178 179 case SYSCD: 180 if (flags & rshflg) 181 failed(argv[0], restricted); 182 else if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval))) 183 { 184 unsigned char *cdpath; 185 unsigned char *dir; 186 int f; 187 188 if ((cdpath = cdpnod.namval) == 0 || 189 *a1 == '/' || 190 cf(a1, ".") == 0 || 191 cf(a1, "..") == 0 || 192 (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/'))) 193 cdpath = (unsigned char *)nullstr; 194 195 do 196 { 197 dir = cdpath; 198 cdpath = catpath(cdpath,a1); 199 } 200 while ((f = (chdir((const char *) curstak()) < 0)) && 201 cdpath); 202 203 if (f) { 204 switch(errno) { 205 case EMULTIHOP: 206 failed(a1, emultihop); 207 break; 208 case ENOTDIR: 209 failed(a1, enotdir); 210 break; 211 case ENOENT: 212 failed(a1, enoent); 213 break; 214 case EACCES: 215 failed(a1, eacces); 216 break; 217 case ENOLINK: 218 failed(a1, enolink); 219 break; 220 default: 221 failed(a1, baddir); 222 break; 223 } 224 } 225 else 226 { 227 cwd(curstak()); 228 if (cf(nullstr, dir) && 229 *dir != ':' && 230 any('/', curstak()) && 231 flags & prompt) 232 { 233 prs_buff(cwdget()); 234 prc_buff(NL); 235 } 236 } 237 zapcd(); 238 } 239 else 240 { 241 if (a1) 242 error(nulldir); 243 else 244 error(nohome); 245 } 246 247 break; 248 249 case SYSSHFT: 250 { 251 int places; 252 253 places = a1 ? stoi(a1) : 1; 254 255 if ((dolc -= places) < 0) 256 { 257 dolc = 0; 258 error(badshift); 259 } 260 else 261 dolv += places; 262 } 263 264 break; 265 266 case SYSWAIT: 267 syswait(argc,argv); 268 break; 269 270 case SYSREAD: 271 if(argc < 2) 272 failed(argv[0],mssgargn); 273 rwait = 1; 274 exitval = readvar(&argv[1]); 275 rwait = 0; 276 break; 277 278 case SYSSET: 279 if (a1) 280 { 281 int cnt; 282 283 cnt = options(argc, argv); 284 if (cnt > 1) 285 setargs(argv + argc - cnt); 286 } 287 else if (comptr(t)->comset == 0) 288 { 289 /* 290 * scan name chain and print 291 */ 292 namscan(printnam); 293 } 294 break; 295 296 case SYSRDONLY: 297 exitval = 0; 298 if (a1) 299 { 300 while (*++argv) 301 attrib(lookup(*argv), N_RDONLY); 302 } 303 else 304 namscan(printro); 305 306 break; 307 308 case SYSXPORT: 309 { 310 struct namnod *n; 311 312 exitval = 0; 313 if (a1) 314 { 315 while (*++argv) 316 { 317 n = lookup(*argv); 318 if (n->namflg & N_FUNCTN) 319 error(badexport); 320 else 321 attrib(n, N_EXPORT); 322 } 323 } 324 else 325 namscan(printexp); 326 } 327 break; 328 329 case SYSEVAL: 330 if (a1) 331 execexp(a1, &argv[2]); 332 break; 333 334 #ifndef RES 335 case SYSULIMIT: 336 sysulimit(argc, argv); 337 break; 338 339 case SYSUMASK: 340 if (a1) 341 { 342 int c; 343 mode_t i; 344 345 i = 0; 346 while ((c = *a1++) >= '0' && c <= '7') 347 i = (i << 3) + c - '0'; 348 umask(i); 349 } 350 else 351 { 352 mode_t i; 353 int j; 354 355 umask(i = umask(0)); 356 prc_buff('0'); 357 for (j = 6; j >= 0; j -= 3) 358 prc_buff(((i >> j) & 07) +'0'); 359 prc_buff(NL); 360 } 361 break; 362 363 #endif 364 365 case SYSTST: 366 exitval = test(argc, argv); 367 break; 368 369 case SYSECHO: 370 exitval = echo(argc, argv); 371 break; 372 373 case SYSHASH: 374 exitval = 0; 375 376 if (a1) 377 { 378 if (a1[0] == '-') 379 { 380 if (a1[1] == 'r') 381 zaphash(); 382 else 383 error(badopt); 384 } 385 else 386 { 387 while (*++argv) 388 { 389 if (hashtype(hash_cmd(*argv)) == NOTFOUND) 390 failed(*argv, notfound); 391 } 392 } 393 } 394 else 395 hashpr(); 396 397 break; 398 399 case SYSPWD: 400 { 401 exitval = 0; 402 cwdprint(); 403 } 404 break; 405 406 case SYSRETURN: 407 if (funcnt == 0) 408 error(badreturn); 409 410 execbrk = 1; 411 exitval = (a1 ? stoi(a1) : retval); 412 break; 413 414 case SYSTYPE: 415 exitval = 0; 416 if (a1) 417 { 418 /* return success only if all names are found */ 419 while (*++argv) 420 exitval |= what_is_path(*argv); 421 } 422 break; 423 424 case SYSUNS: 425 exitval = 0; 426 if (a1) 427 { 428 while (*++argv) 429 unset_name(*argv); 430 } 431 break; 432 433 case SYSGETOPT: { 434 int getoptval; 435 struct namnod *n; 436 extern unsigned char numbuf[]; 437 unsigned char *varnam = argv[2]; 438 unsigned char c[2]; 439 if(argc < 3) { 440 failure(argv[0],mssgargn); 441 break; 442 } 443 exitval = 0; 444 n = lookup("OPTIND"); 445 optind = stoi(n->namval); 446 if(argc > 3) { 447 argv[2] = dolv[0]; 448 getoptval = getopt(argc-2, (char **)&argv[2], (char *)argv[1]); 449 } 450 else 451 getoptval = getopt(dolc+1, (char **)dolv, (char *)argv[1]); 452 if(getoptval == -1) { 453 itos(optind); 454 assign(n, numbuf); 455 n = lookup(varnam); 456 assign(n, nullstr); 457 exitval = 1; 458 break; 459 } 460 argv[2] = varnam; 461 itos(optind); 462 assign(n, numbuf); 463 c[0] = getoptval; 464 c[1] = 0; 465 n = lookup(varnam); 466 assign(n, c); 467 n = lookup("OPTARG"); 468 assign(n, optarg); 469 } 470 break; 471 472 default: 473 prs_buff("unknown builtin\n"); 474 } 475 476 477 flushb(); 478 restore(index); 479 chktrap(); 480 } 481