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