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