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